diff --git a/commands/run.go b/commands/run.go index 5837d630..eed7320d 100644 --- a/commands/run.go +++ b/commands/run.go @@ -2,80 +2,47 @@ package commands import ( "bufio" + "context" "errors" "fmt" + "io" "os" "strings" + "github.com/charmbracelet/bubbles/textinput" + tea "github.com/charmbracelet/bubbletea" "github.com/docker/model-cli/commands/completion" "github.com/docker/model-cli/desktop" + "github.com/docker/model-cli/pkg/history" "github.com/spf13/cobra" + "golang.design/x/clipboard" + "golang.org/x/term" ) -// readMultilineInput reads input from stdin, supporting both single-line and multiline input. -// For multiline input, it detects triple-quoted strings and shows continuation prompts. -func readMultilineInput(cmd *cobra.Command, scanner *bufio.Scanner) (string, error) { - cmd.Print("> ") +const ( + helpCommands = `Available Commands: + /bye Exit + /copy Copy the last response to the clipboard + /?, /help Show this help + /? shortcuts Help for keyboard shortcuts - if !scanner.Scan() { - if err := scanner.Err(); err != nil { - return "", fmt.Errorf("error reading input: %v", err) - } - return "", fmt.Errorf("EOF") - } - - line := scanner.Text() - - // Check if this is the start of a multiline input (triple quotes) - tripleQuoteStart := "" - if strings.HasPrefix(line, `"""`) { - tripleQuoteStart = `"""` - } else if strings.HasPrefix(line, "'''") { - tripleQuoteStart = "'''" - } - - // If no triple quotes, return a single line - if tripleQuoteStart == "" { - return line, nil - } - - // Check if the triple quotes are closed on the same line - restOfLine := line[3:] - if strings.HasSuffix(restOfLine, tripleQuoteStart) && len(restOfLine) >= 3 { - // Complete multiline string on single line - return line, nil - } - - // Start collecting multiline input - var multilineInput strings.Builder - multilineInput.WriteString(line) - multilineInput.WriteString("\n") - - // Continue reading lines until we find the closing triple quotes - for { - cmd.Print("... ") +Use """ to begin and end a multi-line message.` - if !scanner.Scan() { - if err := scanner.Err(); err != nil { - return "", fmt.Errorf("error reading input: %v", err) - } - return "", fmt.Errorf("unclosed multiline input (EOF)") - } - - line = scanner.Text() - multilineInput.WriteString(line) - - // Check if this line contains the closing triple quotes - if strings.Contains(line, tripleQuoteStart) { - // Found closing quotes, we're done - break - } - - multilineInput.WriteString("\n") - } + helpShortcuts = `Available keyboard shortcuts: + Ctrl + a Move to the beginning of the line (Home) + Ctrl + e Move to the end of the line (End) + Alt + b Move left + Alt + f Move right + Ctrl + k Delete the sentence after the cursor + Ctrl + u Delete the sentence before the cursor + Ctrl + w Delete the word before the cursor + Ctrl + d Delete the character under the cursor` - return multilineInput.String(), nil -} + helpUnknownCommand = "Unknown command..." + helpNothingToCopy = "Nothing to copy..." + helpCopied = "Done! Response copied to clipboard." + placeholder = "Start chatting! (/bye to quit, /? for help)" +) func newRunCmd() *cobra.Command { var debug bool @@ -131,44 +98,97 @@ func newRunCmd() *cobra.Command { } } + // If the input is a pipe, read it + if stdinIsPiped() { + promptBytes, err := io.ReadAll(os.Stdin) + if err != nil { + return fmt.Errorf("failed to read stdin: %w", err) + } + // If we already had a prompt received as an argument, add the stdin contents to it + if prompt != "" { + prompt += "\n" + } + prompt += string(promptBytes) + } + if prompt != "" { - if err := desktopClient.Chat(backend, model, prompt, apiKey); err != nil { + if _, err := desktopClient.Chat(backend, model, prompt, apiKey); err != nil { return handleClientError(err, "Failed to generate a response") } cmd.Println() return nil } - scanner := bufio.NewScanner(os.Stdin) cmd.Println("Interactive chat mode started. Type '/bye' to exit.") + h, err := history.New(dockerCLI) + if err != nil { + return fmt.Errorf("unable to initialize history: %w", err) + } + + var lastCommand string + var lastResp []string for { - userInput, err := readMultilineInput(cmd, scanner) - if err != nil { - if err.Error() == "EOF" { - cmd.Println("\nChat session ended.") - break - } - return fmt.Errorf("Error reading input: %v", err) + var promptPlaceholder string + if lastCommand == "" { + promptPlaceholder = placeholder } + prompt := promptModel(h, promptPlaceholder) - if strings.ToLower(strings.TrimSpace(userInput)) == "/bye" { - cmd.Println("Chat session ended.") - break + p := tea.NewProgram(&prompt) + if _, err := p.Run(); err != nil { + return err } - if strings.TrimSpace(userInput) == "" { - continue - } + question := prompt.Text() + switch { + case question == "/bye": + return nil - if err := desktopClient.Chat(backend, model, userInput, apiKey); err != nil { - cmd.PrintErr(handleClientError(err, "Failed to generate a response")) + case strings.TrimSpace(question) == "": continue - } - cmd.Println() + case question == "/help" || question == "/?": + printHelp(helpCommands) + + case question == "/? shortcuts": + printHelp(helpShortcuts) + + case question == "/copy": + if len(lastResp) == 0 { + printHelp(helpNothingToCopy) + continue + } + if err := copyToClipboard(strings.Join(lastResp, "")); err != nil { + return err + } + printHelp(helpCopied) + + case strings.HasPrefix(question, "/"): + printHelp(helpUnknownCommand) + + case strings.HasPrefix(question, `"""`) || strings.HasPrefix(question, `'''`): + initialText := question + "\n" + restOfText, err := readMultilineString(cmd.Context(), os.Stdin, initialText) + if err != nil { + return err + } + question = restOfText + fallthrough + + default: + lastResp, err = desktopClient.Chat(backend, model, question, apiKey) + if err != nil { + cmd.PrintErr(handleClientError(err, "Failed to generate a response")) + return nil + } + if err := h.Append(question); err != nil { + return fmt.Errorf("unable to update history: %w", err) + } + lastCommand = question + cmd.Println() + } } - return nil }, ValidArgsFunction: completion.ModelNames(getDesktopClient, 1), } @@ -193,3 +213,201 @@ func newRunCmd() *cobra.Command { return c } + +func printHelp(status string) { + fmt.Print(status) + fmt.Println() + fmt.Println() +} + +type prompt struct { + text textinput.Model + history *history.History + historyIndex int +} + +func promptModel(h *history.History, placeholder string) prompt { + width, _, _ := term.GetSize(int(os.Stdout.Fd())) + + text := textinput.New() + text.Placeholder = placeholder + text.Prompt = "> " + text.Width = width - len(text.Prompt) - 1 + text.Cursor.Blink = false + text.ShowSuggestions = true + text.Focus() + + return prompt{ + text: text, + history: h, + historyIndex: -1, + } +} + +func (p *prompt) Init() tea.Cmd { + return textinput.Blink +} + +func (p *prompt) Finalize() { + p.text.Blur() + p.text.Placeholder = "" + p.text.SetSuggestions(nil) +} + +func (p *prompt) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + case tea.KeyMsg: + switch msg.Type { + case tea.KeyEnter: + p.Finalize() + return p, tea.Quit + case tea.KeyCtrlC, tea.KeyCtrlD: + p.text.SetValue("/bye") + p.Finalize() + return p, tea.Quit + case tea.KeyEsc: + p.text.SetValue("") + p.Finalize() + return p, tea.Quit + case tea.KeyUp: + if p.history != nil { + position := p.text.Position() + var text string + text, p.historyIndex, position = p.history.Previous(p.text.Value(), position, p.historyIndex) + p.text.SetValue(text) + p.text.SetCursor(position) + } + case tea.KeyDown: + if p.history != nil { + position := p.text.Position() + var text string + text, p.historyIndex, position = p.history.Next(p.text.Value(), position, p.historyIndex) + p.text.SetValue(text) + p.text.SetCursor(position) + } + } + case tea.WindowSizeMsg: + p.text.Width = msg.Width - 5 + return p, nil + default: + if current := p.text.Value(); current == "/" { + p.text.SetSuggestions([]string{"/help", "/bye", "/copy", "/?", "/? shortcuts"}) + } else if p.history != nil { + p.text.SetSuggestions(p.history.Suggestions(current)) + } else { + p.text.SetSuggestions(nil) + } + } + + var cmd tea.Cmd + p.text, cmd = p.text.Update(msg) + return p, cmd +} + +func (p *prompt) Text() string { + return p.text.Value() +} + +func (p *prompt) View() string { + return p.text.View() + "\n" +} + +func copyToClipboard(command string) error { + err := clipboard.Init() + if err != nil { + return nil + } + + clipboard.Write(clipboard.FmtText, []byte(command)) + return nil +} + +// readMultilineString reads a multiline string from r, starting with the initial text if provided. +// The text must start either with triple quotes (""") or single quotes (”'). readMultilineString +// will scan the input until a matching closing quote is found, or return an error if the input +// is not properly closed. It returns the string content without the surrounding quotes but +// preserving the original newlines and indentation. +func readMultilineString(ctx context.Context, r io.Reader, initialText string) (string, error) { + var question string + + // Start with the initial text if provided + if initialText != "" { + tr := strings.NewReader(initialText) + mr := io.MultiReader(tr, r) + r = mr + } + + br := bufio.NewReader(r) + + // Read the first 3 bytes + pd := make([]byte, 3) + if _, err := io.ReadFull(br, pd); err != nil { + return "", err + } + prefix := string(pd) + if prefix != `"""` && prefix != `'''` { + return "", fmt.Errorf("invalid multiline string prefix: %q", prefix) + } + + for { + line, err := readLine(ctx, br) + if err != nil { + if errors.Is(err, io.EOF) { + return "", fmt.Errorf("unclosed multiline input: %w", err) + } + return "", err + } + + question += line + if strings.TrimSpace(line) == prefix || strings.HasSuffix(strings.TrimSpace(line), prefix) { + break + } + fmt.Print("... ") + } + + // Find and remove the closing triple terminator + content := question + if idx := strings.LastIndex(content, prefix); idx >= 0 { + before := content[:idx] + after := content[idx+len(prefix):] + content = before + after + } + + return strings.TrimRight(content, "\n"), nil +} + +// readLine reads a single line from r. +func readLine(ctx context.Context, r *bufio.Reader) (string, error) { + lines := make(chan string) + errs := make(chan error) + + go func() { + defer close(lines) + defer close(errs) + + line, err := r.ReadString('\n') + if err != nil && line == "" { + errs <- err + } else { + lines <- line + } + }() + + select { + case <-ctx.Done(): + return "", ctx.Err() + case err := <-errs: + return "", err + case line := <-lines: + return line, nil + } +} + +// stdinIsPiped returns true if stdin is not a terminal (i.e., it is piped). +func stdinIsPiped() bool { + stat, err := os.Stdin.Stat() + if err != nil { + return false + } + return (stat.Mode() & os.ModeCharDevice) == 0 +} diff --git a/commands/run_test.go b/commands/run_test.go index f8674822..96c49225 100644 --- a/commands/run_test.go +++ b/commands/run_test.go @@ -2,10 +2,13 @@ package commands import ( "bufio" + "errors" + "io" "strings" "testing" - "github.com/spf13/cobra" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestReadMultilineInput(t *testing.T) { @@ -15,40 +18,34 @@ func TestReadMultilineInput(t *testing.T) { expected string wantErr bool }{ - { - name: "single line input", - input: "hello world", - expected: "hello world", - wantErr: false, - }, { name: "single line with triple quotes", input: `"""hello world"""`, - expected: `"""hello world"""`, + expected: `hello world`, wantErr: false, }, { name: "multiline input with double quotes", input: `"""tell -me -a -joke"""`, - expected: `"""tell -me -a -joke"""`, + me + a + joke"""`, + expected: `tell + me + a + joke`, wantErr: false, }, { name: "multiline input with single quotes", input: `'''tell -me -a -joke'''`, - expected: `'''tell -me -a -joke'''`, + me + a + joke'''`, + expected: `tell + me + a + joke`, wantErr: false, }, { @@ -61,27 +58,124 @@ joke'''`, name: "multiline with empty lines", input: `"""first line -third line"""`, - expected: `"""first line + third line"""`, + expected: `first line -third line"""`, + third line`, + wantErr: false, + }, + { + name: "multiline with spaces and closing quotes on new line", + input: `"""first line +second line +third line +"""`, + expected: `first line +second line +third line`, // this will intentionally trim the last newline + wantErr: false, + }, + { + name: "multiline with closing quotes and trailing spaces", + input: `"""first line +second line +third line """`, + expected: `first line +second line +third line `, + wantErr: false, + }, + { + name: "single quotes with spaces", + input: `'''foo bar'''`, + expected: `foo bar`, + wantErr: false, + }, + { + name: "triple quotes only", + input: `""""""`, + expected: "", + wantErr: false, + }, + { + name: "single quotes only", + input: `''''''`, + expected: "", + wantErr: false, + }, + { + name: "closing quotes in middle of line", + input: `"""foo"""bar"""`, + expected: `foo"""bar`, + wantErr: false, + }, + { + name: "no closing quotes", + input: `"""foo +bar +baz`, + expected: "", + wantErr: true, + }, + { + name: "invalid prefix", + input: `"foo bar"`, + expected: "", + wantErr: true, + }, + { + name: "prefix but no content", + input: `"""`, + expected: "", + wantErr: true, + }, + { + name: "prefix and newline only", + input: `""" +"""`, + expected: "", + wantErr: false, + }, + { + name: "multiline with only whitespace", + input: `""" + + """`, + expected: ` + + `, wantErr: false, }, } + // Strings can be read either as the first line followed by the rest of the text, + // or as a single block of text. Make sure we test both scenarios. + for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - // Create a mock command for testing - cmd := &cobra.Command{} + r := bufio.NewReader(strings.NewReader(tt.input)) + result, err := readMultilineString(t.Context(), r, "") - // Create a scanner from the test input - scanner := bufio.NewScanner(strings.NewReader(tt.input)) + if (err != nil) != tt.wantErr { + t.Errorf("readMultilineInput() error = %v, wantErr %v", err, tt.wantErr) + return + } - // Capture output to avoid printing during tests - var output strings.Builder - cmd.SetOut(&output) + if result != tt.expected { + t.Errorf("readMultilineInput() = %q, want %q", result, tt.expected) + } + }) - result, err := readMultilineInput(cmd, scanner) + t.Run(tt.name+"_chunked", func(t *testing.T) { + r := bufio.NewReader(strings.NewReader(tt.input)) + firstLine, err := r.ReadString('\n') // Simulate reading the first line + if errors.Is(err, io.EOF) { + // Some test cases are single line, EOF is ok here + firstLine = tt.input + } else { + require.NoError(t, err) + } + result, err := readMultilineString(t.Context(), r, firstLine) if (err != nil) != tt.wantErr { t.Errorf("readMultilineInput() error = %v, wantErr %v", err, tt.wantErr) @@ -98,18 +192,12 @@ third line"""`, func TestReadMultilineInputUnclosed(t *testing.T) { // Test unclosed multiline input (should return error) input := `"""unclosed multiline` - cmd := &cobra.Command{} - var output strings.Builder - cmd.SetOut(&output) - - scanner := bufio.NewScanner(strings.NewReader(input)) - - _, err := readMultilineInput(cmd, scanner) + _, err := readMultilineString(t.Context(), strings.NewReader(input), "") if err == nil { - t.Error("readMultilineInput() should return error for unclosed multiline input") + t.Fatal("readMultilineInput() should return an error for unclosed multiline input") } - if !strings.Contains(err.Error(), "unclosed multiline input") { - t.Errorf("readMultilineInput() error should mention unclosed multiline input, got: %v", err) - } + assert.Contains(t, err.Error(), "unclosed multiline input", "error should mention unclosed multiline input") + // Error should also be io.EOF + assert.True(t, errors.Is(err, io.EOF), "error should be io.EOF") } diff --git a/desktop/desktop.go b/desktop/desktop.go index 3fff3bfd..96ce84a8 100644 --- a/desktop/desktop.go +++ b/desktop/desktop.go @@ -371,7 +371,9 @@ const ( chatPrinterReasoning ) -func (c *Client) Chat(backend, model, prompt, apiKey string) error { +// Chat sends a chat message to the model, prints the response to the standard output +// and then returns it as a slice of the received chunks. +func (c *Client) Chat(backend, model, prompt, apiKey string) ([]string, error) { model = normalizeHuggingFaceModelName(model) if !strings.Contains(strings.Trim(model, "/"), "/") { // Do an extra API call to check if the model parameter isn't a model ID. @@ -393,7 +395,7 @@ func (c *Client) Chat(backend, model, prompt, apiKey string) error { jsonData, err := json.Marshal(reqBody) if err != nil { - return fmt.Errorf("error marshaling request: %w", err) + return nil, fmt.Errorf("error marshaling request: %w", err) } var completionsPath string @@ -411,18 +413,19 @@ func (c *Client) Chat(backend, model, prompt, apiKey string) error { apiKey, ) if err != nil { - return c.handleQueryError(err, completionsPath) + return nil, c.handleQueryError(err, completionsPath) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) - return fmt.Errorf("error response: status=%d body=%s", resp.StatusCode, body) + return nil, fmt.Errorf("error response: status=%d body=%s", resp.StatusCode, body) } printerState := chatPrinterNone reasoningFmt := color.New(color.FgWhite).Add(color.Italic) scanner := bufio.NewScanner(resp.Body) + var chunks []string for scanner.Scan() { line := scanner.Text() if line == "" { @@ -441,7 +444,7 @@ func (c *Client) Chat(backend, model, prompt, apiKey string) error { var streamResp OpenAIChatResponse if err := json.Unmarshal([]byte(data), &streamResp); err != nil { - return fmt.Errorf("error parsing stream response: %w", err) + return nil, fmt.Errorf("error parsing stream response: %w", err) } if len(streamResp.Choices) > 0 { @@ -463,15 +466,16 @@ func (c *Client) Chat(backend, model, prompt, apiKey string) error { } printerState = chatPrinterContent fmt.Print(chunk) + chunks = append(chunks, chunk) } } } if err := scanner.Err(); err != nil { - return fmt.Errorf("error reading response stream: %w", err) + return nil, fmt.Errorf("error reading response stream: %w", err) } - return nil + return chunks, nil } func (c *Client) Remove(models []string, force bool) (string, error) { diff --git a/desktop/desktop_test.go b/desktop/desktop_test.go index db0f68ef..b0e85377 100644 --- a/desktop/desktop_test.go +++ b/desktop/desktop_test.go @@ -63,8 +63,9 @@ func TestChatHuggingFaceModel(t *testing.T) { Body: io.NopCloser(bytes.NewBufferString("data: {\"choices\":[{\"delta\":{\"content\":\"Hello there!\"}}]}\n")), }, nil) - err := client.Chat("", modelName, prompt, "") + resp, err := client.Chat("", modelName, prompt, "") assert.NoError(t, err) + assert.Equal(t, []string{"Hello there!"}, resp) } func TestInspectHuggingFaceModel(t *testing.T) { diff --git a/go.mod b/go.mod index 5259d6bf..520c5390 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,8 @@ go 1.24 toolchain go1.24.4 require ( + github.com/charmbracelet/bubbles v0.21.0 + github.com/charmbracelet/bubbletea v1.3.6 github.com/containerd/errdefs v1.0.0 github.com/docker/cli v28.3.0+incompatible github.com/docker/cli-docs-tool v0.10.0 @@ -24,14 +26,23 @@ require ( github.com/stretchr/testify v1.10.0 go.opentelemetry.io/otel v1.37.0 go.uber.org/mock v0.5.0 + golang.design/x/clipboard v0.7.1 golang.org/x/sync v0.15.0 + golang.org/x/term v0.32.0 ) require ( github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/StackExchange/wmi v1.2.1 // indirect + github.com/atotto/clipboard v0.1.4 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect + github.com/charmbracelet/lipgloss v1.1.0 // indirect + github.com/charmbracelet/x/ansi v0.9.3 // indirect + github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect github.com/containerd/containerd/v2 v2.1.3 // indirect github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/log v0.1.0 // indirect @@ -46,6 +57,7 @@ require ( github.com/docker/docker-credential-helpers v0.9.3 // indirect github.com/elastic/go-sysinfo v1.15.3 // indirect github.com/elastic/go-windows v1.0.2 // indirect + github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect github.com/fvbommel/sortorder v1.1.0 // indirect @@ -63,7 +75,9 @@ require ( github.com/jaypipes/pcidb v1.0.1 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/compress v1.18.0 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect github.com/mattn/go-shellwords v1.0.12 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect @@ -75,6 +89,9 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/morikuni/aec v1.0.0 // indirect + github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect + github.com/muesli/cancelreader v0.2.2 // indirect + github.com/muesli/termenv v0.16.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.1 // indirect @@ -89,6 +106,7 @@ require ( github.com/smallnest/ringbuffer v0.0.0-20241116012123-461381446e3d // indirect github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a // indirect github.com/vbatts/tar-split v0.12.1 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect @@ -101,6 +119,9 @@ require ( go.opentelemetry.io/proto/otlp v1.5.0 // indirect golang.org/x/crypto v0.39.0 // indirect golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect + golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 // indirect + golang.org/x/image v0.28.0 // indirect + golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f // indirect golang.org/x/mod v0.25.0 // indirect golang.org/x/net v0.41.0 // indirect golang.org/x/sys v0.33.0 // indirect diff --git a/go.sum b/go.sum index 997998e1..f3634e97 100644 --- a/go.sum +++ b/go.sum @@ -10,6 +10,10 @@ github.com/Microsoft/hcsshim v0.13.0/go.mod h1:9KWJ/8DgU+QzYGupX4tzMhRQE8h6w90lH github.com/Shopify/logrus-bugsnag v0.0.0-20170309145241-6dbc35f2c30d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= +github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= @@ -22,6 +26,20 @@ github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK3 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= +github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= +github.com/charmbracelet/bubbletea v1.3.6 h1:VkHIxPJQeDt0aFJIsVxw8BQdh/F/L2KKZGsK6et5taU= +github.com/charmbracelet/bubbletea v1.3.6/go.mod h1:oQD9VCRQFF8KplacJLo28/jofOI2ToOfGYeFgBBxHOc= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= +github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= +github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= +github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0= +github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= +github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/cloudflare/cfssl v0.0.0-20180223231731-4e2dcbde5004/go.mod h1:yMWuSON2oQp+43nFtAV/uvKQIFpSPerB57DCt9t8sSA= github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJHo6Bzo= github.com/containerd/cgroups/v3 v3.0.5/go.mod h1:SA5DLYnXO8pTGYiAHXz94qvLQTKfVM5GEVisn4jpins= @@ -87,6 +105,8 @@ github.com/elastic/go-sysinfo v1.15.3 h1:W+RnmhKFkqPTCRoFq2VCTmsT4p/fwpo+3gKNQsn github.com/elastic/go-sysinfo v1.15.3/go.mod h1:K/cNrqYTDrSoMh2oDkYEMS2+a72GRxMvNP+GC+vRIlo= github.com/elastic/go-windows v1.0.2 h1:yoLLsAsV5cfg9FLhZ9EXZ2n2sQFKeDYrHenkcivY4vI= github.com/elastic/go-windows v1.0.2/go.mod h1:bGcDpBzXgYSqM0Gx3DM4+UxFj300SZLixie9u9ixLM8= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= +github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/erikstmartin/go-testdb v0.0.0-20160219214506-8d10e4a1bae5/go.mod h1:a2zkGnVExMxdzMo3M0Hi/3sEU+cWnZpSni0O6/Yb/P0= github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= @@ -162,12 +182,16 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/magiconair/properties v1.5.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= +github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -202,6 +226,12 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= +github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= +github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= +github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= +github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= @@ -273,6 +303,8 @@ github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a h1:tlJ github.com/theupdateframework/notary v0.7.1-0.20210315103452-bf96a202a09a/go.mod h1:Y94A6rPp2OwNfP/7vmf8O2xx2IykP8pPXQ1DLouGnEw= github.com/vbatts/tar-split v0.12.1 h1:CqKoORW7BUWBe7UL/iqTVvkTBOF8UvOMKOIZykxnnbo= github.com/vbatts/tar-split v0.12.1/go.mod h1:eF6B6i6ftWQcDqEn3/iGFRFRo8cBIMSJVOpnNdfTMFA= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= @@ -305,6 +337,8 @@ go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= +golang.design/x/clipboard v0.7.1 h1:OEG3CmcYRBNnRwpDp7+uWLiZi3hrMRJpE9JkkkYtz2c= +golang.design/x/clipboard v0.7.1/go.mod h1:i5SiIqj0wLFw9P/1D7vfILFK0KHMk7ydE72HRrUIgkg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -315,6 +349,12 @@ golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 h1:yqrTHse8TCMW1M1ZCP+VAR/l0kKxwaAIqN/il7x4voA= golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8/go.mod h1:tujkw807nyEEAamNbDrEGzRav+ilXA7PCRAd6xsmwiU= +golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 h1:Wdx0vgH5Wgsw+lF//LJKmWOJBLWX6nprsMqnf99rYDE= +golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476/go.mod h1:ygj7T6vSGhhm/9yTpOQQNvuAUFziTH7RUiH74EoE2C8= +golang.org/x/image v0.28.0 h1:gdem5JW1OLS4FbkWgLO+7ZeFzYtL3xClb97GaUzYMFE= +golang.org/x/image v0.28.0/go.mod h1:GUJYXtnGKEUgggyzh+Vxt+AviiCcyiwpsl8iQ8MvwGY= +golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f h1:/n+PL2HlfqeSiDCuhdBbRNlGS/g2fM4OHufalHaTVG8= +golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f/go.mod h1:ESkJ836Z6LpG6mTVAhA48LpfW/8fNR0ifStlH2axyfg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= @@ -341,6 +381,7 @@ golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/history/history.go b/pkg/history/history.go new file mode 100644 index 00000000..6e629a0a --- /dev/null +++ b/pkg/history/history.go @@ -0,0 +1,111 @@ +// Package history provides a command history stored inside the Docker CLI configuration. +package history + +import ( + "os" + "path/filepath" + "strings" + + "github.com/docker/cli/cli/command" +) + +const MaxHistoryLength = 100 + +// History manages the command history for the CLI. Only single-line commands are stored. +// Multi-line commands are silently ignored for the time being. +type History struct { + configPath string + history []string +} + +// New creates a new History instance and loads all previous history, if it exists. +func New(cli *command.DockerCli) (*History, error) { + dirname := filepath.Dir(cli.ConfigFile().Filename) + p := filepath.Join(dirname, "model-cli", "history.txt") + h := &History{configPath: p} + if err := h.load(); err != nil { + return nil, err + } + return h, nil +} + +func (h *History) load() error { + data, err := os.ReadFile(h.configPath) + if err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + + var history []string + seen := make(map[string]bool) + for line := range strings.SplitSeq(strings.TrimSuffix(string(data), "\n"), "\n") { + if !seen[line] { + history = append(history, line) + seen[line] = true + } + } + h.history = history + return nil +} + +// Append adds a new entry to the history and updates the history file. +func (h *History) Append(question string) error { + if strings.Contains(question, "\n") { + return nil + } + + h.history = append(h.history, question) + if len(h.history) > MaxHistoryLength { + h.history = h.history[len(h.history)-MaxHistoryLength:] + } + buf := strings.Join(h.history, "\n") + + if err := os.MkdirAll(filepath.Dir(h.configPath), 0700); err != nil { + return err + } + + if err := os.WriteFile(h.configPath+".tmp", []byte(buf), 0600); err != nil { + return err + } + _ = os.Remove(h.configPath) + return os.Rename(h.configPath+".tmp", h.configPath) +} + +// Suggestions returns a list of suggested inputs based on the current input. +func (h *History) Suggestions(text string) []string { + var suggestions []string + + text = strings.ToLower(text) + for _, line := range h.history { + if strings.HasPrefix(strings.ToLower(line), text) { + suggestions = append(suggestions, line) + } + } + + return suggestions +} + +// Previous returns the previous input in the history based on the current, cursor position and history index. +// It returns the new text, history index and cursor position (which might be equal to the input). +func (h *History) Previous(text string, cursorPosition int, historyIndex int) (newText string, newHistoryIndex int, newCursorPosition int) { + if historyIndex == -1 && len(h.history) > 0 { + historyIndex = len(h.history) + } + if historyIndex > 0 && len(h.history) > 0 { + newIndex := historyIndex - 1 + return h.history[newIndex], newIndex, len(h.history[newIndex]) + } + return text, historyIndex, cursorPosition +} + +// Next returns the next input in the history based on the current, cursor position and history index. +// It returns the new text, history index and cursor position (which might be equal to the input). +func (h *History) Next(text string, cursorPosition int, historyIndex int) (newText string, newHistoryIndex int, newCursorPosition int) { + if historyIndex < len(h.history)-1 && historyIndex >= 0 { + newIndex := historyIndex + 1 + return h.history[newIndex], newIndex, len(h.history[newIndex]) + } + return text, historyIndex, cursorPosition +} diff --git a/vendor/github.com/atotto/clipboard/.travis.yml b/vendor/github.com/atotto/clipboard/.travis.yml new file mode 100644 index 00000000..23f21d83 --- /dev/null +++ b/vendor/github.com/atotto/clipboard/.travis.yml @@ -0,0 +1,22 @@ +language: go + +os: + - linux + - osx + - windows + +go: + - go1.13.x + - go1.x + +services: + - xvfb + +before_install: + - export DISPLAY=:99.0 + +script: + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xsel; fi + - go test -v . + - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install xclip; fi + - go test -v . diff --git a/vendor/github.com/atotto/clipboard/LICENSE b/vendor/github.com/atotto/clipboard/LICENSE new file mode 100644 index 00000000..dee3257b --- /dev/null +++ b/vendor/github.com/atotto/clipboard/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013 Ato Araki. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of @atotto. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/atotto/clipboard/README.md b/vendor/github.com/atotto/clipboard/README.md new file mode 100644 index 00000000..41fdd57b --- /dev/null +++ b/vendor/github.com/atotto/clipboard/README.md @@ -0,0 +1,48 @@ +[![Build Status](https://travis-ci.org/atotto/clipboard.svg?branch=master)](https://travis-ci.org/atotto/clipboard) + +[![GoDoc](https://godoc.org/github.com/atotto/clipboard?status.svg)](http://godoc.org/github.com/atotto/clipboard) + +# Clipboard for Go + +Provide copying and pasting to the Clipboard for Go. + +Build: + + $ go get github.com/atotto/clipboard + +Platforms: + +* OSX +* Windows 7 (probably work on other Windows) +* Linux, Unix (requires 'xclip' or 'xsel' command to be installed) + + +Document: + +* http://godoc.org/github.com/atotto/clipboard + +Notes: + +* Text string only +* UTF-8 text encoding only (no conversion) + +TODO: + +* Clipboard watcher(?) + +## Commands: + +paste shell command: + + $ go get github.com/atotto/clipboard/cmd/gopaste + $ # example: + $ gopaste > document.txt + +copy shell command: + + $ go get github.com/atotto/clipboard/cmd/gocopy + $ # example: + $ cat document.txt | gocopy + + + diff --git a/vendor/github.com/atotto/clipboard/clipboard.go b/vendor/github.com/atotto/clipboard/clipboard.go new file mode 100644 index 00000000..d7907d3a --- /dev/null +++ b/vendor/github.com/atotto/clipboard/clipboard.go @@ -0,0 +1,20 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package clipboard read/write on clipboard +package clipboard + +// ReadAll read string from clipboard +func ReadAll() (string, error) { + return readAll() +} + +// WriteAll write string to clipboard +func WriteAll(text string) error { + return writeAll(text) +} + +// Unsupported might be set true during clipboard init, to help callers decide +// whether or not to offer clipboard options. +var Unsupported bool diff --git a/vendor/github.com/atotto/clipboard/clipboard_darwin.go b/vendor/github.com/atotto/clipboard/clipboard_darwin.go new file mode 100644 index 00000000..6f33078d --- /dev/null +++ b/vendor/github.com/atotto/clipboard/clipboard_darwin.go @@ -0,0 +1,52 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin + +package clipboard + +import ( + "os/exec" +) + +var ( + pasteCmdArgs = "pbpaste" + copyCmdArgs = "pbcopy" +) + +func getPasteCommand() *exec.Cmd { + return exec.Command(pasteCmdArgs) +} + +func getCopyCommand() *exec.Cmd { + return exec.Command(copyCmdArgs) +} + +func readAll() (string, error) { + pasteCmd := getPasteCommand() + out, err := pasteCmd.Output() + if err != nil { + return "", err + } + return string(out), nil +} + +func writeAll(text string) error { + copyCmd := getCopyCommand() + in, err := copyCmd.StdinPipe() + if err != nil { + return err + } + + if err := copyCmd.Start(); err != nil { + return err + } + if _, err := in.Write([]byte(text)); err != nil { + return err + } + if err := in.Close(); err != nil { + return err + } + return copyCmd.Wait() +} diff --git a/vendor/github.com/atotto/clipboard/clipboard_plan9.go b/vendor/github.com/atotto/clipboard/clipboard_plan9.go new file mode 100644 index 00000000..9d2fef4e --- /dev/null +++ b/vendor/github.com/atotto/clipboard/clipboard_plan9.go @@ -0,0 +1,42 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build plan9 + +package clipboard + +import ( + "os" + "io/ioutil" +) + +func readAll() (string, error) { + f, err := os.Open("/dev/snarf") + if err != nil { + return "", err + } + defer f.Close() + + str, err := ioutil.ReadAll(f) + if err != nil { + return "", err + } + + return string(str), nil +} + +func writeAll(text string) error { + f, err := os.OpenFile("/dev/snarf", os.O_WRONLY, 0666) + if err != nil { + return err + } + defer f.Close() + + _, err = f.Write([]byte(text)) + if err != nil { + return err + } + + return nil +} diff --git a/vendor/github.com/atotto/clipboard/clipboard_unix.go b/vendor/github.com/atotto/clipboard/clipboard_unix.go new file mode 100644 index 00000000..d9f6a561 --- /dev/null +++ b/vendor/github.com/atotto/clipboard/clipboard_unix.go @@ -0,0 +1,149 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build freebsd linux netbsd openbsd solaris dragonfly + +package clipboard + +import ( + "errors" + "os" + "os/exec" +) + +const ( + xsel = "xsel" + xclip = "xclip" + powershellExe = "powershell.exe" + clipExe = "clip.exe" + wlcopy = "wl-copy" + wlpaste = "wl-paste" + termuxClipboardGet = "termux-clipboard-get" + termuxClipboardSet = "termux-clipboard-set" +) + +var ( + Primary bool + trimDos bool + + pasteCmdArgs []string + copyCmdArgs []string + + xselPasteArgs = []string{xsel, "--output", "--clipboard"} + xselCopyArgs = []string{xsel, "--input", "--clipboard"} + + xclipPasteArgs = []string{xclip, "-out", "-selection", "clipboard"} + xclipCopyArgs = []string{xclip, "-in", "-selection", "clipboard"} + + powershellExePasteArgs = []string{powershellExe, "Get-Clipboard"} + clipExeCopyArgs = []string{clipExe} + + wlpasteArgs = []string{wlpaste, "--no-newline"} + wlcopyArgs = []string{wlcopy} + + termuxPasteArgs = []string{termuxClipboardGet} + termuxCopyArgs = []string{termuxClipboardSet} + + missingCommands = errors.New("No clipboard utilities available. Please install xsel, xclip, wl-clipboard or Termux:API add-on for termux-clipboard-get/set.") +) + +func init() { + if os.Getenv("WAYLAND_DISPLAY") != "" { + pasteCmdArgs = wlpasteArgs + copyCmdArgs = wlcopyArgs + + if _, err := exec.LookPath(wlcopy); err == nil { + if _, err := exec.LookPath(wlpaste); err == nil { + return + } + } + } + + pasteCmdArgs = xclipPasteArgs + copyCmdArgs = xclipCopyArgs + + if _, err := exec.LookPath(xclip); err == nil { + return + } + + pasteCmdArgs = xselPasteArgs + copyCmdArgs = xselCopyArgs + + if _, err := exec.LookPath(xsel); err == nil { + return + } + + pasteCmdArgs = termuxPasteArgs + copyCmdArgs = termuxCopyArgs + + if _, err := exec.LookPath(termuxClipboardSet); err == nil { + if _, err := exec.LookPath(termuxClipboardGet); err == nil { + return + } + } + + pasteCmdArgs = powershellExePasteArgs + copyCmdArgs = clipExeCopyArgs + trimDos = true + + if _, err := exec.LookPath(clipExe); err == nil { + if _, err := exec.LookPath(powershellExe); err == nil { + return + } + } + + Unsupported = true +} + +func getPasteCommand() *exec.Cmd { + if Primary { + pasteCmdArgs = pasteCmdArgs[:1] + } + return exec.Command(pasteCmdArgs[0], pasteCmdArgs[1:]...) +} + +func getCopyCommand() *exec.Cmd { + if Primary { + copyCmdArgs = copyCmdArgs[:1] + } + return exec.Command(copyCmdArgs[0], copyCmdArgs[1:]...) +} + +func readAll() (string, error) { + if Unsupported { + return "", missingCommands + } + pasteCmd := getPasteCommand() + out, err := pasteCmd.Output() + if err != nil { + return "", err + } + result := string(out) + if trimDos && len(result) > 1 { + result = result[:len(result)-2] + } + return result, nil +} + +func writeAll(text string) error { + if Unsupported { + return missingCommands + } + copyCmd := getCopyCommand() + in, err := copyCmd.StdinPipe() + if err != nil { + return err + } + + if err := copyCmd.Start(); err != nil { + return err + } + if _, err := in.Write([]byte(text)); err != nil { + return err + } + if err := in.Close(); err != nil { + return err + } + return copyCmd.Wait() +} diff --git a/vendor/github.com/atotto/clipboard/clipboard_windows.go b/vendor/github.com/atotto/clipboard/clipboard_windows.go new file mode 100644 index 00000000..253bb932 --- /dev/null +++ b/vendor/github.com/atotto/clipboard/clipboard_windows.go @@ -0,0 +1,157 @@ +// Copyright 2013 @atotto. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build windows + +package clipboard + +import ( + "runtime" + "syscall" + "time" + "unsafe" +) + +const ( + cfUnicodetext = 13 + gmemMoveable = 0x0002 +) + +var ( + user32 = syscall.MustLoadDLL("user32") + isClipboardFormatAvailable = user32.MustFindProc("IsClipboardFormatAvailable") + openClipboard = user32.MustFindProc("OpenClipboard") + closeClipboard = user32.MustFindProc("CloseClipboard") + emptyClipboard = user32.MustFindProc("EmptyClipboard") + getClipboardData = user32.MustFindProc("GetClipboardData") + setClipboardData = user32.MustFindProc("SetClipboardData") + + kernel32 = syscall.NewLazyDLL("kernel32") + globalAlloc = kernel32.NewProc("GlobalAlloc") + globalFree = kernel32.NewProc("GlobalFree") + globalLock = kernel32.NewProc("GlobalLock") + globalUnlock = kernel32.NewProc("GlobalUnlock") + lstrcpy = kernel32.NewProc("lstrcpyW") +) + +// waitOpenClipboard opens the clipboard, waiting for up to a second to do so. +func waitOpenClipboard() error { + started := time.Now() + limit := started.Add(time.Second) + var r uintptr + var err error + for time.Now().Before(limit) { + r, _, err = openClipboard.Call(0) + if r != 0 { + return nil + } + time.Sleep(time.Millisecond) + } + return err +} + +func readAll() (string, error) { + // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). + // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + if formatAvailable, _, err := isClipboardFormatAvailable.Call(cfUnicodetext); formatAvailable == 0 { + return "", err + } + err := waitOpenClipboard() + if err != nil { + return "", err + } + + h, _, err := getClipboardData.Call(cfUnicodetext) + if h == 0 { + _, _, _ = closeClipboard.Call() + return "", err + } + + l, _, err := globalLock.Call(h) + if l == 0 { + _, _, _ = closeClipboard.Call() + return "", err + } + + text := syscall.UTF16ToString((*[1 << 20]uint16)(unsafe.Pointer(l))[:]) + + r, _, err := globalUnlock.Call(h) + if r == 0 { + _, _, _ = closeClipboard.Call() + return "", err + } + + closed, _, err := closeClipboard.Call() + if closed == 0 { + return "", err + } + return text, nil +} + +func writeAll(text string) error { + // LockOSThread ensure that the whole method will keep executing on the same thread from begin to end (it actually locks the goroutine thread attribution). + // Otherwise if the goroutine switch thread during execution (which is a common practice), the OpenClipboard and CloseClipboard will happen on two different threads, and it will result in a clipboard deadlock. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + err := waitOpenClipboard() + if err != nil { + return err + } + + r, _, err := emptyClipboard.Call(0) + if r == 0 { + _, _, _ = closeClipboard.Call() + return err + } + + data := syscall.StringToUTF16(text) + + // "If the hMem parameter identifies a memory object, the object must have + // been allocated using the function with the GMEM_MOVEABLE flag." + h, _, err := globalAlloc.Call(gmemMoveable, uintptr(len(data)*int(unsafe.Sizeof(data[0])))) + if h == 0 { + _, _, _ = closeClipboard.Call() + return err + } + defer func() { + if h != 0 { + globalFree.Call(h) + } + }() + + l, _, err := globalLock.Call(h) + if l == 0 { + _, _, _ = closeClipboard.Call() + return err + } + + r, _, err = lstrcpy.Call(l, uintptr(unsafe.Pointer(&data[0]))) + if r == 0 { + _, _, _ = closeClipboard.Call() + return err + } + + r, _, err = globalUnlock.Call(h) + if r == 0 { + if err.(syscall.Errno) != 0 { + _, _, _ = closeClipboard.Call() + return err + } + } + + r, _, err = setClipboardData.Call(cfUnicodetext, h) + if r == 0 { + _, _, _ = closeClipboard.Call() + return err + } + h = 0 // suppress deferred cleanup + closed, _, err := closeClipboard.Call() + if closed == 0 { + return err + } + return nil +} diff --git a/vendor/github.com/aymanbagabas/go-osc52/v2/LICENSE b/vendor/github.com/aymanbagabas/go-osc52/v2/LICENSE new file mode 100644 index 00000000..25cec1ed --- /dev/null +++ b/vendor/github.com/aymanbagabas/go-osc52/v2/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Ayman Bagabas + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/aymanbagabas/go-osc52/v2/README.md b/vendor/github.com/aymanbagabas/go-osc52/v2/README.md new file mode 100644 index 00000000..4de3a22d --- /dev/null +++ b/vendor/github.com/aymanbagabas/go-osc52/v2/README.md @@ -0,0 +1,83 @@ + +# go-osc52 + +

+ Latest Release + GoDoc +

+ +A Go library to work with the [ANSI OSC52](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands) terminal sequence. + +## Usage + +You can use this small library to construct an ANSI OSC52 sequence suitable for +your terminal. + + +### Example + +```go +import ( + "os" + "fmt" + + "github.com/aymanbagabas/go-osc52/v2" +) + +func main() { + s := "Hello World!" + + // Copy `s` to system clipboard + osc52.New(s).WriteTo(os.Stderr) + + // Copy `s` to primary clipboard (X11) + osc52.New(s).Primary().WriteTo(os.Stderr) + + // Query the clipboard + osc52.Query().WriteTo(os.Stderr) + + // Clear system clipboard + osc52.Clear().WriteTo(os.Stderr) + + // Use the fmt.Stringer interface to copy `s` to system clipboard + fmt.Fprint(os.Stderr, osc52.New(s)) + + // Or to primary clipboard + fmt.Fprint(os.Stderr, osc52.New(s).Primary()) +} +``` + +## SSH Example + +You can use this over SSH using [gliderlabs/ssh](https://github.com/gliderlabs/ssh) for instance: + +```go +var sshSession ssh.Session +seq := osc52.New("Hello awesome!") +// Check if term is screen or tmux +pty, _, _ := s.Pty() +if pty.Term == "screen" { + seq = seq.Screen() +} else if isTmux { + seq = seq.Tmux() +} +seq.WriteTo(sshSession.Stderr()) +``` + +## Tmux + +Make sure you have `set-clipboard on` in your config, otherwise, tmux won't +allow your application to access the clipboard [^1]. + +Using the tmux option, `osc52.TmuxMode` or `osc52.New(...).Tmux()`, wraps the +OSC52 sequence in a special tmux DCS sequence and pass it to the outer +terminal. This requires `allow-passthrough on` in your config. +`allow-passthrough` is no longer enabled by default +[since tmux 3.3a](https://github.com/tmux/tmux/issues/3218#issuecomment-1153089282) [^2]. + +[^1]: See [tmux clipboard](https://github.com/tmux/tmux/wiki/Clipboard) +[^2]: [What is allow-passthrough](https://github.com/tmux/tmux/wiki/FAQ#what-is-the-passthrough-escape-sequence-and-how-do-i-use-it) + +## Credits + +* [vim-oscyank](https://github.com/ojroques/vim-oscyank) this is heavily inspired by vim-oscyank. diff --git a/vendor/github.com/aymanbagabas/go-osc52/v2/osc52.go b/vendor/github.com/aymanbagabas/go-osc52/v2/osc52.go new file mode 100644 index 00000000..dc758d28 --- /dev/null +++ b/vendor/github.com/aymanbagabas/go-osc52/v2/osc52.go @@ -0,0 +1,305 @@ +// OSC52 is a terminal escape sequence that allows copying text to the clipboard. +// +// The sequence consists of the following: +// +// OSC 52 ; Pc ; Pd BEL +// +// Pc is the clipboard choice: +// +// c: clipboard +// p: primary +// q: secondary (not supported) +// s: select (not supported) +// 0-7: cut-buffers (not supported) +// +// Pd is the data to copy to the clipboard. This string should be encoded in +// base64 (RFC-4648). +// +// If Pd is "?", the terminal replies to the host with the current contents of +// the clipboard. +// +// If Pd is neither a base64 string nor "?", the terminal clears the clipboard. +// +// See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +// where Ps = 52 => Manipulate Selection Data. +// +// Examples: +// +// // copy "hello world" to the system clipboard +// fmt.Fprint(os.Stderr, osc52.New("hello world")) +// +// // copy "hello world" to the primary Clipboard +// fmt.Fprint(os.Stderr, osc52.New("hello world").Primary()) +// +// // limit the size of the string to copy 10 bytes +// fmt.Fprint(os.Stderr, osc52.New("0123456789").Limit(10)) +// +// // escape the OSC52 sequence for screen using DCS sequences +// fmt.Fprint(os.Stderr, osc52.New("hello world").Screen()) +// +// // escape the OSC52 sequence for Tmux +// fmt.Fprint(os.Stderr, osc52.New("hello world").Tmux()) +// +// // query the system Clipboard +// fmt.Fprint(os.Stderr, osc52.Query()) +// +// // query the primary clipboard +// fmt.Fprint(os.Stderr, osc52.Query().Primary()) +// +// // clear the system Clipboard +// fmt.Fprint(os.Stderr, osc52.Clear()) +// +// // clear the primary Clipboard +// fmt.Fprint(os.Stderr, osc52.Clear().Primary()) +package osc52 + +import ( + "encoding/base64" + "fmt" + "io" + "strings" +) + +// Clipboard is the clipboard buffer to use. +type Clipboard rune + +const ( + // SystemClipboard is the system clipboard buffer. + SystemClipboard Clipboard = 'c' + // PrimaryClipboard is the primary clipboard buffer (X11). + PrimaryClipboard = 'p' +) + +// Mode is the mode to use for the OSC52 sequence. +type Mode uint + +const ( + // DefaultMode is the default OSC52 sequence mode. + DefaultMode Mode = iota + // ScreenMode escapes the OSC52 sequence for screen using DCS sequences. + ScreenMode + // TmuxMode escapes the OSC52 sequence for tmux. Not needed if tmux + // clipboard is set to `set-clipboard on` + TmuxMode +) + +// Operation is the OSC52 operation. +type Operation uint + +const ( + // SetOperation is the copy operation. + SetOperation Operation = iota + // QueryOperation is the query operation. + QueryOperation + // ClearOperation is the clear operation. + ClearOperation +) + +// Sequence is the OSC52 sequence. +type Sequence struct { + str string + limit int + op Operation + mode Mode + clipboard Clipboard +} + +var _ fmt.Stringer = Sequence{} + +var _ io.WriterTo = Sequence{} + +// String returns the OSC52 sequence. +func (s Sequence) String() string { + var seq strings.Builder + // mode escape sequences start + seq.WriteString(s.seqStart()) + // actual OSC52 sequence start + seq.WriteString(fmt.Sprintf("\x1b]52;%c;", s.clipboard)) + switch s.op { + case SetOperation: + str := s.str + if s.limit > 0 && len(str) > s.limit { + return "" + } + b64 := base64.StdEncoding.EncodeToString([]byte(str)) + switch s.mode { + case ScreenMode: + // Screen doesn't support OSC52 but will pass the contents of a DCS + // sequence to the outer terminal unchanged. + // + // Here, we split the encoded string into 76 bytes chunks and then + // join the chunks with sequences. Finally, + // wrap the whole thing in + // . + // s := strings.SplitN(b64, "", 76) + s := make([]string, 0, len(b64)/76+1) + for i := 0; i < len(b64); i += 76 { + end := i + 76 + if end > len(b64) { + end = len(b64) + } + s = append(s, b64[i:end]) + } + seq.WriteString(strings.Join(s, "\x1b\\\x1bP")) + default: + seq.WriteString(b64) + } + case QueryOperation: + // OSC52 queries the clipboard using "?" + seq.WriteString("?") + case ClearOperation: + // OSC52 clears the clipboard if the data is neither a base64 string nor "?" + // we're using "!" as a default + seq.WriteString("!") + } + // actual OSC52 sequence end + seq.WriteString("\x07") + // mode escape end + seq.WriteString(s.seqEnd()) + return seq.String() +} + +// WriteTo writes the OSC52 sequence to the writer. +func (s Sequence) WriteTo(out io.Writer) (int64, error) { + n, err := out.Write([]byte(s.String())) + return int64(n), err +} + +// Mode sets the mode for the OSC52 sequence. +func (s Sequence) Mode(m Mode) Sequence { + s.mode = m + return s +} + +// Tmux sets the mode to TmuxMode. +// Used to escape the OSC52 sequence for `tmux`. +// +// Note: this is not needed if tmux clipboard is set to `set-clipboard on`. If +// TmuxMode is used, tmux must have `allow-passthrough on` set. +// +// This is a syntactic sugar for s.Mode(TmuxMode). +func (s Sequence) Tmux() Sequence { + return s.Mode(TmuxMode) +} + +// Screen sets the mode to ScreenMode. +// Used to escape the OSC52 sequence for `screen`. +// +// This is a syntactic sugar for s.Mode(ScreenMode). +func (s Sequence) Screen() Sequence { + return s.Mode(ScreenMode) +} + +// Clipboard sets the clipboard buffer for the OSC52 sequence. +func (s Sequence) Clipboard(c Clipboard) Sequence { + s.clipboard = c + return s +} + +// Primary sets the clipboard buffer to PrimaryClipboard. +// This is the X11 primary clipboard. +// +// This is a syntactic sugar for s.Clipboard(PrimaryClipboard). +func (s Sequence) Primary() Sequence { + return s.Clipboard(PrimaryClipboard) +} + +// Limit sets the limit for the OSC52 sequence. +// The default limit is 0 (no limit). +// +// Strings longer than the limit get ignored. Settting the limit to 0 or a +// negative value disables the limit. Each terminal defines its own escapse +// sequence limit. +func (s Sequence) Limit(l int) Sequence { + if l < 0 { + s.limit = 0 + } else { + s.limit = l + } + return s +} + +// Operation sets the operation for the OSC52 sequence. +// The default operation is SetOperation. +func (s Sequence) Operation(o Operation) Sequence { + s.op = o + return s +} + +// Clear sets the operation to ClearOperation. +// This clears the clipboard. +// +// This is a syntactic sugar for s.Operation(ClearOperation). +func (s Sequence) Clear() Sequence { + return s.Operation(ClearOperation) +} + +// Query sets the operation to QueryOperation. +// This queries the clipboard contents. +// +// This is a syntactic sugar for s.Operation(QueryOperation). +func (s Sequence) Query() Sequence { + return s.Operation(QueryOperation) +} + +// SetString sets the string for the OSC52 sequence. Strings are joined with a +// space character. +func (s Sequence) SetString(strs ...string) Sequence { + s.str = strings.Join(strs, " ") + return s +} + +// New creates a new OSC52 sequence with the given string(s). Strings are +// joined with a space character. +func New(strs ...string) Sequence { + s := Sequence{ + str: strings.Join(strs, " "), + limit: 0, + mode: DefaultMode, + clipboard: SystemClipboard, + op: SetOperation, + } + return s +} + +// Query creates a new OSC52 sequence with the QueryOperation. +// This returns a new OSC52 sequence to query the clipboard contents. +// +// This is a syntactic sugar for New().Query(). +func Query() Sequence { + return New().Query() +} + +// Clear creates a new OSC52 sequence with the ClearOperation. +// This returns a new OSC52 sequence to clear the clipboard. +// +// This is a syntactic sugar for New().Clear(). +func Clear() Sequence { + return New().Clear() +} + +func (s Sequence) seqStart() string { + switch s.mode { + case TmuxMode: + // Write the start of a tmux escape sequence. + return "\x1bPtmux;\x1b" + case ScreenMode: + // Write the start of a DCS sequence. + return "\x1bP" + default: + return "" + } +} + +func (s Sequence) seqEnd() string { + switch s.mode { + case TmuxMode: + // Terminate the tmux escape sequence. + return "\x1b\\" + case ScreenMode: + // Write the end of a DCS sequence. + return "\x1b\x5c" + default: + return "" + } +} diff --git a/vendor/github.com/charmbracelet/bubbles/LICENSE b/vendor/github.com/charmbracelet/bubbles/LICENSE new file mode 100644 index 00000000..31d76c1c --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbles/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2023 Charmbracelet, Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/charmbracelet/bubbles/cursor/cursor.go b/vendor/github.com/charmbracelet/bubbles/cursor/cursor.go new file mode 100644 index 00000000..d101332b --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbles/cursor/cursor.go @@ -0,0 +1,219 @@ +// Package cursor provides cursor functionality for Bubble Tea applications. +package cursor + +import ( + "context" + "time" + + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" +) + +const defaultBlinkSpeed = time.Millisecond * 530 + +// initialBlinkMsg initializes cursor blinking. +type initialBlinkMsg struct{} + +// BlinkMsg signals that the cursor should blink. It contains metadata that +// allows us to tell if the blink message is the one we're expecting. +type BlinkMsg struct { + id int + tag int +} + +// blinkCanceled is sent when a blink operation is canceled. +type blinkCanceled struct{} + +// blinkCtx manages cursor blinking. +type blinkCtx struct { + ctx context.Context + cancel context.CancelFunc +} + +// Mode describes the behavior of the cursor. +type Mode int + +// Available cursor modes. +const ( + CursorBlink Mode = iota + CursorStatic + CursorHide +) + +// String returns the cursor mode in a human-readable format. This method is +// provisional and for informational purposes only. +func (c Mode) String() string { + return [...]string{ + "blink", + "static", + "hidden", + }[c] +} + +// Model is the Bubble Tea model for this cursor element. +type Model struct { + BlinkSpeed time.Duration + // Style for styling the cursor block. + Style lipgloss.Style + // TextStyle is the style used for the cursor when it is hidden (when blinking). + // I.e. displaying normal text. + TextStyle lipgloss.Style + + // char is the character under the cursor + char string + // The ID of this Model as it relates to other cursors + id int + // focus indicates whether the containing input is focused + focus bool + // Cursor Blink state. + Blink bool + // Used to manage cursor blink + blinkCtx *blinkCtx + // The ID of the blink message we're expecting to receive. + blinkTag int + // mode determines the behavior of the cursor + mode Mode +} + +// New creates a new model with default settings. +func New() Model { + return Model{ + BlinkSpeed: defaultBlinkSpeed, + + Blink: true, + mode: CursorBlink, + + blinkCtx: &blinkCtx{ + ctx: context.Background(), + }, + } +} + +// Update updates the cursor. +func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { + switch msg := msg.(type) { + case initialBlinkMsg: + // We accept all initialBlinkMsgs generated by the Blink command. + + if m.mode != CursorBlink || !m.focus { + return m, nil + } + + cmd := m.BlinkCmd() + return m, cmd + + case tea.FocusMsg: + return m, m.Focus() + + case tea.BlurMsg: + m.Blur() + return m, nil + + case BlinkMsg: + // We're choosy about whether to accept blinkMsgs so that our cursor + // only exactly when it should. + + // Is this model blink-able? + if m.mode != CursorBlink || !m.focus { + return m, nil + } + + // Were we expecting this blink message? + if msg.id != m.id || msg.tag != m.blinkTag { + return m, nil + } + + var cmd tea.Cmd + if m.mode == CursorBlink { + m.Blink = !m.Blink + cmd = m.BlinkCmd() + } + return m, cmd + + case blinkCanceled: // no-op + return m, nil + } + return m, nil +} + +// Mode returns the model's cursor mode. For available cursor modes, see +// type Mode. +func (m Model) Mode() Mode { + return m.mode +} + +// SetMode sets the model's cursor mode. This method returns a command. +// +// For available cursor modes, see type CursorMode. +func (m *Model) SetMode(mode Mode) tea.Cmd { + // Adjust the mode value if it's value is out of range + if mode < CursorBlink || mode > CursorHide { + return nil + } + m.mode = mode + m.Blink = m.mode == CursorHide || !m.focus + if mode == CursorBlink { + return Blink + } + return nil +} + +// BlinkCmd is a command used to manage cursor blinking. +func (m *Model) BlinkCmd() tea.Cmd { + if m.mode != CursorBlink { + return nil + } + + if m.blinkCtx != nil && m.blinkCtx.cancel != nil { + m.blinkCtx.cancel() + } + + ctx, cancel := context.WithTimeout(m.blinkCtx.ctx, m.BlinkSpeed) + m.blinkCtx.cancel = cancel + + m.blinkTag++ + + return func() tea.Msg { + defer cancel() + <-ctx.Done() + if ctx.Err() == context.DeadlineExceeded { + return BlinkMsg{id: m.id, tag: m.blinkTag} + } + return blinkCanceled{} + } +} + +// Blink is a command used to initialize cursor blinking. +func Blink() tea.Msg { + return initialBlinkMsg{} +} + +// Focus focuses the cursor to allow it to blink if desired. +func (m *Model) Focus() tea.Cmd { + m.focus = true + m.Blink = m.mode == CursorHide // show the cursor unless we've explicitly hidden it + + if m.mode == CursorBlink && m.focus { + return m.BlinkCmd() + } + return nil +} + +// Blur blurs the cursor. +func (m *Model) Blur() { + m.focus = false + m.Blink = true +} + +// SetChar sets the character under the cursor. +func (m *Model) SetChar(char string) { + m.char = char +} + +// View displays the cursor. +func (m Model) View() string { + if m.Blink { + return m.TextStyle.Inline(true).Render(m.char) + } + return m.Style.Inline(true).Reverse(true).Render(m.char) +} diff --git a/vendor/github.com/charmbracelet/bubbles/key/key.go b/vendor/github.com/charmbracelet/bubbles/key/key.go new file mode 100644 index 00000000..0682665d --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbles/key/key.go @@ -0,0 +1,140 @@ +// Package key provides some types and functions for generating user-definable +// keymappings useful in Bubble Tea components. There are a few different ways +// you can define a keymapping with this package. Here's one example: +// +// type KeyMap struct { +// Up key.Binding +// Down key.Binding +// } +// +// var DefaultKeyMap = KeyMap{ +// Up: key.NewBinding( +// key.WithKeys("k", "up"), // actual keybindings +// key.WithHelp("↑/k", "move up"), // corresponding help text +// ), +// Down: key.NewBinding( +// key.WithKeys("j", "down"), +// key.WithHelp("↓/j", "move down"), +// ), +// } +// +// func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { +// switch msg := msg.(type) { +// case tea.KeyMsg: +// switch { +// case key.Matches(msg, DefaultKeyMap.Up): +// // The user pressed up +// case key.Matches(msg, DefaultKeyMap.Down): +// // The user pressed down +// } +// } +// +// // ... +// } +// +// The help information, which is not used in the example above, can be used +// to render help text for keystrokes in your views. +package key + +import "fmt" + +// Binding describes a set of keybindings and, optionally, their associated +// help text. +type Binding struct { + keys []string + help Help + disabled bool +} + +// BindingOpt is an initialization option for a keybinding. It's used as an +// argument to NewBinding. +type BindingOpt func(*Binding) + +// NewBinding returns a new keybinding from a set of BindingOpt options. +func NewBinding(opts ...BindingOpt) Binding { + b := &Binding{} + for _, opt := range opts { + opt(b) + } + return *b +} + +// WithKeys initializes a keybinding with the given keystrokes. +func WithKeys(keys ...string) BindingOpt { + return func(b *Binding) { + b.keys = keys + } +} + +// WithHelp initializes a keybinding with the given help text. +func WithHelp(key, desc string) BindingOpt { + return func(b *Binding) { + b.help = Help{Key: key, Desc: desc} + } +} + +// WithDisabled initializes a disabled keybinding. +func WithDisabled() BindingOpt { + return func(b *Binding) { + b.disabled = true + } +} + +// SetKeys sets the keys for the keybinding. +func (b *Binding) SetKeys(keys ...string) { + b.keys = keys +} + +// Keys returns the keys for the keybinding. +func (b Binding) Keys() []string { + return b.keys +} + +// SetHelp sets the help text for the keybinding. +func (b *Binding) SetHelp(key, desc string) { + b.help = Help{Key: key, Desc: desc} +} + +// Help returns the Help information for the keybinding. +func (b Binding) Help() Help { + return b.help +} + +// Enabled returns whether or not the keybinding is enabled. Disabled +// keybindings won't be activated and won't show up in help. Keybindings are +// enabled by default. +func (b Binding) Enabled() bool { + return !b.disabled && b.keys != nil +} + +// SetEnabled enables or disables the keybinding. +func (b *Binding) SetEnabled(v bool) { + b.disabled = !v +} + +// Unbind removes the keys and help from this binding, effectively nullifying +// it. This is a step beyond disabling it, since applications can enable +// or disable key bindings based on application state. +func (b *Binding) Unbind() { + b.keys = nil + b.help = Help{} +} + +// Help is help information for a given keybinding. +type Help struct { + Key string + Desc string +} + +// Matches checks if the given key matches the given bindings. +func Matches[Key fmt.Stringer](k Key, b ...Binding) bool { + keys := k.String() + for _, binding := range b { + for _, v := range binding.keys { + if keys == v && binding.Enabled() { + return true + } + } + } + return false +} diff --git a/vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go b/vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go new file mode 100644 index 00000000..82ea90a2 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbles/runeutil/runeutil.go @@ -0,0 +1,102 @@ +// Package runeutil provides a utility function for use in Bubbles +// that can process Key messages containing runes. +package runeutil + +import ( + "unicode" + "unicode/utf8" +) + +// Sanitizer is a helper for bubble widgets that want to process +// Runes from input key messages. +type Sanitizer interface { + // Sanitize removes control characters from runes in a KeyRunes + // message, and optionally replaces newline/carriage return/tabs by a + // specified character. + // + // The rune array is modified in-place if possible. In that case, the + // returned slice is the original slice shortened after the control + // characters have been removed/translated. + Sanitize(runes []rune) []rune +} + +// NewSanitizer constructs a rune sanitizer. +func NewSanitizer(opts ...Option) Sanitizer { + s := sanitizer{ + replaceNewLine: []rune("\n"), + replaceTab: []rune(" "), + } + for _, o := range opts { + s = o(s) + } + return &s +} + +// Option is the type of option that can be passed to Sanitize(). +type Option func(sanitizer) sanitizer + +// ReplaceTabs replaces tabs by the specified string. +func ReplaceTabs(tabRepl string) Option { + return func(s sanitizer) sanitizer { + s.replaceTab = []rune(tabRepl) + return s + } +} + +// ReplaceNewlines replaces newline characters by the specified string. +func ReplaceNewlines(nlRepl string) Option { + return func(s sanitizer) sanitizer { + s.replaceNewLine = []rune(nlRepl) + return s + } +} + +func (s *sanitizer) Sanitize(runes []rune) []rune { + // dstrunes are where we are storing the result. + dstrunes := runes[:0:len(runes)] + // copied indicates whether dstrunes is an alias of runes + // or a copy. We need a copy when dst moves past src. + // We use this as an optimization to avoid allocating + // a new rune slice in the common case where the output + // is smaller or equal to the input. + copied := false + + for src := 0; src < len(runes); src++ { + r := runes[src] + switch { + case r == utf8.RuneError: + // skip + + case r == '\r' || r == '\n': + if len(dstrunes)+len(s.replaceNewLine) > src && !copied { + dst := len(dstrunes) + dstrunes = make([]rune, dst, len(runes)+len(s.replaceNewLine)) + copy(dstrunes, runes[:dst]) + copied = true + } + dstrunes = append(dstrunes, s.replaceNewLine...) + + case r == '\t': + if len(dstrunes)+len(s.replaceTab) > src && !copied { + dst := len(dstrunes) + dstrunes = make([]rune, dst, len(runes)+len(s.replaceTab)) + copy(dstrunes, runes[:dst]) + copied = true + } + dstrunes = append(dstrunes, s.replaceTab...) + + case unicode.IsControl(r): + // Other control characters: skip. + + default: + // Keep the character. + dstrunes = append(dstrunes, runes[src]) + } + } + return dstrunes +} + +type sanitizer struct { + replaceNewLine []rune + replaceTab []rune +} diff --git a/vendor/github.com/charmbracelet/bubbles/textinput/textinput.go b/vendor/github.com/charmbracelet/bubbles/textinput/textinput.go new file mode 100644 index 00000000..84cbbc93 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbles/textinput/textinput.go @@ -0,0 +1,898 @@ +// Package textinput provides a text input component for Bubble Tea +// applications. +package textinput + +import ( + "reflect" + "strings" + "time" + "unicode" + + "github.com/atotto/clipboard" + "github.com/charmbracelet/bubbles/cursor" + "github.com/charmbracelet/bubbles/key" + "github.com/charmbracelet/bubbles/runeutil" + tea "github.com/charmbracelet/bubbletea" + "github.com/charmbracelet/lipgloss" + rw "github.com/mattn/go-runewidth" + "github.com/rivo/uniseg" +) + +// Internal messages for clipboard operations. +type ( + pasteMsg string + pasteErrMsg struct{ error } +) + +// EchoMode sets the input behavior of the text input field. +type EchoMode int + +const ( + // EchoNormal displays text as is. This is the default behavior. + EchoNormal EchoMode = iota + + // EchoPassword displays the EchoCharacter mask instead of actual + // characters. This is commonly used for password fields. + EchoPassword + + // EchoNone displays nothing as characters are entered. This is commonly + // seen for password fields on the command line. + EchoNone +) + +// ValidateFunc is a function that returns an error if the input is invalid. +type ValidateFunc func(string) error + +// KeyMap is the key bindings for different actions within the textinput. +type KeyMap struct { + CharacterForward key.Binding + CharacterBackward key.Binding + WordForward key.Binding + WordBackward key.Binding + DeleteWordBackward key.Binding + DeleteWordForward key.Binding + DeleteAfterCursor key.Binding + DeleteBeforeCursor key.Binding + DeleteCharacterBackward key.Binding + DeleteCharacterForward key.Binding + LineStart key.Binding + LineEnd key.Binding + Paste key.Binding + AcceptSuggestion key.Binding + NextSuggestion key.Binding + PrevSuggestion key.Binding +} + +// DefaultKeyMap is the default set of key bindings for navigating and acting +// upon the textinput. +var DefaultKeyMap = KeyMap{ + CharacterForward: key.NewBinding(key.WithKeys("right", "ctrl+f")), + CharacterBackward: key.NewBinding(key.WithKeys("left", "ctrl+b")), + WordForward: key.NewBinding(key.WithKeys("alt+right", "ctrl+right", "alt+f")), + WordBackward: key.NewBinding(key.WithKeys("alt+left", "ctrl+left", "alt+b")), + DeleteWordBackward: key.NewBinding(key.WithKeys("alt+backspace", "ctrl+w")), + DeleteWordForward: key.NewBinding(key.WithKeys("alt+delete", "alt+d")), + DeleteAfterCursor: key.NewBinding(key.WithKeys("ctrl+k")), + DeleteBeforeCursor: key.NewBinding(key.WithKeys("ctrl+u")), + DeleteCharacterBackward: key.NewBinding(key.WithKeys("backspace", "ctrl+h")), + DeleteCharacterForward: key.NewBinding(key.WithKeys("delete", "ctrl+d")), + LineStart: key.NewBinding(key.WithKeys("home", "ctrl+a")), + LineEnd: key.NewBinding(key.WithKeys("end", "ctrl+e")), + Paste: key.NewBinding(key.WithKeys("ctrl+v")), + AcceptSuggestion: key.NewBinding(key.WithKeys("tab")), + NextSuggestion: key.NewBinding(key.WithKeys("down", "ctrl+n")), + PrevSuggestion: key.NewBinding(key.WithKeys("up", "ctrl+p")), +} + +// Model is the Bubble Tea model for this text input element. +type Model struct { + Err error + + // General settings. + Prompt string + Placeholder string + EchoMode EchoMode + EchoCharacter rune + Cursor cursor.Model + + // Deprecated: use [cursor.BlinkSpeed] instead. + BlinkSpeed time.Duration + + // Styles. These will be applied as inline styles. + // + // For an introduction to styling with Lip Gloss see: + // https://github.com/charmbracelet/lipgloss + PromptStyle lipgloss.Style + TextStyle lipgloss.Style + PlaceholderStyle lipgloss.Style + CompletionStyle lipgloss.Style + + // Deprecated: use Cursor.Style instead. + CursorStyle lipgloss.Style + + // CharLimit is the maximum amount of characters this input element will + // accept. If 0 or less, there's no limit. + CharLimit int + + // Width is the maximum number of characters that can be displayed at once. + // It essentially treats the text field like a horizontally scrolling + // viewport. If 0 or less this setting is ignored. + Width int + + // KeyMap encodes the keybindings recognized by the widget. + KeyMap KeyMap + + // Underlying text value. + value []rune + + // focus indicates whether user input focus should be on this input + // component. When false, ignore keyboard input and hide the cursor. + focus bool + + // Cursor position. + pos int + + // Used to emulate a viewport when width is set and the content is + // overflowing. + offset int + offsetRight int + + // Validate is a function that checks whether or not the text within the + // input is valid. If it is not valid, the `Err` field will be set to the + // error returned by the function. If the function is not defined, all + // input is considered valid. + Validate ValidateFunc + + // rune sanitizer for input. + rsan runeutil.Sanitizer + + // Should the input suggest to complete + ShowSuggestions bool + + // suggestions is a list of suggestions that may be used to complete the + // input. + suggestions [][]rune + matchedSuggestions [][]rune + currentSuggestionIndex int +} + +// New creates a new model with default settings. +func New() Model { + return Model{ + Prompt: "> ", + EchoCharacter: '*', + CharLimit: 0, + PlaceholderStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("240")), + ShowSuggestions: false, + CompletionStyle: lipgloss.NewStyle().Foreground(lipgloss.Color("240")), + Cursor: cursor.New(), + KeyMap: DefaultKeyMap, + + suggestions: [][]rune{}, + value: nil, + focus: false, + pos: 0, + } +} + +// NewModel creates a new model with default settings. +// +// Deprecated: Use [New] instead. +var NewModel = New + +// SetValue sets the value of the text input. +func (m *Model) SetValue(s string) { + // Clean up any special characters in the input provided by the + // caller. This avoids bugs due to e.g. tab characters and whatnot. + runes := m.san().Sanitize([]rune(s)) + err := m.validate(runes) + m.setValueInternal(runes, err) +} + +func (m *Model) setValueInternal(runes []rune, err error) { + m.Err = err + + empty := len(m.value) == 0 + + if m.CharLimit > 0 && len(runes) > m.CharLimit { + m.value = runes[:m.CharLimit] + } else { + m.value = runes + } + if (m.pos == 0 && empty) || m.pos > len(m.value) { + m.SetCursor(len(m.value)) + } + m.handleOverflow() +} + +// Value returns the value of the text input. +func (m Model) Value() string { + return string(m.value) +} + +// Position returns the cursor position. +func (m Model) Position() int { + return m.pos +} + +// SetCursor moves the cursor to the given position. If the position is +// out of bounds the cursor will be moved to the start or end accordingly. +func (m *Model) SetCursor(pos int) { + m.pos = clamp(pos, 0, len(m.value)) + m.handleOverflow() +} + +// CursorStart moves the cursor to the start of the input field. +func (m *Model) CursorStart() { + m.SetCursor(0) +} + +// CursorEnd moves the cursor to the end of the input field. +func (m *Model) CursorEnd() { + m.SetCursor(len(m.value)) +} + +// Focused returns the focus state on the model. +func (m Model) Focused() bool { + return m.focus +} + +// Focus sets the focus state on the model. When the model is in focus it can +// receive keyboard input and the cursor will be shown. +func (m *Model) Focus() tea.Cmd { + m.focus = true + return m.Cursor.Focus() +} + +// Blur removes the focus state on the model. When the model is blurred it can +// not receive keyboard input and the cursor will be hidden. +func (m *Model) Blur() { + m.focus = false + m.Cursor.Blur() +} + +// Reset sets the input to its default state with no input. +func (m *Model) Reset() { + m.value = nil + m.SetCursor(0) +} + +// SetSuggestions sets the suggestions for the input. +func (m *Model) SetSuggestions(suggestions []string) { + m.suggestions = make([][]rune, len(suggestions)) + for i, s := range suggestions { + m.suggestions[i] = []rune(s) + } + + m.updateSuggestions() +} + +// rsan initializes or retrieves the rune sanitizer. +func (m *Model) san() runeutil.Sanitizer { + if m.rsan == nil { + // Textinput has all its input on a single line so collapse + // newlines/tabs to single spaces. + m.rsan = runeutil.NewSanitizer( + runeutil.ReplaceTabs(" "), runeutil.ReplaceNewlines(" ")) + } + return m.rsan +} + +func (m *Model) insertRunesFromUserInput(v []rune) { + // Clean up any special characters in the input provided by the + // clipboard. This avoids bugs due to e.g. tab characters and + // whatnot. + paste := m.san().Sanitize(v) + + var availSpace int + if m.CharLimit > 0 { + availSpace = m.CharLimit - len(m.value) + + // If the char limit's been reached, cancel. + if availSpace <= 0 { + return + } + + // If there's not enough space to paste the whole thing cut the pasted + // runes down so they'll fit. + if availSpace < len(paste) { + paste = paste[:availSpace] + } + } + + // Stuff before and after the cursor + head := m.value[:m.pos] + tailSrc := m.value[m.pos:] + tail := make([]rune, len(tailSrc)) + copy(tail, tailSrc) + + // Insert pasted runes + for _, r := range paste { + head = append(head, r) + m.pos++ + if m.CharLimit > 0 { + availSpace-- + if availSpace <= 0 { + break + } + } + } + + // Put it all back together + value := append(head, tail...) + inputErr := m.validate(value) + m.setValueInternal(value, inputErr) +} + +// If a max width is defined, perform some logic to treat the visible area +// as a horizontally scrolling viewport. +func (m *Model) handleOverflow() { + if m.Width <= 0 || uniseg.StringWidth(string(m.value)) <= m.Width { + m.offset = 0 + m.offsetRight = len(m.value) + return + } + + // Correct right offset if we've deleted characters + m.offsetRight = min(m.offsetRight, len(m.value)) + + if m.pos < m.offset { + m.offset = m.pos + + w := 0 + i := 0 + runes := m.value[m.offset:] + + for i < len(runes) && w <= m.Width { + w += rw.RuneWidth(runes[i]) + if w <= m.Width+1 { + i++ + } + } + + m.offsetRight = m.offset + i + } else if m.pos >= m.offsetRight { + m.offsetRight = m.pos + + w := 0 + runes := m.value[:m.offsetRight] + i := len(runes) - 1 + + for i > 0 && w < m.Width { + w += rw.RuneWidth(runes[i]) + if w <= m.Width { + i-- + } + } + + m.offset = m.offsetRight - (len(runes) - 1 - i) + } +} + +// deleteBeforeCursor deletes all text before the cursor. +func (m *Model) deleteBeforeCursor() { + m.value = m.value[m.pos:] + m.Err = m.validate(m.value) + m.offset = 0 + m.SetCursor(0) +} + +// deleteAfterCursor deletes all text after the cursor. If input is masked +// delete everything after the cursor so as not to reveal word breaks in the +// masked input. +func (m *Model) deleteAfterCursor() { + m.value = m.value[:m.pos] + m.Err = m.validate(m.value) + m.SetCursor(len(m.value)) +} + +// deleteWordBackward deletes the word left to the cursor. +func (m *Model) deleteWordBackward() { + if m.pos == 0 || len(m.value) == 0 { + return + } + + if m.EchoMode != EchoNormal { + m.deleteBeforeCursor() + return + } + + // Linter note: it's critical that we acquire the initial cursor position + // here prior to altering it via SetCursor() below. As such, moving this + // call into the corresponding if clause does not apply here. + oldPos := m.pos //nolint:ifshort + + m.SetCursor(m.pos - 1) + for unicode.IsSpace(m.value[m.pos]) { + if m.pos <= 0 { + break + } + // ignore series of whitespace before cursor + m.SetCursor(m.pos - 1) + } + + for m.pos > 0 { + if !unicode.IsSpace(m.value[m.pos]) { + m.SetCursor(m.pos - 1) + } else { + if m.pos > 0 { + // keep the previous space + m.SetCursor(m.pos + 1) + } + break + } + } + + if oldPos > len(m.value) { + m.value = m.value[:m.pos] + } else { + m.value = append(m.value[:m.pos], m.value[oldPos:]...) + } + m.Err = m.validate(m.value) +} + +// deleteWordForward deletes the word right to the cursor. If input is masked +// delete everything after the cursor so as not to reveal word breaks in the +// masked input. +func (m *Model) deleteWordForward() { + if m.pos >= len(m.value) || len(m.value) == 0 { + return + } + + if m.EchoMode != EchoNormal { + m.deleteAfterCursor() + return + } + + oldPos := m.pos + m.SetCursor(m.pos + 1) + for unicode.IsSpace(m.value[m.pos]) { + // ignore series of whitespace after cursor + m.SetCursor(m.pos + 1) + + if m.pos >= len(m.value) { + break + } + } + + for m.pos < len(m.value) { + if !unicode.IsSpace(m.value[m.pos]) { + m.SetCursor(m.pos + 1) + } else { + break + } + } + + if m.pos > len(m.value) { + m.value = m.value[:oldPos] + } else { + m.value = append(m.value[:oldPos], m.value[m.pos:]...) + } + m.Err = m.validate(m.value) + + m.SetCursor(oldPos) +} + +// wordBackward moves the cursor one word to the left. If input is masked, move +// input to the start so as not to reveal word breaks in the masked input. +func (m *Model) wordBackward() { + if m.pos == 0 || len(m.value) == 0 { + return + } + + if m.EchoMode != EchoNormal { + m.CursorStart() + return + } + + i := m.pos - 1 + for i >= 0 { + if unicode.IsSpace(m.value[i]) { + m.SetCursor(m.pos - 1) + i-- + } else { + break + } + } + + for i >= 0 { + if !unicode.IsSpace(m.value[i]) { + m.SetCursor(m.pos - 1) + i-- + } else { + break + } + } +} + +// wordForward moves the cursor one word to the right. If the input is masked, +// move input to the end so as not to reveal word breaks in the masked input. +func (m *Model) wordForward() { + if m.pos >= len(m.value) || len(m.value) == 0 { + return + } + + if m.EchoMode != EchoNormal { + m.CursorEnd() + return + } + + i := m.pos + for i < len(m.value) { + if unicode.IsSpace(m.value[i]) { + m.SetCursor(m.pos + 1) + i++ + } else { + break + } + } + + for i < len(m.value) { + if !unicode.IsSpace(m.value[i]) { + m.SetCursor(m.pos + 1) + i++ + } else { + break + } + } +} + +func (m Model) echoTransform(v string) string { + switch m.EchoMode { + case EchoPassword: + return strings.Repeat(string(m.EchoCharacter), uniseg.StringWidth(v)) + case EchoNone: + return "" + case EchoNormal: + return v + default: + return v + } +} + +// Update is the Bubble Tea update loop. +func (m Model) Update(msg tea.Msg) (Model, tea.Cmd) { + if !m.focus { + return m, nil + } + + // Need to check for completion before, because key is configurable and might be double assigned + keyMsg, ok := msg.(tea.KeyMsg) + if ok && key.Matches(keyMsg, m.KeyMap.AcceptSuggestion) { + if m.canAcceptSuggestion() { + m.value = append(m.value, m.matchedSuggestions[m.currentSuggestionIndex][len(m.value):]...) + m.CursorEnd() + } + } + + // Let's remember where the position of the cursor currently is so that if + // the cursor position changes, we can reset the blink. + oldPos := m.pos + + switch msg := msg.(type) { + case tea.KeyMsg: + switch { + case key.Matches(msg, m.KeyMap.DeleteWordBackward): + m.deleteWordBackward() + case key.Matches(msg, m.KeyMap.DeleteCharacterBackward): + m.Err = nil + if len(m.value) > 0 { + m.value = append(m.value[:max(0, m.pos-1)], m.value[m.pos:]...) + m.Err = m.validate(m.value) + if m.pos > 0 { + m.SetCursor(m.pos - 1) + } + } + case key.Matches(msg, m.KeyMap.WordBackward): + m.wordBackward() + case key.Matches(msg, m.KeyMap.CharacterBackward): + if m.pos > 0 { + m.SetCursor(m.pos - 1) + } + case key.Matches(msg, m.KeyMap.WordForward): + m.wordForward() + case key.Matches(msg, m.KeyMap.CharacterForward): + if m.pos < len(m.value) { + m.SetCursor(m.pos + 1) + } + case key.Matches(msg, m.KeyMap.LineStart): + m.CursorStart() + case key.Matches(msg, m.KeyMap.DeleteCharacterForward): + if len(m.value) > 0 && m.pos < len(m.value) { + m.value = append(m.value[:m.pos], m.value[m.pos+1:]...) + m.Err = m.validate(m.value) + } + case key.Matches(msg, m.KeyMap.LineEnd): + m.CursorEnd() + case key.Matches(msg, m.KeyMap.DeleteAfterCursor): + m.deleteAfterCursor() + case key.Matches(msg, m.KeyMap.DeleteBeforeCursor): + m.deleteBeforeCursor() + case key.Matches(msg, m.KeyMap.Paste): + return m, Paste + case key.Matches(msg, m.KeyMap.DeleteWordForward): + m.deleteWordForward() + case key.Matches(msg, m.KeyMap.NextSuggestion): + m.nextSuggestion() + case key.Matches(msg, m.KeyMap.PrevSuggestion): + m.previousSuggestion() + default: + // Input one or more regular characters. + m.insertRunesFromUserInput(msg.Runes) + } + + // Check again if can be completed + // because value might be something that does not match the completion prefix + m.updateSuggestions() + + case pasteMsg: + m.insertRunesFromUserInput([]rune(msg)) + + case pasteErrMsg: + m.Err = msg + } + + var cmds []tea.Cmd + var cmd tea.Cmd + + m.Cursor, cmd = m.Cursor.Update(msg) + cmds = append(cmds, cmd) + + if oldPos != m.pos && m.Cursor.Mode() == cursor.CursorBlink { + m.Cursor.Blink = false + cmds = append(cmds, m.Cursor.BlinkCmd()) + } + + m.handleOverflow() + return m, tea.Batch(cmds...) +} + +// View renders the textinput in its current state. +func (m Model) View() string { + // Placeholder text + if len(m.value) == 0 && m.Placeholder != "" { + return m.placeholderView() + } + + styleText := m.TextStyle.Inline(true).Render + + value := m.value[m.offset:m.offsetRight] + pos := max(0, m.pos-m.offset) + v := styleText(m.echoTransform(string(value[:pos]))) + + if pos < len(value) { //nolint:nestif + char := m.echoTransform(string(value[pos])) + m.Cursor.SetChar(char) + v += m.Cursor.View() // cursor and text under it + v += styleText(m.echoTransform(string(value[pos+1:]))) // text after cursor + v += m.completionView(0) // suggested completion + } else { + if m.focus && m.canAcceptSuggestion() { + suggestion := m.matchedSuggestions[m.currentSuggestionIndex] + if len(value) < len(suggestion) { + m.Cursor.TextStyle = m.CompletionStyle + m.Cursor.SetChar(m.echoTransform(string(suggestion[pos]))) + v += m.Cursor.View() + v += m.completionView(1) + } else { + m.Cursor.SetChar(" ") + v += m.Cursor.View() + } + } else { + m.Cursor.SetChar(" ") + v += m.Cursor.View() + } + } + + // If a max width and background color were set fill the empty spaces with + // the background color. + valWidth := uniseg.StringWidth(string(value)) + if m.Width > 0 && valWidth <= m.Width { + padding := max(0, m.Width-valWidth) + if valWidth+padding <= m.Width && pos < len(value) { + padding++ + } + v += styleText(strings.Repeat(" ", padding)) + } + + return m.PromptStyle.Render(m.Prompt) + v +} + +// placeholderView returns the prompt and placeholder view, if any. +func (m Model) placeholderView() string { + var ( + v string + style = m.PlaceholderStyle.Inline(true).Render + ) + + p := make([]rune, m.Width+1) + copy(p, []rune(m.Placeholder)) + + m.Cursor.TextStyle = m.PlaceholderStyle + m.Cursor.SetChar(string(p[:1])) + v += m.Cursor.View() + + // If the entire placeholder is already set and no padding is needed, finish + if m.Width < 1 && len(p) <= 1 { + return m.PromptStyle.Render(m.Prompt) + v + } + + // If Width is set then size placeholder accordingly + if m.Width > 0 { + // available width is width - len + cursor offset of 1 + minWidth := lipgloss.Width(m.Placeholder) + availWidth := m.Width - minWidth + 1 + + // if width < len, 'subtract'(add) number to len and dont add padding + if availWidth < 0 { + minWidth += availWidth + availWidth = 0 + } + // append placeholder[len] - cursor, append padding + v += style(string(p[1:minWidth])) + v += style(strings.Repeat(" ", availWidth)) + } else { + // if there is no width, the placeholder can be any length + v += style(string(p[1:])) + } + + return m.PromptStyle.Render(m.Prompt) + v +} + +// Blink is a command used to initialize cursor blinking. +func Blink() tea.Msg { + return cursor.Blink() +} + +// Paste is a command for pasting from the clipboard into the text input. +func Paste() tea.Msg { + str, err := clipboard.ReadAll() + if err != nil { + return pasteErrMsg{err} + } + return pasteMsg(str) +} + +func clamp(v, low, high int) int { + if high < low { + low, high = high, low + } + return min(high, max(low, v)) +} + +// Deprecated. + +// Deprecated: use [cursor.Mode]. +// +//nolint:revive +type CursorMode int + +//nolint:revive +const ( + // Deprecated: use [cursor.CursorBlink]. + CursorBlink = CursorMode(cursor.CursorBlink) + // Deprecated: use [cursor.CursorStatic]. + CursorStatic = CursorMode(cursor.CursorStatic) + // Deprecated: use [cursor.CursorHide]. + CursorHide = CursorMode(cursor.CursorHide) +) + +func (c CursorMode) String() string { + return cursor.Mode(c).String() +} + +// Deprecated: use [cursor.Mode]. +// +//nolint:revive +func (m Model) CursorMode() CursorMode { + return CursorMode(m.Cursor.Mode()) +} + +// Deprecated: use cursor.SetMode(). +// +//nolint:revive +func (m *Model) SetCursorMode(mode CursorMode) tea.Cmd { + return m.Cursor.SetMode(cursor.Mode(mode)) +} + +func (m Model) completionView(offset int) string { + var ( + value = m.value + style = m.PlaceholderStyle.Inline(true).Render + ) + + if m.canAcceptSuggestion() { + suggestion := m.matchedSuggestions[m.currentSuggestionIndex] + if len(value) < len(suggestion) { + return style(string(suggestion[len(value)+offset:])) + } + } + return "" +} + +func (m *Model) getSuggestions(sugs [][]rune) []string { + suggestions := make([]string, len(sugs)) + for i, s := range sugs { + suggestions[i] = string(s) + } + return suggestions +} + +// AvailableSuggestions returns the list of available suggestions. +func (m *Model) AvailableSuggestions() []string { + return m.getSuggestions(m.suggestions) +} + +// MatchedSuggestions returns the list of matched suggestions. +func (m *Model) MatchedSuggestions() []string { + return m.getSuggestions(m.matchedSuggestions) +} + +// CurrentSuggestionIndex returns the currently selected suggestion index. +func (m *Model) CurrentSuggestionIndex() int { + return m.currentSuggestionIndex +} + +// CurrentSuggestion returns the currently selected suggestion. +func (m *Model) CurrentSuggestion() string { + if m.currentSuggestionIndex >= len(m.matchedSuggestions) { + return "" + } + + return string(m.matchedSuggestions[m.currentSuggestionIndex]) +} + +// canAcceptSuggestion returns whether there is an acceptable suggestion to +// autocomplete the current value. +func (m *Model) canAcceptSuggestion() bool { + return len(m.matchedSuggestions) > 0 +} + +// updateSuggestions refreshes the list of matching suggestions. +func (m *Model) updateSuggestions() { + if !m.ShowSuggestions { + return + } + + if len(m.value) <= 0 || len(m.suggestions) <= 0 { + m.matchedSuggestions = [][]rune{} + return + } + + matches := [][]rune{} + for _, s := range m.suggestions { + suggestion := string(s) + + if strings.HasPrefix(strings.ToLower(suggestion), strings.ToLower(string(m.value))) { + matches = append(matches, []rune(suggestion)) + } + } + if !reflect.DeepEqual(matches, m.matchedSuggestions) { + m.currentSuggestionIndex = 0 + } + + m.matchedSuggestions = matches +} + +// nextSuggestion selects the next suggestion. +func (m *Model) nextSuggestion() { + m.currentSuggestionIndex = (m.currentSuggestionIndex + 1) + if m.currentSuggestionIndex >= len(m.matchedSuggestions) { + m.currentSuggestionIndex = 0 + } +} + +// previousSuggestion selects the previous suggestion. +func (m *Model) previousSuggestion() { + m.currentSuggestionIndex = (m.currentSuggestionIndex - 1) + if m.currentSuggestionIndex < 0 { + m.currentSuggestionIndex = len(m.matchedSuggestions) - 1 + } +} + +func (m Model) validate(v []rune) error { + if m.Validate != nil { + return m.Validate(string(v)) + } + return nil +} diff --git a/vendor/github.com/charmbracelet/bubbletea/.gitattributes b/vendor/github.com/charmbracelet/bubbletea/.gitattributes new file mode 100644 index 00000000..6c929d48 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/.gitattributes @@ -0,0 +1 @@ +*.golden -text diff --git a/vendor/github.com/charmbracelet/bubbletea/.gitignore b/vendor/github.com/charmbracelet/bubbletea/.gitignore new file mode 100644 index 00000000..abd7c061 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/.gitignore @@ -0,0 +1,23 @@ +.DS_Store +.envrc + +examples/fullscreen/fullscreen +examples/help/help +examples/http/http +examples/list-default/list-default +examples/list-fancy/list-fancy +examples/list-simple/list-simple +examples/mouse/mouse +examples/pager/pager +examples/progress-download/color_vortex.blend +examples/progress-download/progress-download +examples/simple/simple +examples/spinner/spinner +examples/textinput/textinput +examples/textinputs/textinputs +examples/views/views +tutorials/basics/basics +tutorials/commands/commands +.idea +coverage.txt +dist/ diff --git a/vendor/github.com/charmbracelet/bubbletea/.golangci.yml b/vendor/github.com/charmbracelet/bubbletea/.golangci.yml new file mode 100644 index 00000000..4fac29c2 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/.golangci.yml @@ -0,0 +1,40 @@ +version: "2" +run: + tests: false +linters: + enable: + - bodyclose + - exhaustive + - goconst + - godot + - gomoddirectives + - goprintffuncname + - gosec + - misspell + - nakedret + - nestif + - nilerr + - noctx + - nolintlint + - prealloc + - revive + - rowserrcheck + - sqlclosecheck + - tparallel + - unconvert + - unparam + - whitespace + - wrapcheck + exclusions: + generated: lax + presets: + - common-false-positives +issues: + max-issues-per-linter: 0 + max-same-issues: 0 +formatters: + enable: + - gofumpt + - goimports + exclusions: + generated: lax diff --git a/vendor/github.com/charmbracelet/bubbletea/.goreleaser.yml b/vendor/github.com/charmbracelet/bubbletea/.goreleaser.yml new file mode 100644 index 00000000..3353d020 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/.goreleaser.yml @@ -0,0 +1,5 @@ +# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json +version: 2 +includes: + - from_url: + url: charmbracelet/meta/main/goreleaser-lib.yaml diff --git a/vendor/github.com/charmbracelet/bubbletea/LICENSE b/vendor/github.com/charmbracelet/bubbletea/LICENSE new file mode 100644 index 00000000..31d76c1c --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2023 Charmbracelet, Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/charmbracelet/bubbletea/README.md b/vendor/github.com/charmbracelet/bubbletea/README.md new file mode 100644 index 00000000..b3acf900 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/README.md @@ -0,0 +1,400 @@ +# Bubble Tea + +

+ + + + + +
+ Latest Release + GoDoc + Build Status +

+ +The fun, functional and stateful way to build terminal apps. A Go framework +based on [The Elm Architecture][elm]. Bubble Tea is well-suited for simple and +complex terminal applications, either inline, full-window, or a mix of both. + +

+ Bubble Tea Example +

+ +Bubble Tea is in use in production and includes a number of features and +performance optimizations we’ve added along the way. Among those is +a framerate-based renderer, mouse support, focus reporting and more. + +To get started, see the tutorial below, the [examples][examples], the +[docs][docs], the [video tutorials][youtube] and some common [resources](#libraries-we-use-with-bubble-tea). + +[youtube]: https://charm.sh/yt + +## By the way + +Be sure to check out [Bubbles][bubbles], a library of common UI components for Bubble Tea. + +

+ Bubbles Badge   + Text Input Example from Bubbles +

+ +--- + +## Tutorial + +Bubble Tea is based on the functional design paradigms of [The Elm +Architecture][elm], which happens to work nicely with Go. It's a delightful way +to build applications. + +This tutorial assumes you have a working knowledge of Go. + +By the way, the non-annotated source code for this program is available +[on GitHub][tut-source]. + +[elm]: https://guide.elm-lang.org/architecture/ +[tut-source]: https://github.com/charmbracelet/bubbletea/tree/main/tutorials/basics + +### Enough! Let's get to it. + +For this tutorial, we're making a shopping list. + +To start we'll define our package and import some libraries. Our only external +import will be the Bubble Tea library, which we'll call `tea` for short. + +```go +package main + +// These imports will be used later on the tutorial. If you save the file +// now, Go might complain they are unused, but that's fine. +// You may also need to run `go mod tidy` to download bubbletea and its +// dependencies. +import ( + "fmt" + "os" + + tea "github.com/charmbracelet/bubbletea" +) +``` + +Bubble Tea programs are comprised of a **model** that describes the application +state and three simple methods on that model: + +- **Init**, a function that returns an initial command for the application to run. +- **Update**, a function that handles incoming events and updates the model accordingly. +- **View**, a function that renders the UI based on the data in the model. + +### The Model + +So let's start by defining our model which will store our application's state. +It can be any type, but a `struct` usually makes the most sense. + +```go +type model struct { + choices []string // items on the to-do list + cursor int // which to-do list item our cursor is pointing at + selected map[int]struct{} // which to-do items are selected +} +``` + +### Initialization + +Next, we’ll define our application’s initial state. In this case, we’re defining +a function to return our initial model, however, we could just as easily define +the initial model as a variable elsewhere, too. + +```go +func initialModel() model { + return model{ + // Our to-do list is a grocery list + choices: []string{"Buy carrots", "Buy celery", "Buy kohlrabi"}, + + // A map which indicates which choices are selected. We're using + // the map like a mathematical set. The keys refer to the indexes + // of the `choices` slice, above. + selected: make(map[int]struct{}), + } +} +``` + +Next, we define the `Init` method. `Init` can return a `Cmd` that could perform +some initial I/O. For now, we don't need to do any I/O, so for the command, +we'll just return `nil`, which translates to "no command." + +```go +func (m model) Init() tea.Cmd { + // Just return `nil`, which means "no I/O right now, please." + return nil +} +``` + +### The Update Method + +Next up is the update method. The update function is called when ”things +happen.” Its job is to look at what has happened and return an updated model in +response. It can also return a `Cmd` to make more things happen, but for now +don't worry about that part. + +In our case, when a user presses the down arrow, `Update`’s job is to notice +that the down arrow was pressed and move the cursor accordingly (or not). + +The “something happened” comes in the form of a `Msg`, which can be any type. +Messages are the result of some I/O that took place, such as a keypress, timer +tick, or a response from a server. + +We usually figure out which type of `Msg` we received with a type switch, but +you could also use a type assertion. + +For now, we'll just deal with `tea.KeyMsg` messages, which are automatically +sent to the update function when keys are pressed. + +```go +func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { + switch msg := msg.(type) { + + // Is it a key press? + case tea.KeyMsg: + + // Cool, what was the actual key pressed? + switch msg.String() { + + // These keys should exit the program. + case "ctrl+c", "q": + return m, tea.Quit + + // The "up" and "k" keys move the cursor up + case "up", "k": + if m.cursor > 0 { + m.cursor-- + } + + // The "down" and "j" keys move the cursor down + case "down", "j": + if m.cursor < len(m.choices)-1 { + m.cursor++ + } + + // The "enter" key and the spacebar (a literal space) toggle + // the selected state for the item that the cursor is pointing at. + case "enter", " ": + _, ok := m.selected[m.cursor] + if ok { + delete(m.selected, m.cursor) + } else { + m.selected[m.cursor] = struct{}{} + } + } + } + + // Return the updated model to the Bubble Tea runtime for processing. + // Note that we're not returning a command. + return m, nil +} +``` + +You may have noticed that ctrl+c and q above return +a `tea.Quit` command with the model. That’s a special command which instructs +the Bubble Tea runtime to quit, exiting the program. + +### The View Method + +At last, it’s time to render our UI. Of all the methods, the view is the +simplest. We look at the model in its current state and use it to return +a `string`. That string is our UI! + +Because the view describes the entire UI of your application, you don’t have to +worry about redrawing logic and stuff like that. Bubble Tea takes care of it +for you. + +```go +func (m model) View() string { + // The header + s := "What should we buy at the market?\n\n" + + // Iterate over our choices + for i, choice := range m.choices { + + // Is the cursor pointing at this choice? + cursor := " " // no cursor + if m.cursor == i { + cursor = ">" // cursor! + } + + // Is this choice selected? + checked := " " // not selected + if _, ok := m.selected[i]; ok { + checked = "x" // selected! + } + + // Render the row + s += fmt.Sprintf("%s [%s] %s\n", cursor, checked, choice) + } + + // The footer + s += "\nPress q to quit.\n" + + // Send the UI for rendering + return s +} +``` + +### All Together Now + +The last step is to simply run our program. We pass our initial model to +`tea.NewProgram` and let it rip: + +```go +func main() { + p := tea.NewProgram(initialModel()) + if _, err := p.Run(); err != nil { + fmt.Printf("Alas, there's been an error: %v", err) + os.Exit(1) + } +} +``` + +## What’s Next? + +This tutorial covers the basics of building an interactive terminal UI, but +in the real world you'll also need to perform I/O. To learn about that have a +look at the [Command Tutorial][cmd]. It's pretty simple. + +There are also several [Bubble Tea examples][examples] available and, of course, +there are [Go Docs][docs]. + +[cmd]: https://github.com/charmbracelet/bubbletea/tree/main/tutorials/commands/ +[examples]: https://github.com/charmbracelet/bubbletea/tree/main/examples +[docs]: https://pkg.go.dev/github.com/charmbracelet/bubbletea?tab=doc + +## Debugging + +### Debugging with Delve + +Since Bubble Tea apps assume control of stdin and stdout, you’ll need to run +delve in headless mode and then connect to it: + +```bash +# Start the debugger +$ dlv debug --headless --api-version=2 --listen=127.0.0.1:43000 . +API server listening at: 127.0.0.1:43000 + +# Connect to it from another terminal +$ dlv connect 127.0.0.1:43000 +``` + +If you do not explicitly supply the `--listen` flag, the port used will vary +per run, so passing this in makes the debugger easier to use from a script +or your IDE of choice. + +Additionally, we pass in `--api-version=2` because delve defaults to version 1 +for backwards compatibility reasons. However, delve recommends using version 2 +for all new development and some clients may no longer work with version 1. +For more information, see the [Delve documentation](https://github.com/go-delve/delve/tree/master/Documentation/api). + +### Logging Stuff + +You can’t really log to stdout with Bubble Tea because your TUI is busy +occupying that! You can, however, log to a file by including something like +the following prior to starting your Bubble Tea program: + +```go +if len(os.Getenv("DEBUG")) > 0 { + f, err := tea.LogToFile("debug.log", "debug") + if err != nil { + fmt.Println("fatal:", err) + os.Exit(1) + } + defer f.Close() +} +``` + +To see what’s being logged in real time, run `tail -f debug.log` while you run +your program in another window. + +## Libraries we use with Bubble Tea + +- [Bubbles][bubbles]: Common Bubble Tea components such as text inputs, viewports, spinners and so on +- [Lip Gloss][lipgloss]: Style, format and layout tools for terminal applications +- [Harmonica][harmonica]: A spring animation library for smooth, natural motion +- [BubbleZone][bubblezone]: Easy mouse event tracking for Bubble Tea components +- [ntcharts][ntcharts]: A terminal charting library built for Bubble Tea and [Lip Gloss][lipgloss] + +[bubbles]: https://github.com/charmbracelet/bubbles +[lipgloss]: https://github.com/charmbracelet/lipgloss +[harmonica]: https://github.com/charmbracelet/harmonica +[bubblezone]: https://github.com/lrstanley/bubblezone +[ntcharts]: https://github.com/NimbleMarkets/ntcharts + +## Bubble Tea in the Wild + +There are over [10,000 applications](https://github.com/charmbracelet/bubbletea/network/dependents) built with Bubble Tea! Here are a handful of ’em. + +### Staff favourites + +- [chezmoi](https://github.com/twpayne/chezmoi): securely manage your dotfiles across multiple machines +- [circumflex](https://github.com/bensadeh/circumflex): read Hacker News in the terminal +- [gh-dash](https://www.github.com/dlvhdr/gh-dash): a GitHub CLI extension for PRs and issues +- [Tetrigo](https://github.com/Broderick-Westrope/tetrigo): Tetris in the terminal +- [Signls](https://github.com/emprcl/signls): a generative midi sequencer designed for composition and live performance +- [Superfile](https://github.com/yorukot/superfile): a super file manager + +### In Industry + +- Microsoft Azure – [Aztify](https://github.com/Azure/aztfy): bring Microsoft Azure resources under Terraform +- Daytona – [Daytona](https://github.com/daytonaio/daytona): open source dev environment manager +- Cockroach Labs – [CockroachDB](https://github.com/cockroachdb/cockroach): a cloud-native, high-availability distributed SQL database +- Truffle Security Co. – [Trufflehog](https://github.com/trufflesecurity/trufflehog): find leaked credentials +- NVIDIA – [container-canary](https://github.com/NVIDIA/container-canary): a container validator +- AWS – [eks-node-viewer](https://github.com/awslabs/eks-node-viewer): a tool for visualizing dynamic node usage within an EKS cluster +- MinIO – [mc](https://github.com/minio/mc): the official [MinIO](https://min.io) client +- Ubuntu – [Authd](https://github.com/ubuntu/authd): an authentication daemon for cloud-based identity providers + +### Charm stuff + +- [Glow](https://github.com/charmbracelet/glow): a markdown reader, browser, and online markdown stash +- [Huh?](https://github.com/charmbracelet/huh): an interactive prompt and form toolkit +- [Mods](https://github.com/charmbracelet/mods): AI on the CLI, built for pipelines +- [Wishlist](https://github.com/charmbracelet/wishlist): an SSH directory (and bastion!) + +### There’s so much more where that came from + +For more applications built with Bubble Tea see [Charm & Friends][community]. +Is there something cool you made with Bubble Tea you want to share? [PRs][community] are +welcome! + +## Contributing + +See [contributing][contribute]. + +[contribute]: https://github.com/charmbracelet/bubbletea/contribute + +## Feedback + +We’d love to hear your thoughts on this project. Feel free to drop us a note! + +- [Twitter](https://twitter.com/charmcli) +- [The Fediverse](https://mastodon.social/@charmcli) +- [Discord](https://charm.sh/chat) + +## Acknowledgments + +Bubble Tea is based on the paradigms of [The Elm Architecture][elm] by Evan +Czaplicki et alia and the excellent [go-tea][gotea] by TJ Holowaychuk. It’s +inspired by the many great [_Zeichenorientierte Benutzerschnittstellen_][zb] +of days past. + +[elm]: https://guide.elm-lang.org/architecture/ +[gotea]: https://github.com/tj/go-tea +[zb]: https://de.wikipedia.org/wiki/Zeichenorientierte_Benutzerschnittstelle +[community]: https://github.com/charm-and-friends/charm-in-the-wild + +## License + +[MIT](https://github.com/charmbracelet/bubbletea/raw/main/LICENSE) + +--- + +Part of [Charm](https://charm.sh). + +The Charm logo + +Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة diff --git a/vendor/github.com/charmbracelet/bubbletea/Taskfile.yaml b/vendor/github.com/charmbracelet/bubbletea/Taskfile.yaml new file mode 100644 index 00000000..35072035 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/Taskfile.yaml @@ -0,0 +1,14 @@ +# https://taskfile.dev + +version: '3' + +tasks: + lint: + desc: Run lint + cmds: + - golangci-lint run + + test: + desc: Run tests + cmds: + - go test ./... {{.CLI_ARGS}} diff --git a/vendor/github.com/charmbracelet/bubbletea/commands.go b/vendor/github.com/charmbracelet/bubbletea/commands.go new file mode 100644 index 00000000..bfa3b704 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/commands.go @@ -0,0 +1,216 @@ +package tea + +import ( + "time" +) + +// Batch performs a bunch of commands concurrently with no ordering guarantees +// about the results. Use a Batch to return several commands. +// +// Example: +// +// func (m model) Init() Cmd { +// return tea.Batch(someCommand, someOtherCommand) +// } +func Batch(cmds ...Cmd) Cmd { + var validCmds []Cmd //nolint:prealloc + for _, c := range cmds { + if c == nil { + continue + } + validCmds = append(validCmds, c) + } + switch len(validCmds) { + case 0: + return nil + case 1: + return validCmds[0] + default: + return func() Msg { + return BatchMsg(validCmds) + } + } +} + +// BatchMsg is a message used to perform a bunch of commands concurrently with +// no ordering guarantees. You can send a BatchMsg with Batch. +type BatchMsg []Cmd + +// Sequence runs the given commands one at a time, in order. Contrast this with +// Batch, which runs commands concurrently. +func Sequence(cmds ...Cmd) Cmd { + return func() Msg { + return sequenceMsg(cmds) + } +} + +// sequenceMsg is used internally to run the given commands in order. +type sequenceMsg []Cmd + +// Every is a command that ticks in sync with the system clock. So, if you +// wanted to tick with the system clock every second, minute or hour you +// could use this. It's also handy for having different things tick in sync. +// +// Because we're ticking with the system clock the tick will likely not run for +// the entire specified duration. For example, if we're ticking for one minute +// and the clock is at 12:34:20 then the next tick will happen at 12:35:00, 40 +// seconds later. +// +// To produce the command, pass a duration and a function which returns +// a message containing the time at which the tick occurred. +// +// type TickMsg time.Time +// +// cmd := Every(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) +// +// Beginners' note: Every sends a single message and won't automatically +// dispatch messages at an interval. To do that, you'll want to return another +// Every command after receiving your tick message. For example: +// +// type TickMsg time.Time +// +// // Send a message every second. +// func tickEvery() Cmd { +// return Every(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) +// } +// +// func (m model) Init() Cmd { +// // Start ticking. +// return tickEvery() +// } +// +// func (m model) Update(msg Msg) (Model, Cmd) { +// switch msg.(type) { +// case TickMsg: +// // Return your Every command again to loop. +// return m, tickEvery() +// } +// return m, nil +// } +// +// Every is analogous to Tick in the Elm Architecture. +func Every(duration time.Duration, fn func(time.Time) Msg) Cmd { + n := time.Now() + d := n.Truncate(duration).Add(duration).Sub(n) + t := time.NewTimer(d) + return func() Msg { + ts := <-t.C + t.Stop() + for len(t.C) > 0 { + <-t.C + } + return fn(ts) + } +} + +// Tick produces a command at an interval independent of the system clock at +// the given duration. That is, the timer begins precisely when invoked, +// and runs for its entire duration. +// +// To produce the command, pass a duration and a function which returns +// a message containing the time at which the tick occurred. +// +// type TickMsg time.Time +// +// cmd := Tick(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) +// +// Beginners' note: Tick sends a single message and won't automatically +// dispatch messages at an interval. To do that, you'll want to return another +// Tick command after receiving your tick message. For example: +// +// type TickMsg time.Time +// +// func doTick() Cmd { +// return Tick(time.Second, func(t time.Time) Msg { +// return TickMsg(t) +// }) +// } +// +// func (m model) Init() Cmd { +// // Start ticking. +// return doTick() +// } +// +// func (m model) Update(msg Msg) (Model, Cmd) { +// switch msg.(type) { +// case TickMsg: +// // Return your Tick command again to loop. +// return m, doTick() +// } +// return m, nil +// } +func Tick(d time.Duration, fn func(time.Time) Msg) Cmd { + t := time.NewTimer(d) + return func() Msg { + ts := <-t.C + t.Stop() + for len(t.C) > 0 { + <-t.C + } + return fn(ts) + } +} + +// Sequentially produces a command that sequentially executes the given +// commands. +// The Msg returned is the first non-nil message returned by a Cmd. +// +// func saveStateCmd() Msg { +// if err := save(); err != nil { +// return errMsg{err} +// } +// return nil +// } +// +// cmd := Sequentially(saveStateCmd, Quit) +// +// Deprecated: use Sequence instead. +func Sequentially(cmds ...Cmd) Cmd { + return func() Msg { + for _, cmd := range cmds { + if cmd == nil { + continue + } + if msg := cmd(); msg != nil { + return msg + } + } + return nil + } +} + +// setWindowTitleMsg is an internal message used to set the window title. +type setWindowTitleMsg string + +// SetWindowTitle produces a command that sets the terminal title. +// +// For example: +// +// func (m model) Init() Cmd { +// // Set title. +// return tea.SetWindowTitle("My App") +// } +func SetWindowTitle(title string) Cmd { + return func() Msg { + return setWindowTitleMsg(title) + } +} + +type windowSizeMsg struct{} + +// WindowSize is a command that queries the terminal for its current size. It +// delivers the results to Update via a [WindowSizeMsg]. Keep in mind that +// WindowSizeMsgs will automatically be delivered to Update when the [Program] +// starts and when the window dimensions change so in many cases you will not +// need to explicitly invoke this command. +func WindowSize() Cmd { + return func() Msg { + return windowSizeMsg{} + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/exec.go b/vendor/github.com/charmbracelet/bubbletea/exec.go new file mode 100644 index 00000000..80484145 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/exec.go @@ -0,0 +1,133 @@ +package tea + +import ( + "io" + "os" + "os/exec" +) + +// execMsg is used internally to run an ExecCommand sent with Exec. +type execMsg struct { + cmd ExecCommand + fn ExecCallback +} + +// Exec is used to perform arbitrary I/O in a blocking fashion, effectively +// pausing the Program while execution is running and resuming it when +// execution has completed. +// +// Most of the time you'll want to use ExecProcess, which runs an exec.Cmd. +// +// For non-interactive i/o you should use a Cmd (that is, a tea.Cmd). +func Exec(c ExecCommand, fn ExecCallback) Cmd { + return func() Msg { + return execMsg{cmd: c, fn: fn} + } +} + +// ExecProcess runs the given *exec.Cmd in a blocking fashion, effectively +// pausing the Program while the command is running. After the *exec.Cmd exists +// the Program resumes. It's useful for spawning other interactive applications +// such as editors and shells from within a Program. +// +// To produce the command, pass an *exec.Cmd and a function which returns +// a message containing the error which may have occurred when running the +// ExecCommand. +// +// type VimFinishedMsg struct { err error } +// +// c := exec.Command("vim", "file.txt") +// +// cmd := ExecProcess(c, func(err error) Msg { +// return VimFinishedMsg{err: err} +// }) +// +// Or, if you don't care about errors, you could simply: +// +// cmd := ExecProcess(exec.Command("vim", "file.txt"), nil) +// +// For non-interactive i/o you should use a Cmd (that is, a tea.Cmd). +func ExecProcess(c *exec.Cmd, fn ExecCallback) Cmd { + return Exec(wrapExecCommand(c), fn) +} + +// ExecCallback is used when executing an *exec.Command to return a message +// with an error, which may or may not be nil. +type ExecCallback func(error) Msg + +// ExecCommand can be implemented to execute things in a blocking fashion in +// the current terminal. +type ExecCommand interface { + Run() error + SetStdin(io.Reader) + SetStdout(io.Writer) + SetStderr(io.Writer) +} + +// wrapExecCommand wraps an exec.Cmd so that it satisfies the ExecCommand +// interface so it can be used with Exec. +func wrapExecCommand(c *exec.Cmd) ExecCommand { + return &osExecCommand{Cmd: c} +} + +// osExecCommand is a layer over an exec.Cmd that satisfies the ExecCommand +// interface. +type osExecCommand struct{ *exec.Cmd } + +// SetStdin sets stdin on underlying exec.Cmd to the given io.Reader. +func (c *osExecCommand) SetStdin(r io.Reader) { + // If unset, have the command use the same input as the terminal. + if c.Stdin == nil { + c.Stdin = r + } +} + +// SetStdout sets stdout on underlying exec.Cmd to the given io.Writer. +func (c *osExecCommand) SetStdout(w io.Writer) { + // If unset, have the command use the same output as the terminal. + if c.Stdout == nil { + c.Stdout = w + } +} + +// SetStderr sets stderr on the underlying exec.Cmd to the given io.Writer. +func (c *osExecCommand) SetStderr(w io.Writer) { + // If unset, use stderr for the command's stderr + if c.Stderr == nil { + c.Stderr = w + } +} + +// exec runs an ExecCommand and delivers the results to the program as a Msg. +func (p *Program) exec(c ExecCommand, fn ExecCallback) { + if err := p.ReleaseTerminal(); err != nil { + // If we can't release input, abort. + if fn != nil { + go p.Send(fn(err)) + } + return + } + + c.SetStdin(p.input) + c.SetStdout(p.output) + c.SetStderr(os.Stderr) + + // Execute system command. + if err := c.Run(); err != nil { + p.renderer.resetLinesRendered() + _ = p.RestoreTerminal() // also try to restore the terminal. + if fn != nil { + go p.Send(fn(err)) + } + return + } + + // Maintain the existing output from the command + p.renderer.resetLinesRendered() + + // Have the program re-capture input. + err := p.RestoreTerminal() + if fn != nil { + go p.Send(fn(err)) + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/focus.go b/vendor/github.com/charmbracelet/bubbletea/focus.go new file mode 100644 index 00000000..4d34bea6 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/focus.go @@ -0,0 +1,9 @@ +package tea + +// FocusMsg represents a terminal focus message. +// This occurs when the terminal gains focus. +type FocusMsg struct{} + +// BlurMsg represents a terminal blur message. +// This occurs when the terminal loses focus. +type BlurMsg struct{} diff --git a/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go b/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go new file mode 100644 index 00000000..1d1b1761 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/inputreader_other.go @@ -0,0 +1,19 @@ +//go:build !windows +// +build !windows + +package tea + +import ( + "fmt" + "io" + + "github.com/muesli/cancelreader" +) + +func newInputReader(r io.Reader, _ bool) (cancelreader.CancelReader, error) { + cr, err := cancelreader.NewReader(r) + if err != nil { + return nil, fmt.Errorf("bubbletea: error creating cancel reader: %w", err) + } + return cr, nil +} diff --git a/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go b/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go new file mode 100644 index 00000000..d76617d3 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/inputreader_windows.go @@ -0,0 +1,129 @@ +//go:build windows +// +build windows + +package tea + +import ( + "fmt" + "io" + "os" + "sync" + + "github.com/charmbracelet/x/term" + "github.com/erikgeiser/coninput" + "github.com/muesli/cancelreader" + "golang.org/x/sys/windows" +) + +type conInputReader struct { + cancelMixin + + conin windows.Handle + + originalMode uint32 +} + +var _ cancelreader.CancelReader = &conInputReader{} + +func newInputReader(r io.Reader, enableMouse bool) (cancelreader.CancelReader, error) { + fallback := func(io.Reader) (cancelreader.CancelReader, error) { + return cancelreader.NewReader(r) + } + if f, ok := r.(term.File); !ok || f.Fd() != os.Stdin.Fd() { + return fallback(r) + } + + conin, err := coninput.NewStdinHandle() + if err != nil { + return fallback(r) + } + + modes := []uint32{ + windows.ENABLE_WINDOW_INPUT, + windows.ENABLE_EXTENDED_FLAGS, + } + + // Since we have options to enable mouse events, [WithMouseCellMotion], + // [WithMouseAllMotion], and [EnableMouseCellMotion], + // [EnableMouseAllMotion], and [DisableMouse], we need to check if the user + // has enabled mouse events and add the appropriate mode accordingly. + // Otherwise, mouse events will be enabled all the time. + if enableMouse { + modes = append(modes, windows.ENABLE_MOUSE_INPUT) + } + + originalMode, err := prepareConsole(conin, modes...) + if err != nil { + return nil, fmt.Errorf("failed to prepare console input: %w", err) + } + + return &conInputReader{ + conin: conin, + originalMode: originalMode, + }, nil +} + +// Cancel implements cancelreader.CancelReader. +func (r *conInputReader) Cancel() bool { + r.setCanceled() + + // Warning: These cancel methods do not reliably work on console input + // and should not be counted on. + return windows.CancelIoEx(r.conin, nil) == nil || windows.CancelIo(r.conin) == nil +} + +// Close implements cancelreader.CancelReader. +func (r *conInputReader) Close() error { + if r.originalMode != 0 { + err := windows.SetConsoleMode(r.conin, r.originalMode) + if err != nil { + return fmt.Errorf("reset console mode: %w", err) + } + } + + return nil +} + +// Read implements cancelreader.CancelReader. +func (r *conInputReader) Read(_ []byte) (n int, err error) { + if r.isCanceled() { + err = cancelreader.ErrCanceled + } + return +} + +func prepareConsole(input windows.Handle, modes ...uint32) (originalMode uint32, err error) { + err = windows.GetConsoleMode(input, &originalMode) + if err != nil { + return 0, fmt.Errorf("get console mode: %w", err) + } + + newMode := coninput.AddInputModes(0, modes...) + + err = windows.SetConsoleMode(input, newMode) + if err != nil { + return 0, fmt.Errorf("set console mode: %w", err) + } + + return originalMode, nil +} + +// cancelMixin represents a goroutine-safe cancelation status. +type cancelMixin struct { + unsafeCanceled bool + lock sync.Mutex +} + +func (c *cancelMixin) setCanceled() { + c.lock.Lock() + defer c.lock.Unlock() + + c.unsafeCanceled = true +} + +func (c *cancelMixin) isCanceled() bool { + c.lock.Lock() + defer c.lock.Unlock() + + return c.unsafeCanceled +} diff --git a/vendor/github.com/charmbracelet/bubbletea/key.go b/vendor/github.com/charmbracelet/bubbletea/key.go new file mode 100644 index 00000000..12a161a7 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/key.go @@ -0,0 +1,715 @@ +package tea + +import ( + "context" + "fmt" + "io" + "regexp" + "strings" + "unicode/utf8" +) + +// KeyMsg contains information about a keypress. KeyMsgs are always sent to +// the program's update function. There are a couple general patterns you could +// use to check for keypresses: +// +// // Switch on the string representation of the key (shorter) +// switch msg := msg.(type) { +// case KeyMsg: +// switch msg.String() { +// case "enter": +// fmt.Println("you pressed enter!") +// case "a": +// fmt.Println("you pressed a!") +// } +// } +// +// // Switch on the key type (more foolproof) +// switch msg := msg.(type) { +// case KeyMsg: +// switch msg.Type { +// case KeyEnter: +// fmt.Println("you pressed enter!") +// case KeyRunes: +// switch string(msg.Runes) { +// case "a": +// fmt.Println("you pressed a!") +// } +// } +// } +// +// Note that Key.Runes will always contain at least one character, so you can +// always safely call Key.Runes[0]. In most cases Key.Runes will only contain +// one character, though certain input method editors (most notably Chinese +// IMEs) can input multiple runes at once. +type KeyMsg Key + +// String returns a string representation for a key message. It's safe (and +// encouraged) for use in key comparison. +func (k KeyMsg) String() (str string) { + return Key(k).String() +} + +// Key contains information about a keypress. +type Key struct { + Type KeyType + Runes []rune + Alt bool + Paste bool +} + +// String returns a friendly string representation for a key. It's safe (and +// encouraged) for use in key comparison. +// +// k := Key{Type: KeyEnter} +// fmt.Println(k) +// // Output: enter +func (k Key) String() (str string) { + var buf strings.Builder + if k.Alt { + buf.WriteString("alt+") + } + if k.Type == KeyRunes { + if k.Paste { + // Note: bubbles/keys bindings currently do string compares to + // recognize shortcuts. Since pasted text should never activate + // shortcuts, we need to ensure that the binding code doesn't + // match Key events that result from pastes. We achieve this + // here by enclosing pastes in '[...]' so that the string + // comparison in Matches() fails in that case. + buf.WriteByte('[') + } + buf.WriteString(string(k.Runes)) + if k.Paste { + buf.WriteByte(']') + } + return buf.String() + } else if s, ok := keyNames[k.Type]; ok { + buf.WriteString(s) + return buf.String() + } + return "" +} + +// KeyType indicates the key pressed, such as KeyEnter or KeyBreak or KeyCtrlC. +// All other keys will be type KeyRunes. To get the rune value, check the Rune +// method on a Key struct, or use the Key.String() method: +// +// k := Key{Type: KeyRunes, Runes: []rune{'a'}, Alt: true} +// if k.Type == KeyRunes { +// +// fmt.Println(k.Runes) +// // Output: a +// +// fmt.Println(k.String()) +// // Output: alt+a +// +// } +type KeyType int + +func (k KeyType) String() (str string) { + if s, ok := keyNames[k]; ok { + return s + } + return "" +} + +// Control keys. We could do this with an iota, but the values are very +// specific, so we set the values explicitly to avoid any confusion. +// +// See also: +// https://en.wikipedia.org/wiki/C0_and_C1_control_codes +const ( + keyNUL KeyType = 0 // null, \0 + keySOH KeyType = 1 // start of heading + keySTX KeyType = 2 // start of text + keyETX KeyType = 3 // break, ctrl+c + keyEOT KeyType = 4 // end of transmission + keyENQ KeyType = 5 // enquiry + keyACK KeyType = 6 // acknowledge + keyBEL KeyType = 7 // bell, \a + keyBS KeyType = 8 // backspace + keyHT KeyType = 9 // horizontal tabulation, \t + keyLF KeyType = 10 // line feed, \n + keyVT KeyType = 11 // vertical tabulation \v + keyFF KeyType = 12 // form feed \f + keyCR KeyType = 13 // carriage return, \r + keySO KeyType = 14 // shift out + keySI KeyType = 15 // shift in + keyDLE KeyType = 16 // data link escape + keyDC1 KeyType = 17 // device control one + keyDC2 KeyType = 18 // device control two + keyDC3 KeyType = 19 // device control three + keyDC4 KeyType = 20 // device control four + keyNAK KeyType = 21 // negative acknowledge + keySYN KeyType = 22 // synchronous idle + keyETB KeyType = 23 // end of transmission block + keyCAN KeyType = 24 // cancel + keyEM KeyType = 25 // end of medium + keySUB KeyType = 26 // substitution + keyESC KeyType = 27 // escape, \e + keyFS KeyType = 28 // file separator + keyGS KeyType = 29 // group separator + keyRS KeyType = 30 // record separator + keyUS KeyType = 31 // unit separator + keyDEL KeyType = 127 // delete. on most systems this is mapped to backspace, I hear +) + +// Control key aliases. +const ( + KeyNull KeyType = keyNUL + KeyBreak KeyType = keyETX + KeyEnter KeyType = keyCR + KeyBackspace KeyType = keyDEL + KeyTab KeyType = keyHT + KeyEsc KeyType = keyESC + KeyEscape KeyType = keyESC + + KeyCtrlAt KeyType = keyNUL // ctrl+@ + KeyCtrlA KeyType = keySOH + KeyCtrlB KeyType = keySTX + KeyCtrlC KeyType = keyETX + KeyCtrlD KeyType = keyEOT + KeyCtrlE KeyType = keyENQ + KeyCtrlF KeyType = keyACK + KeyCtrlG KeyType = keyBEL + KeyCtrlH KeyType = keyBS + KeyCtrlI KeyType = keyHT + KeyCtrlJ KeyType = keyLF + KeyCtrlK KeyType = keyVT + KeyCtrlL KeyType = keyFF + KeyCtrlM KeyType = keyCR + KeyCtrlN KeyType = keySO + KeyCtrlO KeyType = keySI + KeyCtrlP KeyType = keyDLE + KeyCtrlQ KeyType = keyDC1 + KeyCtrlR KeyType = keyDC2 + KeyCtrlS KeyType = keyDC3 + KeyCtrlT KeyType = keyDC4 + KeyCtrlU KeyType = keyNAK + KeyCtrlV KeyType = keySYN + KeyCtrlW KeyType = keyETB + KeyCtrlX KeyType = keyCAN + KeyCtrlY KeyType = keyEM + KeyCtrlZ KeyType = keySUB + KeyCtrlOpenBracket KeyType = keyESC // ctrl+[ + KeyCtrlBackslash KeyType = keyFS // ctrl+\ + KeyCtrlCloseBracket KeyType = keyGS // ctrl+] + KeyCtrlCaret KeyType = keyRS // ctrl+^ + KeyCtrlUnderscore KeyType = keyUS // ctrl+_ + KeyCtrlQuestionMark KeyType = keyDEL // ctrl+? +) + +// Other keys. +const ( + KeyRunes KeyType = -(iota + 1) + KeyUp + KeyDown + KeyRight + KeyLeft + KeyShiftTab + KeyHome + KeyEnd + KeyPgUp + KeyPgDown + KeyCtrlPgUp + KeyCtrlPgDown + KeyDelete + KeyInsert + KeySpace + KeyCtrlUp + KeyCtrlDown + KeyCtrlRight + KeyCtrlLeft + KeyCtrlHome + KeyCtrlEnd + KeyShiftUp + KeyShiftDown + KeyShiftRight + KeyShiftLeft + KeyShiftHome + KeyShiftEnd + KeyCtrlShiftUp + KeyCtrlShiftDown + KeyCtrlShiftLeft + KeyCtrlShiftRight + KeyCtrlShiftHome + KeyCtrlShiftEnd + KeyF1 + KeyF2 + KeyF3 + KeyF4 + KeyF5 + KeyF6 + KeyF7 + KeyF8 + KeyF9 + KeyF10 + KeyF11 + KeyF12 + KeyF13 + KeyF14 + KeyF15 + KeyF16 + KeyF17 + KeyF18 + KeyF19 + KeyF20 +) + +// Mappings for control keys and other special keys to friendly consts. +var keyNames = map[KeyType]string{ + // Control keys. + keyNUL: "ctrl+@", // also ctrl+` (that's ctrl+backtick) + keySOH: "ctrl+a", + keySTX: "ctrl+b", + keyETX: "ctrl+c", + keyEOT: "ctrl+d", + keyENQ: "ctrl+e", + keyACK: "ctrl+f", + keyBEL: "ctrl+g", + keyBS: "ctrl+h", + keyHT: "tab", // also ctrl+i + keyLF: "ctrl+j", + keyVT: "ctrl+k", + keyFF: "ctrl+l", + keyCR: "enter", + keySO: "ctrl+n", + keySI: "ctrl+o", + keyDLE: "ctrl+p", + keyDC1: "ctrl+q", + keyDC2: "ctrl+r", + keyDC3: "ctrl+s", + keyDC4: "ctrl+t", + keyNAK: "ctrl+u", + keySYN: "ctrl+v", + keyETB: "ctrl+w", + keyCAN: "ctrl+x", + keyEM: "ctrl+y", + keySUB: "ctrl+z", + keyESC: "esc", + keyFS: "ctrl+\\", + keyGS: "ctrl+]", + keyRS: "ctrl+^", + keyUS: "ctrl+_", + keyDEL: "backspace", + + // Other keys. + KeyRunes: "runes", + KeyUp: "up", + KeyDown: "down", + KeyRight: "right", + KeySpace: " ", // for backwards compatibility + KeyLeft: "left", + KeyShiftTab: "shift+tab", + KeyHome: "home", + KeyEnd: "end", + KeyCtrlHome: "ctrl+home", + KeyCtrlEnd: "ctrl+end", + KeyShiftHome: "shift+home", + KeyShiftEnd: "shift+end", + KeyCtrlShiftHome: "ctrl+shift+home", + KeyCtrlShiftEnd: "ctrl+shift+end", + KeyPgUp: "pgup", + KeyPgDown: "pgdown", + KeyCtrlPgUp: "ctrl+pgup", + KeyCtrlPgDown: "ctrl+pgdown", + KeyDelete: "delete", + KeyInsert: "insert", + KeyCtrlUp: "ctrl+up", + KeyCtrlDown: "ctrl+down", + KeyCtrlRight: "ctrl+right", + KeyCtrlLeft: "ctrl+left", + KeyShiftUp: "shift+up", + KeyShiftDown: "shift+down", + KeyShiftRight: "shift+right", + KeyShiftLeft: "shift+left", + KeyCtrlShiftUp: "ctrl+shift+up", + KeyCtrlShiftDown: "ctrl+shift+down", + KeyCtrlShiftLeft: "ctrl+shift+left", + KeyCtrlShiftRight: "ctrl+shift+right", + KeyF1: "f1", + KeyF2: "f2", + KeyF3: "f3", + KeyF4: "f4", + KeyF5: "f5", + KeyF6: "f6", + KeyF7: "f7", + KeyF8: "f8", + KeyF9: "f9", + KeyF10: "f10", + KeyF11: "f11", + KeyF12: "f12", + KeyF13: "f13", + KeyF14: "f14", + KeyF15: "f15", + KeyF16: "f16", + KeyF17: "f17", + KeyF18: "f18", + KeyF19: "f19", + KeyF20: "f20", +} + +// Sequence mappings. +var sequences = map[string]Key{ + // Arrow keys + "\x1b[A": {Type: KeyUp}, + "\x1b[B": {Type: KeyDown}, + "\x1b[C": {Type: KeyRight}, + "\x1b[D": {Type: KeyLeft}, + "\x1b[1;2A": {Type: KeyShiftUp}, + "\x1b[1;2B": {Type: KeyShiftDown}, + "\x1b[1;2C": {Type: KeyShiftRight}, + "\x1b[1;2D": {Type: KeyShiftLeft}, + "\x1b[OA": {Type: KeyShiftUp}, // DECCKM + "\x1b[OB": {Type: KeyShiftDown}, // DECCKM + "\x1b[OC": {Type: KeyShiftRight}, // DECCKM + "\x1b[OD": {Type: KeyShiftLeft}, // DECCKM + "\x1b[a": {Type: KeyShiftUp}, // urxvt + "\x1b[b": {Type: KeyShiftDown}, // urxvt + "\x1b[c": {Type: KeyShiftRight}, // urxvt + "\x1b[d": {Type: KeyShiftLeft}, // urxvt + "\x1b[1;3A": {Type: KeyUp, Alt: true}, + "\x1b[1;3B": {Type: KeyDown, Alt: true}, + "\x1b[1;3C": {Type: KeyRight, Alt: true}, + "\x1b[1;3D": {Type: KeyLeft, Alt: true}, + + "\x1b[1;4A": {Type: KeyShiftUp, Alt: true}, + "\x1b[1;4B": {Type: KeyShiftDown, Alt: true}, + "\x1b[1;4C": {Type: KeyShiftRight, Alt: true}, + "\x1b[1;4D": {Type: KeyShiftLeft, Alt: true}, + + "\x1b[1;5A": {Type: KeyCtrlUp}, + "\x1b[1;5B": {Type: KeyCtrlDown}, + "\x1b[1;5C": {Type: KeyCtrlRight}, + "\x1b[1;5D": {Type: KeyCtrlLeft}, + "\x1b[Oa": {Type: KeyCtrlUp, Alt: true}, // urxvt + "\x1b[Ob": {Type: KeyCtrlDown, Alt: true}, // urxvt + "\x1b[Oc": {Type: KeyCtrlRight, Alt: true}, // urxvt + "\x1b[Od": {Type: KeyCtrlLeft, Alt: true}, // urxvt + "\x1b[1;6A": {Type: KeyCtrlShiftUp}, + "\x1b[1;6B": {Type: KeyCtrlShiftDown}, + "\x1b[1;6C": {Type: KeyCtrlShiftRight}, + "\x1b[1;6D": {Type: KeyCtrlShiftLeft}, + "\x1b[1;7A": {Type: KeyCtrlUp, Alt: true}, + "\x1b[1;7B": {Type: KeyCtrlDown, Alt: true}, + "\x1b[1;7C": {Type: KeyCtrlRight, Alt: true}, + "\x1b[1;7D": {Type: KeyCtrlLeft, Alt: true}, + "\x1b[1;8A": {Type: KeyCtrlShiftUp, Alt: true}, + "\x1b[1;8B": {Type: KeyCtrlShiftDown, Alt: true}, + "\x1b[1;8C": {Type: KeyCtrlShiftRight, Alt: true}, + "\x1b[1;8D": {Type: KeyCtrlShiftLeft, Alt: true}, + + // Miscellaneous keys + "\x1b[Z": {Type: KeyShiftTab}, + + "\x1b[2~": {Type: KeyInsert}, + "\x1b[3;2~": {Type: KeyInsert, Alt: true}, + + "\x1b[3~": {Type: KeyDelete}, + "\x1b[3;3~": {Type: KeyDelete, Alt: true}, + + "\x1b[5~": {Type: KeyPgUp}, + "\x1b[5;3~": {Type: KeyPgUp, Alt: true}, + "\x1b[5;5~": {Type: KeyCtrlPgUp}, + "\x1b[5^": {Type: KeyCtrlPgUp}, // urxvt + "\x1b[5;7~": {Type: KeyCtrlPgUp, Alt: true}, + + "\x1b[6~": {Type: KeyPgDown}, + "\x1b[6;3~": {Type: KeyPgDown, Alt: true}, + "\x1b[6;5~": {Type: KeyCtrlPgDown}, + "\x1b[6^": {Type: KeyCtrlPgDown}, // urxvt + "\x1b[6;7~": {Type: KeyCtrlPgDown, Alt: true}, + + "\x1b[1~": {Type: KeyHome}, + "\x1b[H": {Type: KeyHome}, // xterm, lxterm + "\x1b[1;3H": {Type: KeyHome, Alt: true}, // xterm, lxterm + "\x1b[1;5H": {Type: KeyCtrlHome}, // xterm, lxterm + "\x1b[1;7H": {Type: KeyCtrlHome, Alt: true}, // xterm, lxterm + "\x1b[1;2H": {Type: KeyShiftHome}, // xterm, lxterm + "\x1b[1;4H": {Type: KeyShiftHome, Alt: true}, // xterm, lxterm + "\x1b[1;6H": {Type: KeyCtrlShiftHome}, // xterm, lxterm + "\x1b[1;8H": {Type: KeyCtrlShiftHome, Alt: true}, // xterm, lxterm + + "\x1b[4~": {Type: KeyEnd}, + "\x1b[F": {Type: KeyEnd}, // xterm, lxterm + "\x1b[1;3F": {Type: KeyEnd, Alt: true}, // xterm, lxterm + "\x1b[1;5F": {Type: KeyCtrlEnd}, // xterm, lxterm + "\x1b[1;7F": {Type: KeyCtrlEnd, Alt: true}, // xterm, lxterm + "\x1b[1;2F": {Type: KeyShiftEnd}, // xterm, lxterm + "\x1b[1;4F": {Type: KeyShiftEnd, Alt: true}, // xterm, lxterm + "\x1b[1;6F": {Type: KeyCtrlShiftEnd}, // xterm, lxterm + "\x1b[1;8F": {Type: KeyCtrlShiftEnd, Alt: true}, // xterm, lxterm + + "\x1b[7~": {Type: KeyHome}, // urxvt + "\x1b[7^": {Type: KeyCtrlHome}, // urxvt + "\x1b[7$": {Type: KeyShiftHome}, // urxvt + "\x1b[7@": {Type: KeyCtrlShiftHome}, // urxvt + + "\x1b[8~": {Type: KeyEnd}, // urxvt + "\x1b[8^": {Type: KeyCtrlEnd}, // urxvt + "\x1b[8$": {Type: KeyShiftEnd}, // urxvt + "\x1b[8@": {Type: KeyCtrlShiftEnd}, // urxvt + + // Function keys, Linux console + "\x1b[[A": {Type: KeyF1}, // linux console + "\x1b[[B": {Type: KeyF2}, // linux console + "\x1b[[C": {Type: KeyF3}, // linux console + "\x1b[[D": {Type: KeyF4}, // linux console + "\x1b[[E": {Type: KeyF5}, // linux console + + // Function keys, X11 + "\x1bOP": {Type: KeyF1}, // vt100, xterm + "\x1bOQ": {Type: KeyF2}, // vt100, xterm + "\x1bOR": {Type: KeyF3}, // vt100, xterm + "\x1bOS": {Type: KeyF4}, // vt100, xterm + + "\x1b[1;3P": {Type: KeyF1, Alt: true}, // vt100, xterm + "\x1b[1;3Q": {Type: KeyF2, Alt: true}, // vt100, xterm + "\x1b[1;3R": {Type: KeyF3, Alt: true}, // vt100, xterm + "\x1b[1;3S": {Type: KeyF4, Alt: true}, // vt100, xterm + + "\x1b[11~": {Type: KeyF1}, // urxvt + "\x1b[12~": {Type: KeyF2}, // urxvt + "\x1b[13~": {Type: KeyF3}, // urxvt + "\x1b[14~": {Type: KeyF4}, // urxvt + + "\x1b[15~": {Type: KeyF5}, // vt100, xterm, also urxvt + + "\x1b[15;3~": {Type: KeyF5, Alt: true}, // vt100, xterm, also urxvt + + "\x1b[17~": {Type: KeyF6}, // vt100, xterm, also urxvt + "\x1b[18~": {Type: KeyF7}, // vt100, xterm, also urxvt + "\x1b[19~": {Type: KeyF8}, // vt100, xterm, also urxvt + "\x1b[20~": {Type: KeyF9}, // vt100, xterm, also urxvt + "\x1b[21~": {Type: KeyF10}, // vt100, xterm, also urxvt + + "\x1b[17;3~": {Type: KeyF6, Alt: true}, // vt100, xterm + "\x1b[18;3~": {Type: KeyF7, Alt: true}, // vt100, xterm + "\x1b[19;3~": {Type: KeyF8, Alt: true}, // vt100, xterm + "\x1b[20;3~": {Type: KeyF9, Alt: true}, // vt100, xterm + "\x1b[21;3~": {Type: KeyF10, Alt: true}, // vt100, xterm + + "\x1b[23~": {Type: KeyF11}, // vt100, xterm, also urxvt + "\x1b[24~": {Type: KeyF12}, // vt100, xterm, also urxvt + + "\x1b[23;3~": {Type: KeyF11, Alt: true}, // vt100, xterm + "\x1b[24;3~": {Type: KeyF12, Alt: true}, // vt100, xterm + + "\x1b[1;2P": {Type: KeyF13}, + "\x1b[1;2Q": {Type: KeyF14}, + + "\x1b[25~": {Type: KeyF13}, // vt100, xterm, also urxvt + "\x1b[26~": {Type: KeyF14}, // vt100, xterm, also urxvt + + "\x1b[25;3~": {Type: KeyF13, Alt: true}, // vt100, xterm + "\x1b[26;3~": {Type: KeyF14, Alt: true}, // vt100, xterm + + "\x1b[1;2R": {Type: KeyF15}, + "\x1b[1;2S": {Type: KeyF16}, + + "\x1b[28~": {Type: KeyF15}, // vt100, xterm, also urxvt + "\x1b[29~": {Type: KeyF16}, // vt100, xterm, also urxvt + + "\x1b[28;3~": {Type: KeyF15, Alt: true}, // vt100, xterm + "\x1b[29;3~": {Type: KeyF16, Alt: true}, // vt100, xterm + + "\x1b[15;2~": {Type: KeyF17}, + "\x1b[17;2~": {Type: KeyF18}, + "\x1b[18;2~": {Type: KeyF19}, + "\x1b[19;2~": {Type: KeyF20}, + + "\x1b[31~": {Type: KeyF17}, + "\x1b[32~": {Type: KeyF18}, + "\x1b[33~": {Type: KeyF19}, + "\x1b[34~": {Type: KeyF20}, + + // Powershell sequences. + "\x1bOA": {Type: KeyUp, Alt: false}, + "\x1bOB": {Type: KeyDown, Alt: false}, + "\x1bOC": {Type: KeyRight, Alt: false}, + "\x1bOD": {Type: KeyLeft, Alt: false}, +} + +// unknownInputByteMsg is reported by the input reader when an invalid +// utf-8 byte is detected on the input. Currently, it is not handled +// further by bubbletea. However, having this event makes it possible +// to troubleshoot invalid inputs. +type unknownInputByteMsg byte + +func (u unknownInputByteMsg) String() string { + return fmt.Sprintf("?%#02x?", int(u)) +} + +// unknownCSISequenceMsg is reported by the input reader when an +// unrecognized CSI sequence is detected on the input. Currently, it +// is not handled further by bubbletea. However, having this event +// makes it possible to troubleshoot invalid inputs. +type unknownCSISequenceMsg []byte + +func (u unknownCSISequenceMsg) String() string { + return fmt.Sprintf("?CSI%+v?", []byte(u)[2:]) +} + +var spaceRunes = []rune{' '} + +// readAnsiInputs reads keypress and mouse inputs from a TTY and produces messages +// containing information about the key or mouse events accordingly. +func readAnsiInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { + var buf [256]byte + + var leftOverFromPrevIteration []byte +loop: + for { + // Read and block. + numBytes, err := input.Read(buf[:]) + if err != nil { + return fmt.Errorf("error reading input: %w", err) + } + b := buf[:numBytes] + if leftOverFromPrevIteration != nil { + b = append(leftOverFromPrevIteration, b...) + } + + // If we had a short read (numBytes < len(buf)), we're sure that + // the end of this read is an event boundary, so there is no doubt + // if we are encountering the end of the buffer while parsing a message. + // However, if we've succeeded in filling up the buffer, there may + // be more data in the OS buffer ready to be read in, to complete + // the last message in the input. In that case, we will retry with + // the left over data in the next iteration. + canHaveMoreData := numBytes == len(buf) + + var i, w int + for i, w = 0, 0; i < len(b); i += w { + var msg Msg + w, msg = detectOneMsg(b[i:], canHaveMoreData) + if w == 0 { + // Expecting more bytes beyond the current buffer. Try waiting + // for more input. + leftOverFromPrevIteration = make([]byte, 0, len(b[i:])+len(buf)) + leftOverFromPrevIteration = append(leftOverFromPrevIteration, b[i:]...) + continue loop + } + + select { + case msgs <- msg: + case <-ctx.Done(): + err := ctx.Err() + if err != nil { + err = fmt.Errorf("found context error while reading input: %w", err) + } + return err + } + } + leftOverFromPrevIteration = nil + } +} + +var ( + unknownCSIRe = regexp.MustCompile(`^\x1b\[[\x30-\x3f]*[\x20-\x2f]*[\x40-\x7e]`) + mouseSGRRegex = regexp.MustCompile(`(\d+);(\d+);(\d+)([Mm])`) +) + +func detectOneMsg(b []byte, canHaveMoreData bool) (w int, msg Msg) { + // Detect mouse events. + // X10 mouse events have a length of 6 bytes + const mouseEventX10Len = 6 + if len(b) >= mouseEventX10Len && b[0] == '\x1b' && b[1] == '[' { + switch b[2] { + case 'M': + return mouseEventX10Len, MouseMsg(parseX10MouseEvent(b)) + case '<': + if matchIndices := mouseSGRRegex.FindSubmatchIndex(b[3:]); matchIndices != nil { + // SGR mouse events length is the length of the match plus the length of the escape sequence + mouseEventSGRLen := matchIndices[1] + 3 //nolint:mnd + return mouseEventSGRLen, MouseMsg(parseSGRMouseEvent(b)) + } + } + } + + // Detect focus events. + var foundRF bool + foundRF, w, msg = detectReportFocus(b) + if foundRF { + return w, msg + } + + // Detect bracketed paste. + var foundbp bool + foundbp, w, msg = detectBracketedPaste(b) + if foundbp { + return w, msg + } + + // Detect escape sequence and control characters other than NUL, + // possibly with an escape character in front to mark the Alt + // modifier. + var foundSeq bool + foundSeq, w, msg = detectSequence(b) + if foundSeq { + return w, msg + } + + // No non-NUL control character or escape sequence. + // If we are seeing at least an escape character, remember it for later below. + alt := false + i := 0 + if b[0] == '\x1b' { + alt = true + i++ + } + + // Are we seeing a standalone NUL? This is not handled by detectSequence(). + if i < len(b) && b[i] == 0 { + return i + 1, KeyMsg{Type: keyNUL, Alt: alt} + } + + // Find the longest sequence of runes that are not control + // characters from this point. + var runes []rune + for rw := 0; i < len(b); i += rw { + var r rune + r, rw = utf8.DecodeRune(b[i:]) + if r == utf8.RuneError || r <= rune(keyUS) || r == rune(keyDEL) || r == ' ' { + // Rune errors are handled below; control characters and spaces will + // be handled by detectSequence in the next call to detectOneMsg. + break + } + runes = append(runes, r) + if alt { + // We only support a single rune after an escape alt modifier. + i += rw + break + } + } + if i >= len(b) && canHaveMoreData { + // We have encountered the end of the input buffer. Alas, we can't + // be sure whether the data in the remainder of the buffer is + // complete (maybe there was a short read). Instead of sending anything + // dumb to the message channel, do a short read. The outer loop will + // handle this case by extending the buffer as necessary. + return 0, nil + } + + // If we found at least one rune, we report the bunch of them as + // a single KeyRunes or KeySpace event. + if len(runes) > 0 { + k := Key{Type: KeyRunes, Runes: runes, Alt: alt} + if len(runes) == 1 && runes[0] == ' ' { + k.Type = KeySpace + } + return i, KeyMsg(k) + } + + // We didn't find an escape sequence, nor a valid rune. Was this a + // lone escape character at the end of the input? + if alt && len(b) == 1 { + return 1, KeyMsg(Key{Type: KeyEscape}) + } + + // The character at the current position is neither an escape + // sequence, a valid rune start or a sole escape character. Report + // it as an invalid byte. + return 1, unknownInputByteMsg(b[0]) +} diff --git a/vendor/github.com/charmbracelet/bubbletea/key_other.go b/vendor/github.com/charmbracelet/bubbletea/key_other.go new file mode 100644 index 00000000..b8c46082 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/key_other.go @@ -0,0 +1,13 @@ +//go:build !windows +// +build !windows + +package tea + +import ( + "context" + "io" +) + +func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { + return readAnsiInputs(ctx, msgs, input) +} diff --git a/vendor/github.com/charmbracelet/bubbletea/key_sequences.go b/vendor/github.com/charmbracelet/bubbletea/key_sequences.go new file mode 100644 index 00000000..dce9bf48 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/key_sequences.go @@ -0,0 +1,130 @@ +package tea + +import ( + "bytes" + "sort" + "unicode/utf8" +) + +// extSequences is used by the map-based algorithm below. It contains +// the sequences plus their alternatives with an escape character +// prefixed, plus the control chars, plus the space. +// It does not contain the NUL character, which is handled specially +// by detectOneMsg. +var extSequences = func() map[string]Key { + s := map[string]Key{} + for seq, key := range sequences { + key := key + s[seq] = key + if !key.Alt { + key.Alt = true + s["\x1b"+seq] = key + } + } + for i := keyNUL + 1; i <= keyDEL; i++ { + if i == keyESC { + continue + } + s[string([]byte{byte(i)})] = Key{Type: i} + s[string([]byte{'\x1b', byte(i)})] = Key{Type: i, Alt: true} + if i == keyUS { + i = keyDEL - 1 + } + } + s[" "] = Key{Type: KeySpace, Runes: spaceRunes} + s["\x1b "] = Key{Type: KeySpace, Alt: true, Runes: spaceRunes} + s["\x1b\x1b"] = Key{Type: KeyEscape, Alt: true} + return s +}() + +// seqLengths is the sizes of valid sequences, starting with the +// largest size. +var seqLengths = func() []int { + sizes := map[int]struct{}{} + for seq := range extSequences { + sizes[len(seq)] = struct{}{} + } + lsizes := make([]int, 0, len(sizes)) + for sz := range sizes { + lsizes = append(lsizes, sz) + } + sort.Slice(lsizes, func(i, j int) bool { return lsizes[i] > lsizes[j] }) + return lsizes +}() + +// detectSequence uses a longest prefix match over the input +// sequence and a hash map. +func detectSequence(input []byte) (hasSeq bool, width int, msg Msg) { + seqs := extSequences + for _, sz := range seqLengths { + if sz > len(input) { + continue + } + prefix := input[:sz] + key, ok := seqs[string(prefix)] + if ok { + return true, sz, KeyMsg(key) + } + } + // Is this an unknown CSI sequence? + if loc := unknownCSIRe.FindIndex(input); loc != nil { + return true, loc[1], unknownCSISequenceMsg(input[:loc[1]]) + } + + return false, 0, nil +} + +// detectBracketedPaste detects an input pasted while bracketed +// paste mode was enabled. +// +// Note: this function is a no-op if bracketed paste was not enabled +// on the terminal, since in that case we'd never see this +// particular escape sequence. +func detectBracketedPaste(input []byte) (hasBp bool, width int, msg Msg) { + // Detect the start sequence. + const bpStart = "\x1b[200~" + if len(input) < len(bpStart) || string(input[:len(bpStart)]) != bpStart { + return false, 0, nil + } + + // Skip over the start sequence. + input = input[len(bpStart):] + + // If we saw the start sequence, then we must have an end sequence + // as well. Find it. + const bpEnd = "\x1b[201~" + idx := bytes.Index(input, []byte(bpEnd)) + inputLen := len(bpStart) + idx + len(bpEnd) + if idx == -1 { + // We have encountered the end of the input buffer without seeing + // the marker for the end of the bracketed paste. + // Tell the outer loop we have done a short read and we want more. + return true, 0, nil + } + + // The paste is everything in-between. + paste := input[:idx] + + // All there is in-between is runes, not to be interpreted further. + k := Key{Type: KeyRunes, Paste: true} + for len(paste) > 0 { + r, w := utf8.DecodeRune(paste) + if r != utf8.RuneError { + k.Runes = append(k.Runes, r) + } + paste = paste[w:] + } + + return true, inputLen, KeyMsg(k) +} + +// detectReportFocus detects a focus report sequence. +func detectReportFocus(input []byte) (hasRF bool, width int, msg Msg) { + switch { + case bytes.Equal(input, []byte("\x1b[I")): + return true, 3, FocusMsg{} //nolint:mnd + case bytes.Equal(input, []byte("\x1b[O")): + return true, 3, BlurMsg{} //nolint:mnd + } + return false, 0, nil +} diff --git a/vendor/github.com/charmbracelet/bubbletea/key_windows.go b/vendor/github.com/charmbracelet/bubbletea/key_windows.go new file mode 100644 index 00000000..ac983739 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/key_windows.go @@ -0,0 +1,441 @@ +//go:build windows +// +build windows + +package tea + +import ( + "context" + "fmt" + "io" + "time" + + "github.com/erikgeiser/coninput" + localereader "github.com/mattn/go-localereader" + "github.com/muesli/cancelreader" +) + +func readInputs(ctx context.Context, msgs chan<- Msg, input io.Reader) error { + if coninReader, ok := input.(*conInputReader); ok { + return readConInputs(ctx, msgs, coninReader) + } + + return readAnsiInputs(ctx, msgs, localereader.NewReader(input)) +} + +func readConInputs(ctx context.Context, msgsch chan<- Msg, con *conInputReader) error { + var ps coninput.ButtonState // keep track of previous mouse state + var ws coninput.WindowBufferSizeEventRecord // keep track of the last window size event + for { + events, err := peekAndReadConsInput(con) + if err != nil { + return err + } + for _, event := range events { + var msgs []Msg + switch e := event.Unwrap().(type) { + case coninput.KeyEventRecord: + if !e.KeyDown || e.VirtualKeyCode == coninput.VK_SHIFT { + continue + } + + for i := 0; i < int(e.RepeatCount); i++ { + eventKeyType := keyType(e) + var runes []rune + + // Add the character only if the key type is an actual character and not a control sequence. + // This mimics the behavior in readAnsiInputs where the character is also removed. + // We don't need to handle KeySpace here. See the comment in keyType(). + if eventKeyType == KeyRunes { + runes = []rune{e.Char} + } + + msgs = append(msgs, KeyMsg{ + Type: eventKeyType, + Runes: runes, + Alt: e.ControlKeyState.Contains(coninput.LEFT_ALT_PRESSED | coninput.RIGHT_ALT_PRESSED), + }) + } + case coninput.WindowBufferSizeEventRecord: + if e != ws { + ws = e + msgs = append(msgs, WindowSizeMsg{ + Width: int(e.Size.X), + Height: int(e.Size.Y), + }) + } + case coninput.MouseEventRecord: + event := mouseEvent(ps, e) + if event.Type != MouseUnknown { + msgs = append(msgs, event) + } + ps = e.ButtonState + case coninput.FocusEventRecord, coninput.MenuEventRecord: + // ignore + default: // unknown event + continue + } + + // Send all messages to the channel + for _, msg := range msgs { + select { + case msgsch <- msg: + case <-ctx.Done(): + err := ctx.Err() + if err != nil { + return fmt.Errorf("coninput context error: %w", err) + } + return nil + } + } + } + } +} + +// Peek for new input in a tight loop and then read the input. +// windows.CancelIo* does not work reliably so peek first and only use the data if +// the console input is not cancelled. +func peekAndReadConsInput(con *conInputReader) ([]coninput.InputRecord, error) { + events, err := peekConsInput(con) + if err != nil { + return events, err + } + events, err = coninput.ReadNConsoleInputs(con.conin, intToUint32OrDie(len(events))) + if con.isCanceled() { + return events, cancelreader.ErrCanceled + } + if err != nil { + return events, fmt.Errorf("read coninput events: %w", err) + } + return events, nil +} + +// Convert i to unit32 or panic if it cannot be converted. Check satisifes lint G115. +func intToUint32OrDie(i int) uint32 { + if i < 0 { + panic("cannot convert numEvents " + fmt.Sprint(i) + " to uint32") + } + return uint32(i) +} + +// Keeps peeking until there is data or the input is cancelled. +func peekConsInput(con *conInputReader) ([]coninput.InputRecord, error) { + for { + events, err := coninput.PeekNConsoleInputs(con.conin, 16) + if con.isCanceled() { + return events, cancelreader.ErrCanceled + } + if err != nil { + return events, fmt.Errorf("peek coninput events: %w", err) + } + if len(events) > 0 { + return events, nil + } + // Sleep for a bit to avoid busy waiting. + time.Sleep(16 * time.Millisecond) + } +} + +func mouseEventButton(p, s coninput.ButtonState) (button MouseButton, action MouseAction) { + btn := p ^ s + action = MouseActionPress + if btn&s == 0 { + action = MouseActionRelease + } + + if btn == 0 { + switch { + case s&coninput.FROM_LEFT_1ST_BUTTON_PRESSED > 0: + button = MouseButtonLeft + case s&coninput.FROM_LEFT_2ND_BUTTON_PRESSED > 0: + button = MouseButtonMiddle + case s&coninput.RIGHTMOST_BUTTON_PRESSED > 0: + button = MouseButtonRight + case s&coninput.FROM_LEFT_3RD_BUTTON_PRESSED > 0: + button = MouseButtonBackward + case s&coninput.FROM_LEFT_4TH_BUTTON_PRESSED > 0: + button = MouseButtonForward + } + return button, action + } + + switch { + case btn == coninput.FROM_LEFT_1ST_BUTTON_PRESSED: // left button + button = MouseButtonLeft + case btn == coninput.RIGHTMOST_BUTTON_PRESSED: // right button + button = MouseButtonRight + case btn == coninput.FROM_LEFT_2ND_BUTTON_PRESSED: // middle button + button = MouseButtonMiddle + case btn == coninput.FROM_LEFT_3RD_BUTTON_PRESSED: // unknown (possibly mouse backward) + button = MouseButtonBackward + case btn == coninput.FROM_LEFT_4TH_BUTTON_PRESSED: // unknown (possibly mouse forward) + button = MouseButtonForward + } + + return button, action +} + +func mouseEvent(p coninput.ButtonState, e coninput.MouseEventRecord) MouseMsg { + ev := MouseMsg{ + X: int(e.MousePositon.X), + Y: int(e.MousePositon.Y), + Alt: e.ControlKeyState.Contains(coninput.LEFT_ALT_PRESSED | coninput.RIGHT_ALT_PRESSED), + Ctrl: e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED), + Shift: e.ControlKeyState.Contains(coninput.SHIFT_PRESSED), + } + switch e.EventFlags { + case coninput.CLICK, coninput.DOUBLE_CLICK: + ev.Button, ev.Action = mouseEventButton(p, e.ButtonState) + if ev.Action == MouseActionRelease { + ev.Type = MouseRelease + } + switch ev.Button { //nolint:exhaustive + case MouseButtonLeft: + ev.Type = MouseLeft + case MouseButtonMiddle: + ev.Type = MouseMiddle + case MouseButtonRight: + ev.Type = MouseRight + case MouseButtonBackward: + ev.Type = MouseBackward + case MouseButtonForward: + ev.Type = MouseForward + } + case coninput.MOUSE_WHEELED: + if e.WheelDirection > 0 { + ev.Button = MouseButtonWheelUp + ev.Type = MouseWheelUp + } else { + ev.Button = MouseButtonWheelDown + ev.Type = MouseWheelDown + } + case coninput.MOUSE_HWHEELED: + if e.WheelDirection > 0 { + ev.Button = MouseButtonWheelRight + ev.Type = MouseWheelRight + } else { + ev.Button = MouseButtonWheelLeft + ev.Type = MouseWheelLeft + } + case coninput.MOUSE_MOVED: + ev.Button, _ = mouseEventButton(p, e.ButtonState) + ev.Action = MouseActionMotion + ev.Type = MouseMotion + } + + return ev +} + +func keyType(e coninput.KeyEventRecord) KeyType { + code := e.VirtualKeyCode + + shiftPressed := e.ControlKeyState.Contains(coninput.SHIFT_PRESSED) + ctrlPressed := e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED | coninput.RIGHT_CTRL_PRESSED) + + switch code { //nolint:exhaustive + case coninput.VK_RETURN: + return KeyEnter + case coninput.VK_BACK: + return KeyBackspace + case coninput.VK_TAB: + if shiftPressed { + return KeyShiftTab + } + return KeyTab + case coninput.VK_SPACE: + return KeyRunes // this could be KeySpace but on unix space also produces KeyRunes + case coninput.VK_ESCAPE: + return KeyEscape + case coninput.VK_UP: + switch { + case shiftPressed && ctrlPressed: + return KeyCtrlShiftUp + case shiftPressed: + return KeyShiftUp + case ctrlPressed: + return KeyCtrlUp + default: + return KeyUp + } + case coninput.VK_DOWN: + switch { + case shiftPressed && ctrlPressed: + return KeyCtrlShiftDown + case shiftPressed: + return KeyShiftDown + case ctrlPressed: + return KeyCtrlDown + default: + return KeyDown + } + case coninput.VK_RIGHT: + switch { + case shiftPressed && ctrlPressed: + return KeyCtrlShiftRight + case shiftPressed: + return KeyShiftRight + case ctrlPressed: + return KeyCtrlRight + default: + return KeyRight + } + case coninput.VK_LEFT: + switch { + case shiftPressed && ctrlPressed: + return KeyCtrlShiftLeft + case shiftPressed: + return KeyShiftLeft + case ctrlPressed: + return KeyCtrlLeft + default: + return KeyLeft + } + case coninput.VK_HOME: + switch { + case shiftPressed && ctrlPressed: + return KeyCtrlShiftHome + case shiftPressed: + return KeyShiftHome + case ctrlPressed: + return KeyCtrlHome + default: + return KeyHome + } + case coninput.VK_END: + switch { + case shiftPressed && ctrlPressed: + return KeyCtrlShiftEnd + case shiftPressed: + return KeyShiftEnd + case ctrlPressed: + return KeyCtrlEnd + default: + return KeyEnd + } + case coninput.VK_PRIOR: + return KeyPgUp + case coninput.VK_NEXT: + return KeyPgDown + case coninput.VK_DELETE: + return KeyDelete + case coninput.VK_F1: + return KeyF1 + case coninput.VK_F2: + return KeyF2 + case coninput.VK_F3: + return KeyF3 + case coninput.VK_F4: + return KeyF4 + case coninput.VK_F5: + return KeyF5 + case coninput.VK_F6: + return KeyF6 + case coninput.VK_F7: + return KeyF7 + case coninput.VK_F8: + return KeyF8 + case coninput.VK_F9: + return KeyF9 + case coninput.VK_F10: + return KeyF10 + case coninput.VK_F11: + return KeyF11 + case coninput.VK_F12: + return KeyF12 + case coninput.VK_F13: + return KeyF13 + case coninput.VK_F14: + return KeyF14 + case coninput.VK_F15: + return KeyF15 + case coninput.VK_F16: + return KeyF16 + case coninput.VK_F17: + return KeyF17 + case coninput.VK_F18: + return KeyF18 + case coninput.VK_F19: + return KeyF19 + case coninput.VK_F20: + return KeyF20 + default: + switch { + case e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED) && e.ControlKeyState.Contains(coninput.RIGHT_ALT_PRESSED): + // AltGr is pressed, then it's a rune. + fallthrough + case !e.ControlKeyState.Contains(coninput.LEFT_CTRL_PRESSED) && !e.ControlKeyState.Contains(coninput.RIGHT_CTRL_PRESSED): + return KeyRunes + } + + switch e.Char { + case '@': + return KeyCtrlAt + case '\x01': + return KeyCtrlA + case '\x02': + return KeyCtrlB + case '\x03': + return KeyCtrlC + case '\x04': + return KeyCtrlD + case '\x05': + return KeyCtrlE + case '\x06': + return KeyCtrlF + case '\a': + return KeyCtrlG + case '\b': + return KeyCtrlH + case '\t': + return KeyCtrlI + case '\n': + return KeyCtrlJ + case '\v': + return KeyCtrlK + case '\f': + return KeyCtrlL + case '\r': + return KeyCtrlM + case '\x0e': + return KeyCtrlN + case '\x0f': + return KeyCtrlO + case '\x10': + return KeyCtrlP + case '\x11': + return KeyCtrlQ + case '\x12': + return KeyCtrlR + case '\x13': + return KeyCtrlS + case '\x14': + return KeyCtrlT + case '\x15': + return KeyCtrlU + case '\x16': + return KeyCtrlV + case '\x17': + return KeyCtrlW + case '\x18': + return KeyCtrlX + case '\x19': + return KeyCtrlY + case '\x1a': + return KeyCtrlZ + case '\x1b': + return KeyCtrlOpenBracket // KeyEscape + case '\x1c': + return KeyCtrlBackslash + case '\x1f': + return KeyCtrlUnderscore + } + + switch code { //nolint:exhaustive + case coninput.VK_OEM_4: + return KeyCtrlOpenBracket + case coninput.VK_OEM_6: + return KeyCtrlCloseBracket + } + + return KeyRunes + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/logging.go b/vendor/github.com/charmbracelet/bubbletea/logging.go new file mode 100644 index 00000000..349758cb --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/logging.go @@ -0,0 +1,53 @@ +package tea + +import ( + "fmt" + "io" + "log" + "os" + "unicode" +) + +// LogToFile sets up default logging to log to a file. This is helpful as we +// can't print to the terminal since our TUI is occupying it. If the file +// doesn't exist it will be created. +// +// Don't forget to close the file when you're done with it. +// +// f, err := LogToFile("debug.log", "debug") +// if err != nil { +// fmt.Println("fatal:", err) +// os.Exit(1) +// } +// defer f.Close() +func LogToFile(path string, prefix string) (*os.File, error) { + return LogToFileWith(path, prefix, log.Default()) +} + +// LogOptionsSetter is an interface implemented by stdlib's log and charm's log +// libraries. +type LogOptionsSetter interface { + SetOutput(io.Writer) + SetPrefix(string) +} + +// LogToFileWith does allows to call LogToFile with a custom LogOptionsSetter. +func LogToFileWith(path string, prefix string, log LogOptionsSetter) (*os.File, error) { + f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0o600) //nolint:mnd + if err != nil { + return nil, fmt.Errorf("error opening file for logging: %w", err) + } + log.SetOutput(f) + + // Add a space after the prefix if a prefix is being specified and it + // doesn't already have a trailing space. + if len(prefix) > 0 { + finalChar := prefix[len(prefix)-1] + if !unicode.IsSpace(rune(finalChar)) { + prefix += " " + } + } + log.SetPrefix(prefix) + + return f, nil +} diff --git a/vendor/github.com/charmbracelet/bubbletea/mouse.go b/vendor/github.com/charmbracelet/bubbletea/mouse.go new file mode 100644 index 00000000..490f49ac --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/mouse.go @@ -0,0 +1,308 @@ +package tea + +import "strconv" + +// MouseMsg contains information about a mouse event and are sent to a programs +// update function when mouse activity occurs. Note that the mouse must first +// be enabled in order for the mouse events to be received. +type MouseMsg MouseEvent + +// String returns a string representation of a mouse event. +func (m MouseMsg) String() string { + return MouseEvent(m).String() +} + +// MouseEvent represents a mouse event, which could be a click, a scroll wheel +// movement, a cursor movement, or a combination. +type MouseEvent struct { + X int + Y int + Shift bool + Alt bool + Ctrl bool + Action MouseAction + Button MouseButton + + // Deprecated: Use MouseAction & MouseButton instead. + Type MouseEventType +} + +// IsWheel returns true if the mouse event is a wheel event. +func (m MouseEvent) IsWheel() bool { + return m.Button == MouseButtonWheelUp || m.Button == MouseButtonWheelDown || + m.Button == MouseButtonWheelLeft || m.Button == MouseButtonWheelRight +} + +// String returns a string representation of a mouse event. +func (m MouseEvent) String() (s string) { + if m.Ctrl { + s += "ctrl+" + } + if m.Alt { + s += "alt+" + } + if m.Shift { + s += "shift+" + } + + if m.Button == MouseButtonNone { //nolint:nestif + if m.Action == MouseActionMotion || m.Action == MouseActionRelease { + s += mouseActions[m.Action] + } else { + s += "unknown" + } + } else if m.IsWheel() { + s += mouseButtons[m.Button] + } else { + btn := mouseButtons[m.Button] + if btn != "" { + s += btn + } + act := mouseActions[m.Action] + if act != "" { + s += " " + act + } + } + + return s +} + +// MouseAction represents the action that occurred during a mouse event. +type MouseAction int + +// Mouse event actions. +const ( + MouseActionPress MouseAction = iota + MouseActionRelease + MouseActionMotion +) + +var mouseActions = map[MouseAction]string{ + MouseActionPress: "press", + MouseActionRelease: "release", + MouseActionMotion: "motion", +} + +// MouseButton represents the button that was pressed during a mouse event. +type MouseButton int + +// Mouse event buttons +// +// This is based on X11 mouse button codes. +// +// 1 = left button +// 2 = middle button (pressing the scroll wheel) +// 3 = right button +// 4 = turn scroll wheel up +// 5 = turn scroll wheel down +// 6 = push scroll wheel left +// 7 = push scroll wheel right +// 8 = 4th button (aka browser backward button) +// 9 = 5th button (aka browser forward button) +// 10 +// 11 +// +// Other buttons are not supported. +const ( + MouseButtonNone MouseButton = iota + MouseButtonLeft + MouseButtonMiddle + MouseButtonRight + MouseButtonWheelUp + MouseButtonWheelDown + MouseButtonWheelLeft + MouseButtonWheelRight + MouseButtonBackward + MouseButtonForward + MouseButton10 + MouseButton11 +) + +var mouseButtons = map[MouseButton]string{ + MouseButtonNone: "none", + MouseButtonLeft: "left", + MouseButtonMiddle: "middle", + MouseButtonRight: "right", + MouseButtonWheelUp: "wheel up", + MouseButtonWheelDown: "wheel down", + MouseButtonWheelLeft: "wheel left", + MouseButtonWheelRight: "wheel right", + MouseButtonBackward: "backward", + MouseButtonForward: "forward", + MouseButton10: "button 10", + MouseButton11: "button 11", +} + +// MouseEventType indicates the type of mouse event occurring. +// +// Deprecated: Use MouseAction & MouseButton instead. +type MouseEventType int + +// Mouse event types. +// +// Deprecated: Use MouseAction & MouseButton instead. +const ( + MouseUnknown MouseEventType = iota + MouseLeft + MouseRight + MouseMiddle + MouseRelease // mouse button release (X10 only) + MouseWheelUp + MouseWheelDown + MouseWheelLeft + MouseWheelRight + MouseBackward + MouseForward + MouseMotion +) + +// Parse SGR-encoded mouse events; SGR extended mouse events. SGR mouse events +// look like: +// +// ESC [ < Cb ; Cx ; Cy (M or m) +// +// where: +// +// Cb is the encoded button code +// Cx is the x-coordinate of the mouse +// Cy is the y-coordinate of the mouse +// M is for button press, m is for button release +// +// https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Extended-coordinates +func parseSGRMouseEvent(buf []byte) MouseEvent { + str := string(buf[3:]) + matches := mouseSGRRegex.FindStringSubmatch(str) + if len(matches) != 5 { //nolint:mnd + // Unreachable, we already checked the regex in `detectOneMsg`. + panic("invalid mouse event") + } + + b, _ := strconv.Atoi(matches[1]) + px := matches[2] + py := matches[3] + release := matches[4] == "m" + m := parseMouseButton(b, true) + + // Wheel buttons don't have release events + // Motion can be reported as a release event in some terminals (Windows Terminal) + if m.Action != MouseActionMotion && !m.IsWheel() && release { + m.Action = MouseActionRelease + m.Type = MouseRelease + } + + x, _ := strconv.Atoi(px) + y, _ := strconv.Atoi(py) + + // (1,1) is the upper left. We subtract 1 to normalize it to (0,0). + m.X = x - 1 + m.Y = y - 1 + + return m +} + +const x10MouseByteOffset = 32 + +// Parse X10-encoded mouse events; the simplest kind. The last release of X10 +// was December 1986, by the way. The original X10 mouse protocol limits the Cx +// and Cy coordinates to 223 (=255-032). +// +// X10 mouse events look like: +// +// ESC [M Cb Cx Cy +// +// See: http://www.xfree86.org/current/ctlseqs.html#Mouse%20Tracking +func parseX10MouseEvent(buf []byte) MouseEvent { + v := buf[3:6] + m := parseMouseButton(int(v[0]), false) + + // (1,1) is the upper left. We subtract 1 to normalize it to (0,0). + m.X = int(v[1]) - x10MouseByteOffset - 1 + m.Y = int(v[2]) - x10MouseByteOffset - 1 + + return m +} + +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Extended-coordinates +func parseMouseButton(b int, isSGR bool) MouseEvent { + var m MouseEvent + e := b + if !isSGR { + e -= x10MouseByteOffset + } + + const ( + bitShift = 0b0000_0100 + bitAlt = 0b0000_1000 + bitCtrl = 0b0001_0000 + bitMotion = 0b0010_0000 + bitWheel = 0b0100_0000 + bitAdd = 0b1000_0000 // additional buttons 8-11 + + bitsMask = 0b0000_0011 + ) + + if e&bitAdd != 0 { + m.Button = MouseButtonBackward + MouseButton(e&bitsMask) + } else if e&bitWheel != 0 { + m.Button = MouseButtonWheelUp + MouseButton(e&bitsMask) + } else { + m.Button = MouseButtonLeft + MouseButton(e&bitsMask) + // X10 reports a button release as 0b0000_0011 (3) + if e&bitsMask == bitsMask { + m.Action = MouseActionRelease + m.Button = MouseButtonNone + } + } + + // Motion bit doesn't get reported for wheel events. + if e&bitMotion != 0 && !m.IsWheel() { + m.Action = MouseActionMotion + } + + // Modifiers + m.Alt = e&bitAlt != 0 + m.Ctrl = e&bitCtrl != 0 + m.Shift = e&bitShift != 0 + + // backward compatibility + switch { + case m.Button == MouseButtonLeft && m.Action == MouseActionPress: + m.Type = MouseLeft + case m.Button == MouseButtonMiddle && m.Action == MouseActionPress: + m.Type = MouseMiddle + case m.Button == MouseButtonRight && m.Action == MouseActionPress: + m.Type = MouseRight + case m.Button == MouseButtonNone && m.Action == MouseActionRelease: + m.Type = MouseRelease + case m.Button == MouseButtonWheelUp && m.Action == MouseActionPress: + m.Type = MouseWheelUp + case m.Button == MouseButtonWheelDown && m.Action == MouseActionPress: + m.Type = MouseWheelDown + case m.Button == MouseButtonWheelLeft && m.Action == MouseActionPress: + m.Type = MouseWheelLeft + case m.Button == MouseButtonWheelRight && m.Action == MouseActionPress: + m.Type = MouseWheelRight + case m.Button == MouseButtonBackward && m.Action == MouseActionPress: + m.Type = MouseBackward + case m.Button == MouseButtonForward && m.Action == MouseActionPress: + m.Type = MouseForward + case m.Action == MouseActionMotion: + m.Type = MouseMotion + switch m.Button { //nolint:exhaustive + case MouseButtonLeft: + m.Type = MouseLeft + case MouseButtonMiddle: + m.Type = MouseMiddle + case MouseButtonRight: + m.Type = MouseRight + case MouseButtonBackward: + m.Type = MouseBackward + case MouseButtonForward: + m.Type = MouseForward + } + default: + m.Type = MouseUnknown + } + + return m +} diff --git a/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go b/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go new file mode 100644 index 00000000..1bc909b6 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/nil_renderer.go @@ -0,0 +1,29 @@ +package tea + +type nilRenderer struct{} + +func (n nilRenderer) start() {} +func (n nilRenderer) stop() {} +func (n nilRenderer) kill() {} +func (n nilRenderer) write(_ string) {} +func (n nilRenderer) repaint() {} +func (n nilRenderer) clearScreen() {} +func (n nilRenderer) altScreen() bool { return false } +func (n nilRenderer) enterAltScreen() {} +func (n nilRenderer) exitAltScreen() {} +func (n nilRenderer) showCursor() {} +func (n nilRenderer) hideCursor() {} +func (n nilRenderer) enableMouseCellMotion() {} +func (n nilRenderer) disableMouseCellMotion() {} +func (n nilRenderer) enableMouseAllMotion() {} +func (n nilRenderer) disableMouseAllMotion() {} +func (n nilRenderer) enableBracketedPaste() {} +func (n nilRenderer) disableBracketedPaste() {} +func (n nilRenderer) enableMouseSGRMode() {} +func (n nilRenderer) disableMouseSGRMode() {} +func (n nilRenderer) bracketedPasteActive() bool { return false } +func (n nilRenderer) setWindowTitle(_ string) {} +func (n nilRenderer) reportFocus() bool { return false } +func (n nilRenderer) enableReportFocus() {} +func (n nilRenderer) disableReportFocus() {} +func (n nilRenderer) resetLinesRendered() {} diff --git a/vendor/github.com/charmbracelet/bubbletea/options.go b/vendor/github.com/charmbracelet/bubbletea/options.go new file mode 100644 index 00000000..49cf378b --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/options.go @@ -0,0 +1,252 @@ +package tea + +import ( + "context" + "io" + "sync/atomic" +) + +// ProgramOption is used to set options when initializing a Program. Program can +// accept a variable number of options. +// +// Example usage: +// +// p := NewProgram(model, WithInput(someInput), WithOutput(someOutput)) +type ProgramOption func(*Program) + +// WithContext lets you specify a context in which to run the Program. This is +// useful if you want to cancel the execution from outside. When a Program gets +// cancelled it will exit with an error ErrProgramKilled. +func WithContext(ctx context.Context) ProgramOption { + return func(p *Program) { + p.externalCtx = ctx + } +} + +// WithOutput sets the output which, by default, is stdout. In most cases you +// won't need to use this. +func WithOutput(output io.Writer) ProgramOption { + return func(p *Program) { + p.output = output + } +} + +// WithInput sets the input which, by default, is stdin. In most cases you +// won't need to use this. To disable input entirely pass nil. +// +// p := NewProgram(model, WithInput(nil)) +func WithInput(input io.Reader) ProgramOption { + return func(p *Program) { + p.input = input + p.inputType = customInput + } +} + +// WithInputTTY opens a new TTY for input (or console input device on Windows). +func WithInputTTY() ProgramOption { + return func(p *Program) { + p.inputType = ttyInput + } +} + +// WithEnvironment sets the environment variables that the program will use. +// This useful when the program is running in a remote session (e.g. SSH) and +// you want to pass the environment variables from the remote session to the +// program. +// +// Example: +// +// var sess ssh.Session // ssh.Session is a type from the github.com/charmbracelet/ssh package +// pty, _, _ := sess.Pty() +// environ := append(sess.Environ(), "TERM="+pty.Term) +// p := tea.NewProgram(model, tea.WithEnvironment(environ) +func WithEnvironment(env []string) ProgramOption { + return func(p *Program) { + p.environ = env + } +} + +// WithoutSignalHandler disables the signal handler that Bubble Tea sets up for +// Programs. This is useful if you want to handle signals yourself. +func WithoutSignalHandler() ProgramOption { + return func(p *Program) { + p.startupOptions |= withoutSignalHandler + } +} + +// WithoutCatchPanics disables the panic catching that Bubble Tea does by +// default. If panic catching is disabled the terminal will be in a fairly +// unusable state after a panic because Bubble Tea will not perform its usual +// cleanup on exit. +func WithoutCatchPanics() ProgramOption { + return func(p *Program) { + p.startupOptions |= withoutCatchPanics + } +} + +// WithoutSignals will ignore OS signals. +// This is mainly useful for testing. +func WithoutSignals() ProgramOption { + return func(p *Program) { + atomic.StoreUint32(&p.ignoreSignals, 1) + } +} + +// WithAltScreen starts the program with the alternate screen buffer enabled +// (i.e. the program starts in full window mode). Note that the altscreen will +// be automatically exited when the program quits. +// +// Example: +// +// p := tea.NewProgram(Model{}, tea.WithAltScreen()) +// if _, err := p.Run(); err != nil { +// fmt.Println("Error running program:", err) +// os.Exit(1) +// } +// +// To enter the altscreen once the program has already started running use the +// EnterAltScreen command. +func WithAltScreen() ProgramOption { + return func(p *Program) { + p.startupOptions |= withAltScreen + } +} + +// WithoutBracketedPaste starts the program with bracketed paste disabled. +func WithoutBracketedPaste() ProgramOption { + return func(p *Program) { + p.startupOptions |= withoutBracketedPaste + } +} + +// WithMouseCellMotion starts the program with the mouse enabled in "cell +// motion" mode. +// +// Cell motion mode enables mouse click, release, and wheel events. Mouse +// movement events are also captured if a mouse button is pressed (i.e., drag +// events). Cell motion mode is better supported than all motion mode. +// +// This will try to enable the mouse in extended mode (SGR), if that is not +// supported by the terminal it will fall back to normal mode (X10). +// +// To enable mouse cell motion once the program has already started running use +// the EnableMouseCellMotion command. To disable the mouse when the program is +// running use the DisableMouse command. +// +// The mouse will be automatically disabled when the program exits. +func WithMouseCellMotion() ProgramOption { + return func(p *Program) { + p.startupOptions |= withMouseCellMotion // set + p.startupOptions &^= withMouseAllMotion // clear + } +} + +// WithMouseAllMotion starts the program with the mouse enabled in "all motion" +// mode. +// +// EnableMouseAllMotion is a special command that enables mouse click, release, +// wheel, and motion events, which are delivered regardless of whether a mouse +// button is pressed, effectively enabling support for hover interactions. +// +// This will try to enable the mouse in extended mode (SGR), if that is not +// supported by the terminal it will fall back to normal mode (X10). +// +// Many modern terminals support this, but not all. If in doubt, use +// EnableMouseCellMotion instead. +// +// To enable the mouse once the program has already started running use the +// EnableMouseAllMotion command. To disable the mouse when the program is +// running use the DisableMouse command. +// +// The mouse will be automatically disabled when the program exits. +func WithMouseAllMotion() ProgramOption { + return func(p *Program) { + p.startupOptions |= withMouseAllMotion // set + p.startupOptions &^= withMouseCellMotion // clear + } +} + +// WithoutRenderer disables the renderer. When this is set output and log +// statements will be plainly sent to stdout (or another output if one is set) +// without any rendering and redrawing logic. In other words, printing and +// logging will behave the same way it would in a non-TUI commandline tool. +// This can be useful if you want to use the Bubble Tea framework for a non-TUI +// application, or to provide an additional non-TUI mode to your Bubble Tea +// programs. For example, your program could behave like a daemon if output is +// not a TTY. +func WithoutRenderer() ProgramOption { + return func(p *Program) { + p.renderer = &nilRenderer{} + } +} + +// WithANSICompressor removes redundant ANSI sequences to produce potentially +// smaller output, at the cost of some processing overhead. +// +// This feature is provisional, and may be changed or removed in a future version +// of this package. +// +// Deprecated: this incurs a noticeable performance hit. A future release will +// optimize ANSI automatically without the performance penalty. +func WithANSICompressor() ProgramOption { + return func(p *Program) { + p.startupOptions |= withANSICompressor + } +} + +// WithFilter supplies an event filter that will be invoked before Bubble Tea +// processes a tea.Msg. The event filter can return any tea.Msg which will then +// get handled by Bubble Tea instead of the original event. If the event filter +// returns nil, the event will be ignored and Bubble Tea will not process it. +// +// As an example, this could be used to prevent a program from shutting down if +// there are unsaved changes. +// +// Example: +// +// func filter(m tea.Model, msg tea.Msg) tea.Msg { +// if _, ok := msg.(tea.QuitMsg); !ok { +// return msg +// } +// +// model := m.(myModel) +// if model.hasChanges { +// return nil +// } +// +// return msg +// } +// +// p := tea.NewProgram(Model{}, tea.WithFilter(filter)); +// +// if _,err := p.Run(); err != nil { +// fmt.Println("Error running program:", err) +// os.Exit(1) +// } +func WithFilter(filter func(Model, Msg) Msg) ProgramOption { + return func(p *Program) { + p.filter = filter + } +} + +// WithFPS sets a custom maximum FPS at which the renderer should run. If +// less than 1, the default value of 60 will be used. If over 120, the FPS +// will be capped at 120. +func WithFPS(fps int) ProgramOption { + return func(p *Program) { + p.fps = fps + } +} + +// WithReportFocus enables reporting when the terminal gains and loses +// focus. When this is enabled [FocusMsg] and [BlurMsg] messages will be sent +// to your Update method. +// +// Note that while most terminals and multiplexers support focus reporting, +// some do not. Also note that tmux needs to be configured to report focus +// events. +func WithReportFocus() ProgramOption { + return func(p *Program) { + p.startupOptions |= withReportFocus + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/renderer.go b/vendor/github.com/charmbracelet/bubbletea/renderer.go new file mode 100644 index 00000000..5b6df66a --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/renderer.go @@ -0,0 +1,88 @@ +package tea + +// renderer is the interface for Bubble Tea renderers. +type renderer interface { + // Start the renderer. + start() + + // Stop the renderer, but render the final frame in the buffer, if any. + stop() + + // Stop the renderer without doing any final rendering. + kill() + + // Write a frame to the renderer. The renderer can write this data to + // output at its discretion. + write(string) + + // Request a full re-render. Note that this will not trigger a render + // immediately. Rather, this method causes the next render to be a full + // repaint. Because of this, it's safe to call this method multiple times + // in succession. + repaint() + + // Clears the terminal. + clearScreen() + + // Whether or not the alternate screen buffer is enabled. + altScreen() bool + // Enable the alternate screen buffer. + enterAltScreen() + // Disable the alternate screen buffer. + exitAltScreen() + + // Show the cursor. + showCursor() + // Hide the cursor. + hideCursor() + + // enableMouseCellMotion enables mouse click, release, wheel and motion + // events if a mouse button is pressed (i.e., drag events). + enableMouseCellMotion() + + // disableMouseCellMotion disables Mouse Cell Motion tracking. + disableMouseCellMotion() + + // enableMouseAllMotion enables mouse click, release, wheel and motion + // events, regardless of whether a mouse button is pressed. Many modern + // terminals support this, but not all. + enableMouseAllMotion() + + // disableMouseAllMotion disables All Motion mouse tracking. + disableMouseAllMotion() + + // enableMouseSGRMode enables mouse extended mode (SGR). + enableMouseSGRMode() + + // disableMouseSGRMode disables mouse extended mode (SGR). + disableMouseSGRMode() + + // enableBracketedPaste enables bracketed paste, where characters + // inside the input are not interpreted when pasted as a whole. + enableBracketedPaste() + + // disableBracketedPaste disables bracketed paste. + disableBracketedPaste() + + // bracketedPasteActive reports whether bracketed paste mode is + // currently enabled. + bracketedPasteActive() bool + + // setWindowTitle sets the terminal window title. + setWindowTitle(string) + + // reportFocus returns whether reporting focus events is enabled. + reportFocus() bool + + // enableReportFocus reports focus events to the program. + enableReportFocus() + + // disableReportFocus stops reporting focus events to the program. + disableReportFocus() + + // resetLinesRendered ensures exec output remains on screen on exit + resetLinesRendered() +} + +// repaintMsg forces a full repaint. +type repaintMsg struct{} diff --git a/vendor/github.com/charmbracelet/bubbletea/screen.go b/vendor/github.com/charmbracelet/bubbletea/screen.go new file mode 100644 index 00000000..dfec48f0 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/screen.go @@ -0,0 +1,248 @@ +package tea + +// WindowSizeMsg is used to report the terminal size. It's sent to Update once +// initially and then on every terminal resize. Note that Windows does not +// have support for reporting when resizes occur as it does not support the +// SIGWINCH signal. +type WindowSizeMsg struct { + Width int + Height int +} + +// ClearScreen is a special command that tells the program to clear the screen +// before the next update. This can be used to move the cursor to the top left +// of the screen and clear visual clutter when the alt screen is not in use. +// +// Note that it should never be necessary to call ClearScreen() for regular +// redraws. +func ClearScreen() Msg { + return clearScreenMsg{} +} + +// clearScreenMsg is an internal message that signals to clear the screen. +// You can send a clearScreenMsg with ClearScreen. +type clearScreenMsg struct{} + +// EnterAltScreen is a special command that tells the Bubble Tea program to +// enter the alternate screen buffer. +// +// Because commands run asynchronously, this command should not be used in your +// model's Init function. To initialize your program with the altscreen enabled +// use the WithAltScreen ProgramOption instead. +func EnterAltScreen() Msg { + return enterAltScreenMsg{} +} + +// enterAltScreenMsg in an internal message signals that the program should +// enter alternate screen buffer. You can send a enterAltScreenMsg with +// EnterAltScreen. +type enterAltScreenMsg struct{} + +// ExitAltScreen is a special command that tells the Bubble Tea program to exit +// the alternate screen buffer. This command should be used to exit the +// alternate screen buffer while the program is running. +// +// Note that the alternate screen buffer will be automatically exited when the +// program quits. +func ExitAltScreen() Msg { + return exitAltScreenMsg{} +} + +// exitAltScreenMsg in an internal message signals that the program should exit +// alternate screen buffer. You can send a exitAltScreenMsg with ExitAltScreen. +type exitAltScreenMsg struct{} + +// EnableMouseCellMotion is a special command that enables mouse click, +// release, and wheel events. Mouse movement events are also captured if +// a mouse button is pressed (i.e., drag events). +// +// Because commands run asynchronously, this command should not be used in your +// model's Init function. Use the WithMouseCellMotion ProgramOption instead. +func EnableMouseCellMotion() Msg { + return enableMouseCellMotionMsg{} +} + +// enableMouseCellMotionMsg is a special command that signals to start +// listening for "cell motion" type mouse events (ESC[?1002l). To send an +// enableMouseCellMotionMsg, use the EnableMouseCellMotion command. +type enableMouseCellMotionMsg struct{} + +// EnableMouseAllMotion is a special command that enables mouse click, release, +// wheel, and motion events, which are delivered regardless of whether a mouse +// button is pressed, effectively enabling support for hover interactions. +// +// Many modern terminals support this, but not all. If in doubt, use +// EnableMouseCellMotion instead. +// +// Because commands run asynchronously, this command should not be used in your +// model's Init function. Use the WithMouseAllMotion ProgramOption instead. +func EnableMouseAllMotion() Msg { + return enableMouseAllMotionMsg{} +} + +// enableMouseAllMotionMsg is a special command that signals to start listening +// for "all motion" type mouse events (ESC[?1003l). To send an +// enableMouseAllMotionMsg, use the EnableMouseAllMotion command. +type enableMouseAllMotionMsg struct{} + +// DisableMouse is a special command that stops listening for mouse events. +func DisableMouse() Msg { + return disableMouseMsg{} +} + +// disableMouseMsg is an internal message that signals to stop listening +// for mouse events. To send a disableMouseMsg, use the DisableMouse command. +type disableMouseMsg struct{} + +// HideCursor is a special command for manually instructing Bubble Tea to hide +// the cursor. In some rare cases, certain operations will cause the terminal +// to show the cursor, which is normally hidden for the duration of a Bubble +// Tea program's lifetime. You will most likely not need to use this command. +func HideCursor() Msg { + return hideCursorMsg{} +} + +// hideCursorMsg is an internal command used to hide the cursor. You can send +// this message with HideCursor. +type hideCursorMsg struct{} + +// ShowCursor is a special command for manually instructing Bubble Tea to show +// the cursor. +func ShowCursor() Msg { + return showCursorMsg{} +} + +// showCursorMsg is an internal command used to show the cursor. You can send +// this message with ShowCursor. +type showCursorMsg struct{} + +// EnableBracketedPaste is a special command that tells the Bubble Tea program +// to accept bracketed paste input. +// +// Note that bracketed paste will be automatically disabled when the +// program quits. +func EnableBracketedPaste() Msg { + return enableBracketedPasteMsg{} +} + +// enableBracketedPasteMsg in an internal message signals that +// bracketed paste should be enabled. You can send an +// enableBracketedPasteMsg with EnableBracketedPaste. +type enableBracketedPasteMsg struct{} + +// DisableBracketedPaste is a special command that tells the Bubble Tea program +// to accept bracketed paste input. +// +// Note that bracketed paste will be automatically disabled when the +// program quits. +func DisableBracketedPaste() Msg { + return disableBracketedPasteMsg{} +} + +// disableBracketedPasteMsg in an internal message signals that +// bracketed paste should be disabled. You can send an +// disableBracketedPasteMsg with DisableBracketedPaste. +type disableBracketedPasteMsg struct{} + +// enableReportFocusMsg is an internal message that signals to enable focus +// reporting. You can send an enableReportFocusMsg with EnableReportFocus. +type enableReportFocusMsg struct{} + +// EnableReportFocus is a special command that tells the Bubble Tea program to +// report focus events to the program. +func EnableReportFocus() Msg { + return enableReportFocusMsg{} +} + +// disableReportFocusMsg is an internal message that signals to disable focus +// reporting. You can send an disableReportFocusMsg with DisableReportFocus. +type disableReportFocusMsg struct{} + +// DisableReportFocus is a special command that tells the Bubble Tea program to +// stop reporting focus events to the program. +func DisableReportFocus() Msg { + return disableReportFocusMsg{} +} + +// EnterAltScreen enters the alternate screen buffer, which consumes the entire +// terminal window. ExitAltScreen will return the terminal to its former state. +// +// Deprecated: Use the WithAltScreen ProgramOption instead. +func (p *Program) EnterAltScreen() { + if p.renderer != nil { + p.renderer.enterAltScreen() + } else { + p.startupOptions |= withAltScreen + } +} + +// ExitAltScreen exits the alternate screen buffer. +// +// Deprecated: The altscreen will exited automatically when the program exits. +func (p *Program) ExitAltScreen() { + if p.renderer != nil { + p.renderer.exitAltScreen() + } else { + p.startupOptions &^= withAltScreen + } +} + +// EnableMouseCellMotion enables mouse click, release, wheel and motion events +// if a mouse button is pressed (i.e., drag events). +// +// Deprecated: Use the WithMouseCellMotion ProgramOption instead. +func (p *Program) EnableMouseCellMotion() { + if p.renderer != nil { + p.renderer.enableMouseCellMotion() + } else { + p.startupOptions |= withMouseCellMotion + } +} + +// DisableMouseCellMotion disables Mouse Cell Motion tracking. This will be +// called automatically when exiting a Bubble Tea program. +// +// Deprecated: The mouse will automatically be disabled when the program exits. +func (p *Program) DisableMouseCellMotion() { + if p.renderer != nil { + p.renderer.disableMouseCellMotion() + } else { + p.startupOptions &^= withMouseCellMotion + } +} + +// EnableMouseAllMotion enables mouse click, release, wheel and motion events, +// regardless of whether a mouse button is pressed. Many modern terminals +// support this, but not all. +// +// Deprecated: Use the WithMouseAllMotion ProgramOption instead. +func (p *Program) EnableMouseAllMotion() { + if p.renderer != nil { + p.renderer.enableMouseAllMotion() + } else { + p.startupOptions |= withMouseAllMotion + } +} + +// DisableMouseAllMotion disables All Motion mouse tracking. This will be +// called automatically when exiting a Bubble Tea program. +// +// Deprecated: The mouse will automatically be disabled when the program exits. +func (p *Program) DisableMouseAllMotion() { + if p.renderer != nil { + p.renderer.disableMouseAllMotion() + } else { + p.startupOptions &^= withMouseAllMotion + } +} + +// SetWindowTitle sets the terminal window title. +// +// Deprecated: Use the SetWindowTitle command instead. +func (p *Program) SetWindowTitle(title string) { + if p.renderer != nil { + p.renderer.setWindowTitle(title) + } else { + p.startupTitle = title + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/signals_unix.go b/vendor/github.com/charmbracelet/bubbletea/signals_unix.go new file mode 100644 index 00000000..40954038 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/signals_unix.go @@ -0,0 +1,33 @@ +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || aix || zos +// +build darwin dragonfly freebsd linux netbsd openbsd solaris aix zos + +package tea + +import ( + "os" + "os/signal" + "syscall" +) + +// listenForResize sends messages (or errors) when the terminal resizes. +// Argument output should be the file descriptor for the terminal; usually +// os.Stdout. +func (p *Program) listenForResize(done chan struct{}) { + sig := make(chan os.Signal, 1) + signal.Notify(sig, syscall.SIGWINCH) + + defer func() { + signal.Stop(sig) + close(done) + }() + + for { + select { + case <-p.ctx.Done(): + return + case <-sig: + } + + p.checkResize() + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/signals_windows.go b/vendor/github.com/charmbracelet/bubbletea/signals_windows.go new file mode 100644 index 00000000..2fc6f8ae --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/signals_windows.go @@ -0,0 +1,10 @@ +//go:build windows +// +build windows + +package tea + +// listenForResize is not available on windows because windows does not +// implement syscall.SIGWINCH. +func (p *Program) listenForResize(done chan struct{}) { + close(done) +} diff --git a/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go b/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go new file mode 100644 index 00000000..d6dce6db --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/standard_renderer.go @@ -0,0 +1,790 @@ +package tea + +import ( + "bytes" + "fmt" + "io" + "strings" + "sync" + "time" + + "github.com/charmbracelet/x/ansi" + "github.com/muesli/ansi/compressor" +) + +const ( + // defaultFramerate specifies the maximum interval at which we should + // update the view. + defaultFPS = 60 + maxFPS = 120 +) + +// standardRenderer is a framerate-based terminal renderer, updating the view +// at a given framerate to avoid overloading the terminal emulator. +// +// In cases where very high performance is needed the renderer can be told +// to exclude ranges of lines, allowing them to be written to directly. +type standardRenderer struct { + mtx *sync.Mutex + out io.Writer + + buf bytes.Buffer + queuedMessageLines []string + framerate time.Duration + ticker *time.Ticker + done chan struct{} + lastRender string + lastRenderedLines []string + linesRendered int + altLinesRendered int + useANSICompressor bool + once sync.Once + + // cursor visibility state + cursorHidden bool + + // essentially whether or not we're using the full size of the terminal + altScreenActive bool + + // whether or not we're currently using bracketed paste + bpActive bool + + // reportingFocus whether reporting focus events is enabled + reportingFocus bool + + // renderer dimensions; usually the size of the window + width int + height int + + // lines explicitly set not to render + ignoreLines map[int]struct{} +} + +// newRenderer creates a new renderer. Normally you'll want to initialize it +// with os.Stdout as the first argument. +func newRenderer(out io.Writer, useANSICompressor bool, fps int) renderer { + if fps < 1 { + fps = defaultFPS + } else if fps > maxFPS { + fps = maxFPS + } + r := &standardRenderer{ + out: out, + mtx: &sync.Mutex{}, + done: make(chan struct{}), + framerate: time.Second / time.Duration(fps), + useANSICompressor: useANSICompressor, + queuedMessageLines: []string{}, + } + if r.useANSICompressor { + r.out = &compressor.Writer{Forward: out} + } + return r +} + +// start starts the renderer. +func (r *standardRenderer) start() { + if r.ticker == nil { + r.ticker = time.NewTicker(r.framerate) + } else { + // If the ticker already exists, it has been stopped and we need to + // reset it. + r.ticker.Reset(r.framerate) + } + + // Since the renderer can be restarted after a stop, we need to reset + // the done channel and its corresponding sync.Once. + r.once = sync.Once{} + + go r.listen() +} + +// stop permanently halts the renderer, rendering the final frame. +func (r *standardRenderer) stop() { + // Stop the renderer before acquiring the mutex to avoid a deadlock. + r.once.Do(func() { + r.done <- struct{}{} + }) + + // flush locks the mutex + r.flush() + + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.EraseEntireLine) + // Move the cursor back to the beginning of the line + r.execute("\r") + + if r.useANSICompressor { + if w, ok := r.out.(io.WriteCloser); ok { + _ = w.Close() + } + } +} + +// execute writes a sequence to the terminal. +func (r *standardRenderer) execute(seq string) { + _, _ = io.WriteString(r.out, seq) +} + +// kill halts the renderer. The final frame will not be rendered. +func (r *standardRenderer) kill() { + // Stop the renderer before acquiring the mutex to avoid a deadlock. + r.once.Do(func() { + r.done <- struct{}{} + }) + + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.EraseEntireLine) + // Move the cursor back to the beginning of the line + r.execute("\r") +} + +// listen waits for ticks on the ticker, or a signal to stop the renderer. +func (r *standardRenderer) listen() { + for { + select { + case <-r.done: + r.ticker.Stop() + return + + case <-r.ticker.C: + r.flush() + } + } +} + +// flush renders the buffer. +func (r *standardRenderer) flush() { + r.mtx.Lock() + defer r.mtx.Unlock() + + if r.buf.Len() == 0 || r.buf.String() == r.lastRender { + // Nothing to do. + return + } + + // Output buffer. + buf := &bytes.Buffer{} + + // Moving to the beginning of the section, that we rendered. + if r.altScreenActive { + buf.WriteString(ansi.CursorHomePosition) + } else if r.linesRendered > 1 { + buf.WriteString(ansi.CursorUp(r.linesRendered - 1)) + } + + newLines := strings.Split(r.buf.String(), "\n") + + // If we know the output's height, we can use it to determine how many + // lines we can render. We drop lines from the top of the render buffer if + // necessary, as we can't navigate the cursor into the terminal's scrollback + // buffer. + if r.height > 0 && len(newLines) > r.height { + newLines = newLines[len(newLines)-r.height:] + } + + flushQueuedMessages := len(r.queuedMessageLines) > 0 && !r.altScreenActive + + if flushQueuedMessages { + // Dump the lines we've queued up for printing. + for _, line := range r.queuedMessageLines { + if ansi.StringWidth(line) < r.width { + // We only erase the rest of the line when the line is shorter than + // the width of the terminal. When the cursor reaches the end of + // the line, any escape sequences that follow will only affect the + // last cell of the line. + + // Removing previously rendered content at the end of line. + line = line + ansi.EraseLineRight + } + + _, _ = buf.WriteString(line) + _, _ = buf.WriteString("\r\n") + } + // Clear the queued message lines. + r.queuedMessageLines = []string{} + } + + // Paint new lines. + for i := 0; i < len(newLines); i++ { + canSkip := !flushQueuedMessages && // Queuing messages triggers repaint -> we don't have access to previous frame content. + len(r.lastRenderedLines) > i && r.lastRenderedLines[i] == newLines[i] // Previously rendered line is the same. + + if _, ignore := r.ignoreLines[i]; ignore || canSkip { + // Unless this is the last line, move the cursor down. + if i < len(newLines)-1 { + buf.WriteByte('\n') + } + continue + } + + if i == 0 && r.lastRender == "" { + // On first render, reset the cursor to the start of the line + // before writing anything. + buf.WriteByte('\r') + } + + line := newLines[i] + + // Truncate lines wider than the width of the window to avoid + // wrapping, which will mess up rendering. If we don't have the + // width of the window this will be ignored. + // + // Note that on Windows we only get the width of the window on + // program initialization, so after a resize this won't perform + // correctly (signal SIGWINCH is not supported on Windows). + if r.width > 0 { + line = ansi.Truncate(line, r.width, "") + } + + if ansi.StringWidth(line) < r.width { + // We only erase the rest of the line when the line is shorter than + // the width of the terminal. When the cursor reaches the end of + // the line, any escape sequences that follow will only affect the + // last cell of the line. + + // Removing previously rendered content at the end of line. + line = line + ansi.EraseLineRight + } + + _, _ = buf.WriteString(line) + + if i < len(newLines)-1 { + _, _ = buf.WriteString("\r\n") + } + } + + // Clearing left over content from last render. + if r.lastLinesRendered() > len(newLines) { + buf.WriteString(ansi.EraseScreenBelow) + } + + if r.altScreenActive { + r.altLinesRendered = len(newLines) + } else { + r.linesRendered = len(newLines) + } + + // Make sure the cursor is at the start of the last line to keep rendering + // behavior consistent. + if r.altScreenActive { + // This case fixes a bug in macOS terminal. In other terminals the + // other case seems to do the job regardless of whether or not we're + // using the full terminal window. + buf.WriteString(ansi.CursorPosition(0, len(newLines))) + } else { + buf.WriteString(ansi.CursorBackward(r.width)) + } + + _, _ = r.out.Write(buf.Bytes()) + r.lastRender = r.buf.String() + + // Save previously rendered lines for comparison in the next render. If we + // don't do this, we can't skip rendering lines that haven't changed. + // See https://github.com/charmbracelet/bubbletea/pull/1233 + r.lastRenderedLines = newLines + r.buf.Reset() +} + +// lastLinesRendered returns the number of lines rendered lastly. +func (r *standardRenderer) lastLinesRendered() int { + if r.altScreenActive { + return r.altLinesRendered + } + return r.linesRendered +} + +// write writes to the internal buffer. The buffer will be outputted via the +// ticker which calls flush(). +func (r *standardRenderer) write(s string) { + r.mtx.Lock() + defer r.mtx.Unlock() + r.buf.Reset() + + // If an empty string was passed we should clear existing output and + // rendering nothing. Rather than introduce additional state to manage + // this, we render a single space as a simple (albeit less correct) + // solution. + if s == "" { + s = " " + } + + _, _ = r.buf.WriteString(s) +} + +func (r *standardRenderer) repaint() { + r.lastRender = "" + r.lastRenderedLines = nil +} + +func (r *standardRenderer) clearScreen() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.EraseEntireScreen) + r.execute(ansi.CursorHomePosition) + + r.repaint() +} + +func (r *standardRenderer) altScreen() bool { + r.mtx.Lock() + defer r.mtx.Unlock() + + return r.altScreenActive +} + +func (r *standardRenderer) enterAltScreen() { + r.mtx.Lock() + defer r.mtx.Unlock() + + if r.altScreenActive { + return + } + + r.altScreenActive = true + r.execute(ansi.SetAltScreenSaveCursorMode) + + // Ensure that the terminal is cleared, even when it doesn't support + // alt screen (or alt screen support is disabled, like GNU screen by + // default). + // + // Note: we can't use r.clearScreen() here because the mutex is already + // locked. + r.execute(ansi.EraseEntireScreen) + r.execute(ansi.CursorHomePosition) + + // cmd.exe and other terminals keep separate cursor states for the AltScreen + // and the main buffer. We have to explicitly reset the cursor visibility + // whenever we enter AltScreen. + if r.cursorHidden { + r.execute(ansi.HideCursor) + } else { + r.execute(ansi.ShowCursor) + } + + // Entering the alt screen resets the lines rendered count. + r.altLinesRendered = 0 + + r.repaint() +} + +func (r *standardRenderer) exitAltScreen() { + r.mtx.Lock() + defer r.mtx.Unlock() + + if !r.altScreenActive { + return + } + + r.altScreenActive = false + r.execute(ansi.ResetAltScreenSaveCursorMode) + + // cmd.exe and other terminals keep separate cursor states for the AltScreen + // and the main buffer. We have to explicitly reset the cursor visibility + // whenever we exit AltScreen. + if r.cursorHidden { + r.execute(ansi.HideCursor) + } else { + r.execute(ansi.ShowCursor) + } + + r.repaint() +} + +func (r *standardRenderer) showCursor() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.cursorHidden = false + r.execute(ansi.ShowCursor) +} + +func (r *standardRenderer) hideCursor() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.cursorHidden = true + r.execute(ansi.HideCursor) +} + +func (r *standardRenderer) enableMouseCellMotion() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.SetButtonEventMouseMode) +} + +func (r *standardRenderer) disableMouseCellMotion() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.ResetButtonEventMouseMode) +} + +func (r *standardRenderer) enableMouseAllMotion() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.SetAnyEventMouseMode) +} + +func (r *standardRenderer) disableMouseAllMotion() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.ResetAnyEventMouseMode) +} + +func (r *standardRenderer) enableMouseSGRMode() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.SetSgrExtMouseMode) +} + +func (r *standardRenderer) disableMouseSGRMode() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.ResetSgrExtMouseMode) +} + +func (r *standardRenderer) enableBracketedPaste() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.SetBracketedPasteMode) + r.bpActive = true +} + +func (r *standardRenderer) disableBracketedPaste() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.ResetBracketedPasteMode) + r.bpActive = false +} + +func (r *standardRenderer) bracketedPasteActive() bool { + r.mtx.Lock() + defer r.mtx.Unlock() + + return r.bpActive +} + +func (r *standardRenderer) enableReportFocus() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.SetFocusEventMode) + r.reportingFocus = true +} + +func (r *standardRenderer) disableReportFocus() { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.execute(ansi.ResetFocusEventMode) + r.reportingFocus = false +} + +func (r *standardRenderer) reportFocus() bool { + r.mtx.Lock() + defer r.mtx.Unlock() + + return r.reportingFocus +} + +// setWindowTitle sets the terminal window title. +func (r *standardRenderer) setWindowTitle(title string) { + r.execute(ansi.SetWindowTitle(title)) +} + +// setIgnoredLines specifies lines not to be touched by the standard Bubble Tea +// renderer. +func (r *standardRenderer) setIgnoredLines(from int, to int) { + // Lock if we're going to be clearing some lines since we don't want + // anything jacking our cursor. + if r.lastLinesRendered() > 0 { + r.mtx.Lock() + defer r.mtx.Unlock() + } + + if r.ignoreLines == nil { + r.ignoreLines = make(map[int]struct{}) + } + for i := from; i < to; i++ { + r.ignoreLines[i] = struct{}{} + } + + // Erase ignored lines + lastLinesRendered := r.lastLinesRendered() + if lastLinesRendered > 0 { + buf := &bytes.Buffer{} + + for i := lastLinesRendered - 1; i >= 0; i-- { + if _, exists := r.ignoreLines[i]; exists { + buf.WriteString(ansi.EraseEntireLine) + } + buf.WriteString(ansi.CUU1) + } + buf.WriteString(ansi.CursorPosition(0, lastLinesRendered)) // put cursor back + _, _ = r.out.Write(buf.Bytes()) + } +} + +// clearIgnoredLines returns control of any ignored lines to the standard +// Bubble Tea renderer. That is, any lines previously set to be ignored can be +// rendered to again. +func (r *standardRenderer) clearIgnoredLines() { + r.ignoreLines = nil +} + +func (r *standardRenderer) resetLinesRendered() { + r.linesRendered = 0 +} + +// insertTop effectively scrolls up. It inserts lines at the top of a given +// area designated to be a scrollable region, pushing everything else down. +// This is roughly how ncurses does it. +// +// To call this function use command ScrollUp(). +// +// For this to work renderer.ignoreLines must be set to ignore the scrollable +// region since we are bypassing the normal Bubble Tea renderer here. +// +// Because this method relies on the terminal dimensions, it's only valid for +// full-window applications (generally those that use the alternate screen +// buffer). +// +// This method bypasses the normal rendering buffer and is philosophically +// different than the normal way we approach rendering in Bubble Tea. It's for +// use in high-performance rendering, such as a pager that could potentially +// be rendering very complicated ansi. In cases where the content is simpler +// standard Bubble Tea rendering should suffice. +// +// Deprecated: This option is deprecated and will be removed in a future +// version of this package. +func (r *standardRenderer) insertTop(lines []string, topBoundary, bottomBoundary int) { + r.mtx.Lock() + defer r.mtx.Unlock() + + buf := &bytes.Buffer{} + + buf.WriteString(ansi.SetTopBottomMargins(topBoundary, bottomBoundary)) + buf.WriteString(ansi.CursorPosition(0, topBoundary)) + buf.WriteString(ansi.InsertLine(len(lines))) + _, _ = buf.WriteString(strings.Join(lines, "\r\n")) + buf.WriteString(ansi.SetTopBottomMargins(0, r.height)) + + // Move cursor back to where the main rendering routine expects it to be + buf.WriteString(ansi.CursorPosition(0, r.lastLinesRendered())) + + _, _ = r.out.Write(buf.Bytes()) +} + +// insertBottom effectively scrolls down. It inserts lines at the bottom of +// a given area designated to be a scrollable region, pushing everything else +// up. This is roughly how ncurses does it. +// +// To call this function use the command ScrollDown(). +// +// See note in insertTop() for caveats, how this function only makes sense for +// full-window applications, and how it differs from the normal way we do +// rendering in Bubble Tea. +// +// Deprecated: This option is deprecated and will be removed in a future +// version of this package. +func (r *standardRenderer) insertBottom(lines []string, topBoundary, bottomBoundary int) { + r.mtx.Lock() + defer r.mtx.Unlock() + + buf := &bytes.Buffer{} + + buf.WriteString(ansi.SetTopBottomMargins(topBoundary, bottomBoundary)) + buf.WriteString(ansi.CursorPosition(0, bottomBoundary)) + _, _ = buf.WriteString("\r\n" + strings.Join(lines, "\r\n")) + buf.WriteString(ansi.SetTopBottomMargins(0, r.height)) + + // Move cursor back to where the main rendering routine expects it to be + buf.WriteString(ansi.CursorPosition(0, r.lastLinesRendered())) + + _, _ = r.out.Write(buf.Bytes()) +} + +// handleMessages handles internal messages for the renderer. +func (r *standardRenderer) handleMessages(msg Msg) { + switch msg := msg.(type) { + case repaintMsg: + // Force a repaint by clearing the render cache as we slide into a + // render. + r.mtx.Lock() + r.repaint() + r.mtx.Unlock() + + case WindowSizeMsg: + r.mtx.Lock() + r.width = msg.Width + r.height = msg.Height + r.repaint() + r.mtx.Unlock() + + case clearScrollAreaMsg: + r.clearIgnoredLines() + + // Force a repaint on the area where the scrollable stuff was in this + // update cycle + r.mtx.Lock() + r.repaint() + r.mtx.Unlock() + + case syncScrollAreaMsg: + // Re-render scrolling area + r.clearIgnoredLines() + r.setIgnoredLines(msg.topBoundary, msg.bottomBoundary) + r.insertTop(msg.lines, msg.topBoundary, msg.bottomBoundary) + + // Force non-scrolling stuff to repaint in this update cycle + r.mtx.Lock() + r.repaint() + r.mtx.Unlock() + + case scrollUpMsg: + r.insertTop(msg.lines, msg.topBoundary, msg.bottomBoundary) + + case scrollDownMsg: + r.insertBottom(msg.lines, msg.topBoundary, msg.bottomBoundary) + + case printLineMessage: + if !r.altScreenActive { + lines := strings.Split(msg.messageBody, "\n") + r.mtx.Lock() + r.queuedMessageLines = append(r.queuedMessageLines, lines...) + r.repaint() + r.mtx.Unlock() + } + } +} + +// HIGH-PERFORMANCE RENDERING STUFF + +type syncScrollAreaMsg struct { + lines []string + topBoundary int + bottomBoundary int +} + +// SyncScrollArea performs a paint of the entire region designated to be the +// scrollable area. This is required to initialize the scrollable region and +// should also be called on resize (WindowSizeMsg). +// +// For high-performance, scroll-based rendering only. +// +// Deprecated: This option will be removed in a future version of this package. +func SyncScrollArea(lines []string, topBoundary int, bottomBoundary int) Cmd { + return func() Msg { + return syncScrollAreaMsg{ + lines: lines, + topBoundary: topBoundary, + bottomBoundary: bottomBoundary, + } + } +} + +type clearScrollAreaMsg struct{} + +// ClearScrollArea deallocates the scrollable region and returns the control of +// those lines to the main rendering routine. +// +// For high-performance, scroll-based rendering only. +// +// Deprecated: This option will be removed in a future version of this package. +func ClearScrollArea() Msg { + return clearScrollAreaMsg{} +} + +type scrollUpMsg struct { + lines []string + topBoundary int + bottomBoundary int +} + +// ScrollUp adds lines to the top of the scrollable region, pushing existing +// lines below down. Lines that are pushed out the scrollable region disappear +// from view. +// +// For high-performance, scroll-based rendering only. +// +// Deprecated: This option will be removed in a future version of this package. +func ScrollUp(newLines []string, topBoundary, bottomBoundary int) Cmd { + return func() Msg { + return scrollUpMsg{ + lines: newLines, + topBoundary: topBoundary, + bottomBoundary: bottomBoundary, + } + } +} + +type scrollDownMsg struct { + lines []string + topBoundary int + bottomBoundary int +} + +// ScrollDown adds lines to the bottom of the scrollable region, pushing +// existing lines above up. Lines that are pushed out of the scrollable region +// disappear from view. +// +// For high-performance, scroll-based rendering only. +// +// Deprecated: This option will be removed in a future version of this package. +func ScrollDown(newLines []string, topBoundary, bottomBoundary int) Cmd { + return func() Msg { + return scrollDownMsg{ + lines: newLines, + topBoundary: topBoundary, + bottomBoundary: bottomBoundary, + } + } +} + +type printLineMessage struct { + messageBody string +} + +// Println prints above the Program. This output is unmanaged by the program and +// will persist across renders by the Program. +// +// Unlike fmt.Println (but similar to log.Println) the message will be print on +// its own line. +// +// If the altscreen is active no output will be printed. +func Println(args ...interface{}) Cmd { + return func() Msg { + return printLineMessage{ + messageBody: fmt.Sprint(args...), + } + } +} + +// Printf prints above the Program. It takes a format template followed by +// values similar to fmt.Printf. This output is unmanaged by the program and +// will persist across renders by the Program. +// +// Unlike fmt.Printf (but similar to log.Printf) the message will be print on +// its own line. +// +// If the altscreen is active no output will be printed. +func Printf(template string, args ...interface{}) Cmd { + return func() Msg { + return printLineMessage{ + messageBody: fmt.Sprintf(template, args...), + } + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/tea.go b/vendor/github.com/charmbracelet/bubbletea/tea.go new file mode 100644 index 00000000..c4866f22 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/tea.go @@ -0,0 +1,904 @@ +// Package tea provides a framework for building rich terminal user interfaces +// based on the paradigms of The Elm Architecture. It's well-suited for simple +// and complex terminal applications, either inline, full-window, or a mix of +// both. It's been battle-tested in several large projects and is +// production-ready. +// +// A tutorial is available at https://github.com/charmbracelet/bubbletea/tree/master/tutorials +// +// Example programs can be found at https://github.com/charmbracelet/bubbletea/tree/master/examples +package tea + +import ( + "context" + "errors" + "fmt" + "io" + "os" + "os/signal" + "runtime" + "runtime/debug" + "sync" + "sync/atomic" + "syscall" + + "github.com/charmbracelet/x/term" + "github.com/muesli/cancelreader" + "golang.org/x/sync/errgroup" +) + +// ErrProgramPanic is returned by [Program.Run] when the program recovers from a panic. +var ErrProgramPanic = errors.New("program experienced a panic") + +// ErrProgramKilled is returned by [Program.Run] when the program gets killed. +var ErrProgramKilled = errors.New("program was killed") + +// ErrInterrupted is returned by [Program.Run] when the program get a SIGINT +// signal, or when it receives a [InterruptMsg]. +var ErrInterrupted = errors.New("program was interrupted") + +// Msg contain data from the result of a IO operation. Msgs trigger the update +// function and, henceforth, the UI. +type Msg interface{} + +// Model contains the program's state as well as its core functions. +type Model interface { + // Init is the first function that will be called. It returns an optional + // initial command. To not perform an initial command return nil. + Init() Cmd + + // Update is called when a message is received. Use it to inspect messages + // and, in response, update the model and/or send a command. + Update(Msg) (Model, Cmd) + + // View renders the program's UI, which is just a string. The view is + // rendered after every Update. + View() string +} + +// Cmd is an IO operation that returns a message when it's complete. If it's +// nil it's considered a no-op. Use it for things like HTTP requests, timers, +// saving and loading from disk, and so on. +// +// Note that there's almost never a reason to use a command to send a message +// to another part of your program. That can almost always be done in the +// update function. +type Cmd func() Msg + +type inputType int + +const ( + defaultInput inputType = iota + ttyInput + customInput +) + +// String implements the stringer interface for [inputType]. It is inteded to +// be used in testing. +func (i inputType) String() string { + return [...]string{ + "default input", + "tty input", + "custom input", + }[i] +} + +// Options to customize the program during its initialization. These are +// generally set with ProgramOptions. +// +// The options here are treated as bits. +type startupOptions int16 + +func (s startupOptions) has(option startupOptions) bool { + return s&option != 0 +} + +const ( + withAltScreen startupOptions = 1 << iota + withMouseCellMotion + withMouseAllMotion + withANSICompressor + withoutSignalHandler + // Catching panics is incredibly useful for restoring the terminal to a + // usable state after a panic occurs. When this is set, Bubble Tea will + // recover from panics, print the stack trace, and disable raw mode. This + // feature is on by default. + withoutCatchPanics + withoutBracketedPaste + withReportFocus +) + +// channelHandlers manages the series of channels returned by various processes. +// It allows us to wait for those processes to terminate before exiting the +// program. +type channelHandlers []chan struct{} + +// Adds a channel to the list of handlers. We wait for all handlers to terminate +// gracefully on shutdown. +func (h *channelHandlers) add(ch chan struct{}) { + *h = append(*h, ch) +} + +// shutdown waits for all handlers to terminate. +func (h channelHandlers) shutdown() { + var wg sync.WaitGroup + for _, ch := range h { + wg.Add(1) + go func(ch chan struct{}) { + <-ch + wg.Done() + }(ch) + } + wg.Wait() +} + +// Program is a terminal user interface. +type Program struct { + initialModel Model + + // handlers is a list of channels that need to be waited on before the + // program can exit. + handlers channelHandlers + + // Configuration options that will set as the program is initializing, + // treated as bits. These options can be set via various ProgramOptions. + startupOptions startupOptions + + // startupTitle is the title that will be set on the terminal when the + // program starts. + startupTitle string + + inputType inputType + + // externalCtx is a context that was passed in via WithContext, otherwise defaulting + // to ctx.Background() (in case it was not), the internal context is derived from it. + externalCtx context.Context + + // ctx is the programs's internal context for signalling internal teardown. + // It is built and derived from the externalCtx in NewProgram(). + ctx context.Context + cancel context.CancelFunc + + msgs chan Msg + errs chan error + finished chan struct{} + + // where to send output, this will usually be os.Stdout. + output io.Writer + // ttyOutput is null if output is not a TTY. + ttyOutput term.File + previousOutputState *term.State + renderer renderer + + // the environment variables for the program, defaults to os.Environ(). + environ []string + + // where to read inputs from, this will usually be os.Stdin. + input io.Reader + // ttyInput is null if input is not a TTY. + ttyInput term.File + previousTtyInputState *term.State + cancelReader cancelreader.CancelReader + readLoopDone chan struct{} + + // was the altscreen active before releasing the terminal? + altScreenWasActive bool + ignoreSignals uint32 + + bpWasActive bool // was the bracketed paste mode active before releasing the terminal? + reportFocus bool // was focus reporting active before releasing the terminal? + + filter func(Model, Msg) Msg + + // fps is the frames per second we should set on the renderer, if + // applicable, + fps int + + // mouseMode is true if the program should enable mouse mode on Windows. + mouseMode bool +} + +// Quit is a special command that tells the Bubble Tea program to exit. +func Quit() Msg { + return QuitMsg{} +} + +// QuitMsg signals that the program should quit. You can send a [QuitMsg] with +// [Quit]. +type QuitMsg struct{} + +// Suspend is a special command that tells the Bubble Tea program to suspend. +func Suspend() Msg { + return SuspendMsg{} +} + +// SuspendMsg signals the program should suspend. +// This usually happens when ctrl+z is pressed on common programs, but since +// bubbletea puts the terminal in raw mode, we need to handle it in a +// per-program basis. +// +// You can send this message with [Suspend()]. +type SuspendMsg struct{} + +// ResumeMsg can be listen to to do something once a program is resumed back +// from a suspend state. +type ResumeMsg struct{} + +// InterruptMsg signals the program should suspend. +// This usually happens when ctrl+c is pressed on common programs, but since +// bubbletea puts the terminal in raw mode, we need to handle it in a +// per-program basis. +// +// You can send this message with [Interrupt()]. +type InterruptMsg struct{} + +// Interrupt is a special command that tells the Bubble Tea program to +// interrupt. +func Interrupt() Msg { + return InterruptMsg{} +} + +// NewProgram creates a new Program. +func NewProgram(model Model, opts ...ProgramOption) *Program { + p := &Program{ + initialModel: model, + msgs: make(chan Msg), + } + + // Apply all options to the program. + for _, opt := range opts { + opt(p) + } + + // A context can be provided with a ProgramOption, but if none was provided + // we'll use the default background context. + if p.externalCtx == nil { + p.externalCtx = context.Background() + } + // Initialize context and teardown channel. + p.ctx, p.cancel = context.WithCancel(p.externalCtx) + + // if no output was set, set it to stdout + if p.output == nil { + p.output = os.Stdout + } + + // if no environment was set, set it to os.Environ() + if p.environ == nil { + p.environ = os.Environ() + } + + return p +} + +func (p *Program) handleSignals() chan struct{} { + ch := make(chan struct{}) + + // Listen for SIGINT and SIGTERM. + // + // In most cases ^C will not send an interrupt because the terminal will be + // in raw mode and ^C will be captured as a keystroke and sent along to + // Program.Update as a KeyMsg. When input is not a TTY, however, ^C will be + // caught here. + // + // SIGTERM is sent by unix utilities (like kill) to terminate a process. + go func() { + sig := make(chan os.Signal, 1) + signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM) + defer func() { + signal.Stop(sig) + close(ch) + }() + + for { + select { + case <-p.ctx.Done(): + return + + case s := <-sig: + if atomic.LoadUint32(&p.ignoreSignals) == 0 { + switch s { + case syscall.SIGINT: + p.msgs <- InterruptMsg{} + default: + p.msgs <- QuitMsg{} + } + return + } + } + } + }() + + return ch +} + +// handleResize handles terminal resize events. +func (p *Program) handleResize() chan struct{} { + ch := make(chan struct{}) + + if p.ttyOutput != nil { + // Get the initial terminal size and send it to the program. + go p.checkResize() + + // Listen for window resizes. + go p.listenForResize(ch) + } else { + close(ch) + } + + return ch +} + +// handleCommands runs commands in a goroutine and sends the result to the +// program's message channel. +func (p *Program) handleCommands(cmds chan Cmd) chan struct{} { + ch := make(chan struct{}) + + go func() { + defer close(ch) + + for { + select { + case <-p.ctx.Done(): + return + + case cmd := <-cmds: + if cmd == nil { + continue + } + + // Don't wait on these goroutines, otherwise the shutdown + // latency would get too large as a Cmd can run for some time + // (e.g. tick commands that sleep for half a second). It's not + // possible to cancel them so we'll have to leak the goroutine + // until Cmd returns. + go func() { + // Recover from panics. + if !p.startupOptions.has(withoutCatchPanics) { + defer func() { + if r := recover(); r != nil { + p.recoverFromGoPanic(r) + } + }() + } + + msg := cmd() // this can be long. + p.Send(msg) + }() + } + } + }() + + return ch +} + +func (p *Program) disableMouse() { + p.renderer.disableMouseCellMotion() + p.renderer.disableMouseAllMotion() + p.renderer.disableMouseSGRMode() +} + +// eventLoop is the central message loop. It receives and handles the default +// Bubble Tea messages, update the model and triggers redraws. +func (p *Program) eventLoop(model Model, cmds chan Cmd) (Model, error) { + for { + select { + case <-p.ctx.Done(): + return model, nil + + case err := <-p.errs: + return model, err + + case msg := <-p.msgs: + // Filter messages. + if p.filter != nil { + msg = p.filter(model, msg) + } + if msg == nil { + continue + } + + // Handle special internal messages. + switch msg := msg.(type) { + case QuitMsg: + return model, nil + + case InterruptMsg: + return model, ErrInterrupted + + case SuspendMsg: + if suspendSupported { + p.suspend() + } + + case clearScreenMsg: + p.renderer.clearScreen() + + case enterAltScreenMsg: + p.renderer.enterAltScreen() + + case exitAltScreenMsg: + p.renderer.exitAltScreen() + + case enableMouseCellMotionMsg, enableMouseAllMotionMsg: + switch msg.(type) { + case enableMouseCellMotionMsg: + p.renderer.enableMouseCellMotion() + case enableMouseAllMotionMsg: + p.renderer.enableMouseAllMotion() + } + // mouse mode (1006) is a no-op if the terminal doesn't support it. + p.renderer.enableMouseSGRMode() + + // XXX: This is used to enable mouse mode on Windows. We need + // to reinitialize the cancel reader to get the mouse events to + // work. + if runtime.GOOS == "windows" && !p.mouseMode { + p.mouseMode = true + p.initCancelReader(true) //nolint:errcheck,gosec + } + + case disableMouseMsg: + p.disableMouse() + + // XXX: On Windows, mouse mode is enabled on the input reader + // level. We need to instruct the input reader to stop reading + // mouse events. + if runtime.GOOS == "windows" && p.mouseMode { + p.mouseMode = false + p.initCancelReader(true) //nolint:errcheck,gosec + } + + case showCursorMsg: + p.renderer.showCursor() + + case hideCursorMsg: + p.renderer.hideCursor() + + case enableBracketedPasteMsg: + p.renderer.enableBracketedPaste() + + case disableBracketedPasteMsg: + p.renderer.disableBracketedPaste() + + case enableReportFocusMsg: + p.renderer.enableReportFocus() + + case disableReportFocusMsg: + p.renderer.disableReportFocus() + + case execMsg: + // NB: this blocks. + p.exec(msg.cmd, msg.fn) + + case BatchMsg: + for _, cmd := range msg { + select { + case <-p.ctx.Done(): + return model, nil + case cmds <- cmd: + } + } + continue + + case sequenceMsg: + go func() { + // Execute commands one at a time, in order. + for _, cmd := range msg { + if cmd == nil { + continue + } + + msg := cmd() + if batchMsg, ok := msg.(BatchMsg); ok { + g, _ := errgroup.WithContext(p.ctx) + for _, cmd := range batchMsg { + cmd := cmd + g.Go(func() error { + p.Send(cmd()) + return nil + }) + } + + //nolint:errcheck,gosec + g.Wait() // wait for all commands from batch msg to finish + continue + } + + p.Send(msg) + } + }() + + case setWindowTitleMsg: + p.SetWindowTitle(string(msg)) + + case windowSizeMsg: + go p.checkResize() + } + + // Process internal messages for the renderer. + if r, ok := p.renderer.(*standardRenderer); ok { + r.handleMessages(msg) + } + + var cmd Cmd + model, cmd = model.Update(msg) // run update + + select { + case <-p.ctx.Done(): + return model, nil + case cmds <- cmd: // process command (if any) + } + + p.renderer.write(model.View()) // send view to renderer + } + } +} + +// Run initializes the program and runs its event loops, blocking until it gets +// terminated by either [Program.Quit], [Program.Kill], or its signal handler. +// Returns the final model. +func (p *Program) Run() (returnModel Model, returnErr error) { + p.handlers = channelHandlers{} + cmds := make(chan Cmd) + p.errs = make(chan error, 1) + + p.finished = make(chan struct{}) + defer func() { + close(p.finished) + }() + + defer p.cancel() + + switch p.inputType { + case defaultInput: + p.input = os.Stdin + + // The user has not set a custom input, so we need to check whether or + // not standard input is a terminal. If it's not, we open a new TTY for + // input. This will allow things to "just work" in cases where data was + // piped in or redirected to the application. + // + // To disable input entirely pass nil to the [WithInput] program option. + f, isFile := p.input.(term.File) + if !isFile { + break + } + if term.IsTerminal(f.Fd()) { + break + } + + f, err := openInputTTY() + if err != nil { + return p.initialModel, err + } + defer f.Close() //nolint:errcheck + p.input = f + + case ttyInput: + // Open a new TTY, by request + f, err := openInputTTY() + if err != nil { + return p.initialModel, err + } + defer f.Close() //nolint:errcheck + p.input = f + + case customInput: + // (There is nothing extra to do.) + } + + // Handle signals. + if !p.startupOptions.has(withoutSignalHandler) { + p.handlers.add(p.handleSignals()) + } + + // Recover from panics. + if !p.startupOptions.has(withoutCatchPanics) { + defer func() { + if r := recover(); r != nil { + returnErr = fmt.Errorf("%w: %w", ErrProgramKilled, ErrProgramPanic) + p.recoverFromPanic(r) + } + }() + } + + // If no renderer is set use the standard one. + if p.renderer == nil { + p.renderer = newRenderer(p.output, p.startupOptions.has(withANSICompressor), p.fps) + } + + // Check if output is a TTY before entering raw mode, hiding the cursor and + // so on. + if err := p.initTerminal(); err != nil { + return p.initialModel, err + } + + // Honor program startup options. + if p.startupTitle != "" { + p.renderer.setWindowTitle(p.startupTitle) + } + if p.startupOptions&withAltScreen != 0 { + p.renderer.enterAltScreen() + } + if p.startupOptions&withoutBracketedPaste == 0 { + p.renderer.enableBracketedPaste() + } + if p.startupOptions&withMouseCellMotion != 0 { + p.renderer.enableMouseCellMotion() + p.renderer.enableMouseSGRMode() + } else if p.startupOptions&withMouseAllMotion != 0 { + p.renderer.enableMouseAllMotion() + p.renderer.enableMouseSGRMode() + } + + // XXX: Should we enable mouse mode on Windows? + // This needs to happen before initializing the cancel and input reader. + p.mouseMode = p.startupOptions&withMouseCellMotion != 0 || p.startupOptions&withMouseAllMotion != 0 + + if p.startupOptions&withReportFocus != 0 { + p.renderer.enableReportFocus() + } + + // Start the renderer. + p.renderer.start() + + // Initialize the program. + model := p.initialModel + if initCmd := model.Init(); initCmd != nil { + ch := make(chan struct{}) + p.handlers.add(ch) + + go func() { + defer close(ch) + + select { + case cmds <- initCmd: + case <-p.ctx.Done(): + } + }() + } + + // Render the initial view. + p.renderer.write(model.View()) + + // Subscribe to user input. + if p.input != nil { + if err := p.initCancelReader(false); err != nil { + return model, err + } + } + + // Handle resize events. + p.handlers.add(p.handleResize()) + + // Process commands. + p.handlers.add(p.handleCommands(cmds)) + + // Run event loop, handle updates and draw. + model, err := p.eventLoop(model, cmds) + + if err == nil && len(p.errs) > 0 { + err = <-p.errs // Drain a leftover error in case eventLoop crashed + } + + killed := p.externalCtx.Err() != nil || p.ctx.Err() != nil || err != nil + if killed { + if err == nil && p.externalCtx.Err() != nil { + // Return also as context error the cancellation of an external context. + // This is the context the user knows about and should be able to act on. + err = fmt.Errorf("%w: %w", ErrProgramKilled, p.externalCtx.Err()) + } else if err == nil && p.ctx.Err() != nil { + // Return only that the program was killed (not the internal mechanism). + // The user does not know or need to care about the internal program context. + err = ErrProgramKilled + } else { + // Return that the program was killed and also the error that caused it. + err = fmt.Errorf("%w: %w", ErrProgramKilled, err) + } + } else { + // Graceful shutdown of the program (not killed): + // Ensure we rendered the final state of the model. + p.renderer.write(model.View()) + } + + // Restore terminal state. + p.shutdown(killed) + + return model, err +} + +// StartReturningModel initializes the program and runs its event loops, +// blocking until it gets terminated by either [Program.Quit], [Program.Kill], +// or its signal handler. Returns the final model. +// +// Deprecated: please use [Program.Run] instead. +func (p *Program) StartReturningModel() (Model, error) { + return p.Run() +} + +// Start initializes the program and runs its event loops, blocking until it +// gets terminated by either [Program.Quit], [Program.Kill], or its signal +// handler. +// +// Deprecated: please use [Program.Run] instead. +func (p *Program) Start() error { + _, err := p.Run() + return err +} + +// Send sends a message to the main update function, effectively allowing +// messages to be injected from outside the program for interoperability +// purposes. +// +// If the program hasn't started yet this will be a blocking operation. +// If the program has already been terminated this will be a no-op, so it's safe +// to send messages after the program has exited. +func (p *Program) Send(msg Msg) { + select { + case <-p.ctx.Done(): + case p.msgs <- msg: + } +} + +// Quit is a convenience function for quitting Bubble Tea programs. Use it +// when you need to shut down a Bubble Tea program from the outside. +// +// If you wish to quit from within a Bubble Tea program use the Quit command. +// +// If the program is not running this will be a no-op, so it's safe to call +// if the program is unstarted or has already exited. +func (p *Program) Quit() { + p.Send(Quit()) +} + +// Kill signals the program to stop immediately and restore the former terminal state. +// The final render that you would normally see when quitting will be skipped. +// [program.Run] returns a [ErrProgramKilled] error. +func (p *Program) Kill() { + p.cancel() +} + +// Wait waits/blocks until the underlying Program finished shutting down. +func (p *Program) Wait() { + <-p.finished +} + +// shutdown performs operations to free up resources and restore the terminal +// to its original state. It is called once at the end of the program's lifetime. +// +// This method should not be called to signal the program to be killed/shutdown. +// Doing so can lead to race conditions with the eventual call at the program's end. +// As alternatives, the [Quit] or [Kill] convenience methods should be used instead. +func (p *Program) shutdown(kill bool) { + p.cancel() + + // Wait for all handlers to finish. + p.handlers.shutdown() + + // Check if the cancel reader has been setup before waiting and closing. + if p.cancelReader != nil { + // Wait for input loop to finish. + if p.cancelReader.Cancel() { + if !kill { + p.waitForReadLoop() + } + } + _ = p.cancelReader.Close() + } + + if p.renderer != nil { + if kill { + p.renderer.kill() + } else { + p.renderer.stop() + } + } + + _ = p.restoreTerminalState() +} + +// recoverFromPanic recovers from a panic, prints the stack trace, and restores +// the terminal to a usable state. +func (p *Program) recoverFromPanic(r interface{}) { + select { + case p.errs <- ErrProgramPanic: + default: + } + p.shutdown(true) // Ok to call here, p.Run() cannot do it anymore. + fmt.Printf("Caught panic:\n\n%s\n\nRestoring terminal...\n\n", r) + debug.PrintStack() +} + +// recoverFromGoPanic recovers from a goroutine panic, prints a stack trace and +// signals for the program to be killed and terminal restored to a usable state. +func (p *Program) recoverFromGoPanic(r interface{}) { + select { + case p.errs <- ErrProgramPanic: + default: + } + p.cancel() + fmt.Printf("Caught goroutine panic:\n\n%s\n\nRestoring terminal...\n\n", r) + debug.PrintStack() +} + +// ReleaseTerminal restores the original terminal state and cancels the input +// reader. You can return control to the Program with RestoreTerminal. +func (p *Program) ReleaseTerminal() error { + atomic.StoreUint32(&p.ignoreSignals, 1) + if p.cancelReader != nil { + p.cancelReader.Cancel() + } + + p.waitForReadLoop() + + if p.renderer != nil { + p.renderer.stop() + p.altScreenWasActive = p.renderer.altScreen() + p.bpWasActive = p.renderer.bracketedPasteActive() + p.reportFocus = p.renderer.reportFocus() + } + + return p.restoreTerminalState() +} + +// RestoreTerminal reinitializes the Program's input reader, restores the +// terminal to the former state when the program was running, and repaints. +// Use it to reinitialize a Program after running ReleaseTerminal. +func (p *Program) RestoreTerminal() error { + atomic.StoreUint32(&p.ignoreSignals, 0) + + if err := p.initTerminal(); err != nil { + return err + } + if err := p.initCancelReader(false); err != nil { + return err + } + if p.altScreenWasActive { + p.renderer.enterAltScreen() + } else { + // entering alt screen already causes a repaint. + go p.Send(repaintMsg{}) + } + if p.renderer != nil { + p.renderer.start() + } + if p.bpWasActive { + p.renderer.enableBracketedPaste() + } + if p.reportFocus { + p.renderer.enableReportFocus() + } + + // If the output is a terminal, it may have been resized while another + // process was at the foreground, in which case we may not have received + // SIGWINCH. Detect any size change now and propagate the new size as + // needed. + go p.checkResize() + + return nil +} + +// Println prints above the Program. This output is unmanaged by the program +// and will persist across renders by the Program. +// +// If the altscreen is active no output will be printed. +func (p *Program) Println(args ...interface{}) { + p.msgs <- printLineMessage{ + messageBody: fmt.Sprint(args...), + } +} + +// Printf prints above the Program. It takes a format template followed by +// values similar to fmt.Printf. This output is unmanaged by the program and +// will persist across renders by the Program. +// +// Unlike fmt.Printf (but similar to log.Printf) the message will be print on +// its own line. +// +// If the altscreen is active no output will be printed. +func (p *Program) Printf(template string, args ...interface{}) { + p.msgs <- printLineMessage{ + messageBody: fmt.Sprintf(template, args...), + } +} diff --git a/vendor/github.com/charmbracelet/bubbletea/tea_init.go b/vendor/github.com/charmbracelet/bubbletea/tea_init.go new file mode 100644 index 00000000..19b6cc39 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/tea_init.go @@ -0,0 +1,22 @@ +package tea + +import ( + "github.com/charmbracelet/lipgloss" +) + +func init() { + // XXX: This is a workaround to make assure that Lip Gloss and Termenv + // query the terminal before any Bubble Tea Program runs and acquires the + // terminal. Without this, Programs that use Lip Gloss/Termenv might hang + // while waiting for a a [termenv.OSCTimeout] while querying the terminal + // for its background/foreground colors. + // + // This happens because Bubble Tea acquires the terminal before termenv + // reads any responses. + // + // Note that this will only affect programs running on the default IO i.e. + // [os.Stdout] and [os.Stdin]. + // + // This workaround will be removed in v2. + _ = lipgloss.HasDarkBackground() +} diff --git a/vendor/github.com/charmbracelet/bubbletea/tty.go b/vendor/github.com/charmbracelet/bubbletea/tty.go new file mode 100644 index 00000000..6812bfc5 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/tty.go @@ -0,0 +1,141 @@ +package tea + +import ( + "errors" + "fmt" + "io" + "time" + + "github.com/charmbracelet/x/term" + "github.com/muesli/cancelreader" +) + +func (p *Program) suspend() { + if err := p.ReleaseTerminal(); err != nil { + // If we can't release input, abort. + return + } + + suspendProcess() + + _ = p.RestoreTerminal() + go p.Send(ResumeMsg{}) +} + +func (p *Program) initTerminal() error { + if _, ok := p.renderer.(*nilRenderer); ok { + // No need to initialize the terminal if we're not rendering + return nil + } + + if err := p.initInput(); err != nil { + return err + } + + p.renderer.hideCursor() + return nil +} + +// restoreTerminalState restores the terminal to the state prior to running the +// Bubble Tea program. +func (p *Program) restoreTerminalState() error { + if p.renderer != nil { + p.renderer.disableBracketedPaste() + p.renderer.showCursor() + p.disableMouse() + + if p.renderer.reportFocus() { + p.renderer.disableReportFocus() + } + + if p.renderer.altScreen() { + p.renderer.exitAltScreen() + + // give the terminal a moment to catch up + time.Sleep(time.Millisecond * 10) //nolint:mnd + } + } + + return p.restoreInput() +} + +// restoreInput restores the tty input to its original state. +func (p *Program) restoreInput() error { + if p.ttyInput != nil && p.previousTtyInputState != nil { + if err := term.Restore(p.ttyInput.Fd(), p.previousTtyInputState); err != nil { + return fmt.Errorf("error restoring console: %w", err) + } + } + if p.ttyOutput != nil && p.previousOutputState != nil { + if err := term.Restore(p.ttyOutput.Fd(), p.previousOutputState); err != nil { + return fmt.Errorf("error restoring console: %w", err) + } + } + return nil +} + +// initCancelReader (re)commences reading inputs. +func (p *Program) initCancelReader(cancel bool) error { + if cancel && p.cancelReader != nil { + p.cancelReader.Cancel() + p.waitForReadLoop() + } + + var err error + p.cancelReader, err = newInputReader(p.input, p.mouseMode) + if err != nil { + return fmt.Errorf("error creating cancelreader: %w", err) + } + + p.readLoopDone = make(chan struct{}) + go p.readLoop() + + return nil +} + +func (p *Program) readLoop() { + defer close(p.readLoopDone) + + err := readInputs(p.ctx, p.msgs, p.cancelReader) + if !errors.Is(err, io.EOF) && !errors.Is(err, cancelreader.ErrCanceled) { + select { + case <-p.ctx.Done(): + case p.errs <- err: + } + } +} + +// waitForReadLoop waits for the cancelReader to finish its read loop. +func (p *Program) waitForReadLoop() { + select { + case <-p.readLoopDone: + case <-time.After(500 * time.Millisecond): //nolint:mnd + // The read loop hangs, which means the input + // cancelReader's cancel function has returned true even + // though it was not able to cancel the read. + } +} + +// checkResize detects the current size of the output and informs the program +// via a WindowSizeMsg. +func (p *Program) checkResize() { + if p.ttyOutput == nil { + // can't query window size + return + } + + w, h, err := term.GetSize(p.ttyOutput.Fd()) + if err != nil { + select { + case <-p.ctx.Done(): + case p.errs <- err: + } + + return + } + + p.Send(WindowSizeMsg{ + Width: w, + Height: h, + }) +} diff --git a/vendor/github.com/charmbracelet/bubbletea/tty_unix.go b/vendor/github.com/charmbracelet/bubbletea/tty_unix.go new file mode 100644 index 00000000..5cbb4fe1 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/tty_unix.go @@ -0,0 +1,49 @@ +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || aix || zos +// +build darwin dragonfly freebsd linux netbsd openbsd solaris aix zos + +package tea + +import ( + "fmt" + "os" + "os/signal" + "syscall" + + "github.com/charmbracelet/x/term" +) + +func (p *Program) initInput() (err error) { + // Check if input is a terminal + if f, ok := p.input.(term.File); ok && term.IsTerminal(f.Fd()) { + p.ttyInput = f + p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd()) + if err != nil { + return fmt.Errorf("error entering raw mode: %w", err) + } + } + + if f, ok := p.output.(term.File); ok && term.IsTerminal(f.Fd()) { + p.ttyOutput = f + } + + return nil +} + +func openInputTTY() (*os.File, error) { + f, err := os.Open("/dev/tty") + if err != nil { + return nil, fmt.Errorf("could not open a new TTY: %w", err) + } + return f, nil +} + +const suspendSupported = true + +// Send SIGTSTP to the entire process group. +func suspendProcess() { + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGCONT) + _ = syscall.Kill(0, syscall.SIGTSTP) + // blocks until a CONT happens... + <-c +} diff --git a/vendor/github.com/charmbracelet/bubbletea/tty_windows.go b/vendor/github.com/charmbracelet/bubbletea/tty_windows.go new file mode 100644 index 00000000..154491a6 --- /dev/null +++ b/vendor/github.com/charmbracelet/bubbletea/tty_windows.go @@ -0,0 +1,68 @@ +//go:build windows +// +build windows + +package tea + +import ( + "fmt" + "os" + + "github.com/charmbracelet/x/term" + "golang.org/x/sys/windows" +) + +func (p *Program) initInput() (err error) { + // Save stdin state and enable VT input + // We also need to enable VT + // input here. + if f, ok := p.input.(term.File); ok && term.IsTerminal(f.Fd()) { + p.ttyInput = f + p.previousTtyInputState, err = term.MakeRaw(p.ttyInput.Fd()) + if err != nil { + return fmt.Errorf("error making raw: %w", err) + } + + // Enable VT input + var mode uint32 + if err := windows.GetConsoleMode(windows.Handle(p.ttyInput.Fd()), &mode); err != nil { + return fmt.Errorf("error getting console mode: %w", err) + } + + if err := windows.SetConsoleMode(windows.Handle(p.ttyInput.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_INPUT); err != nil { + return fmt.Errorf("error setting console mode: %w", err) + } + } + + // Save output screen buffer state and enable VT processing. + if f, ok := p.output.(term.File); ok && term.IsTerminal(f.Fd()) { + p.ttyOutput = f + p.previousOutputState, err = term.GetState(f.Fd()) + if err != nil { + return fmt.Errorf("error getting state: %w", err) + } + + var mode uint32 + if err := windows.GetConsoleMode(windows.Handle(p.ttyOutput.Fd()), &mode); err != nil { + return fmt.Errorf("error getting console mode: %w", err) + } + + if err := windows.SetConsoleMode(windows.Handle(p.ttyOutput.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil { + return fmt.Errorf("error setting console mode: %w", err) + } + } + + return nil +} + +// Open the Windows equivalent of a TTY. +func openInputTTY() (*os.File, error) { + f, err := os.OpenFile("CONIN$", os.O_RDWR, 0o644) + if err != nil { + return nil, fmt.Errorf("error opening file: %w", err) + } + return f, nil +} + +const suspendSupported = false + +func suspendProcess() {} diff --git a/vendor/github.com/charmbracelet/colorprofile/.golangci-soft.yml b/vendor/github.com/charmbracelet/colorprofile/.golangci-soft.yml new file mode 100644 index 00000000..d325d4fc --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/.golangci-soft.yml @@ -0,0 +1,40 @@ +run: + tests: false + issues-exit-code: 0 + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - exhaustive + - goconst + - godot + - godox + - mnd + - gomoddirectives + - goprintffuncname + - misspell + - nakedret + - nestif + - noctx + - nolintlint + - prealloc + - wrapcheck + + # disable default linters, they are already enabled in .golangci.yml + disable: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - unused diff --git a/vendor/github.com/charmbracelet/colorprofile/.golangci.yml b/vendor/github.com/charmbracelet/colorprofile/.golangci.yml new file mode 100644 index 00000000..d6789e01 --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/.golangci.yml @@ -0,0 +1,28 @@ +run: + tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - bodyclose + - gofumpt + - goimports + - gosec + - nilerr + - revive + - rowserrcheck + - sqlclosecheck + - tparallel + - unconvert + - unparam + - whitespace diff --git a/vendor/github.com/charmbracelet/colorprofile/.goreleaser.yml b/vendor/github.com/charmbracelet/colorprofile/.goreleaser.yml new file mode 100644 index 00000000..40d9f298 --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/.goreleaser.yml @@ -0,0 +1,6 @@ +includes: + - from_url: + url: charmbracelet/meta/main/goreleaser-lib.yaml + +# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json + diff --git a/vendor/github.com/charmbracelet/colorprofile/LICENSE b/vendor/github.com/charmbracelet/colorprofile/LICENSE new file mode 100644 index 00000000..b7974b07 --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020-2024 Charmbracelet, Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/charmbracelet/colorprofile/README.md b/vendor/github.com/charmbracelet/colorprofile/README.md new file mode 100644 index 00000000..c72b2f4b --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/README.md @@ -0,0 +1,103 @@ +# Colorprofile + +

+ Latest Release + GoDoc + Build Status +

+ +A simple, powerful—and at times magical—package for detecting terminal color +profiles and performing color (and CSI) degradation. + +## Detecting the terminal’s color profile + +Detecting the terminal’s color profile is easy. + +```go +import "github.com/charmbracelet/colorprofile" + +// Detect the color profile. If you’re planning on writing to stderr you'd want +// to use os.Stderr instead. +p := colorprofile.Detect(os.Stdout, os.Environ()) + +// Comment on the profile. +fmt.Printf("You know, your colors are quite %s.", func() string { + switch p { + case colorprofile.TrueColor: + return "fancy" + case colorprofile.ANSI256: + return "1990s fancy" + case colorprofile.ANSI: + return "normcore" + case colorprofile.Ascii: + return "ancient" + case colorprofile.NoTTY: + return "naughty!" + } + return "...IDK" // this should never happen +}()) +``` + +## Downsampling colors + +When necessary, colors can be downsampled to a given profile, or manually +downsampled to a specific profile. + +```go +p := colorprofile.Detect(os.Stdout, os.Environ()) +c := color.RGBA{0x6b, 0x50, 0xff, 0xff} // #6b50ff + +// Downsample to the detected profile, when necessary. +convertedColor := p.Convert(c) + +// Or manually convert to a given profile. +ansi256Color := colorprofile.ANSI256.Convert(c) +ansiColor := colorprofile.ANSI.Convert(c) +noColor := colorprofile.Ascii.Convert(c) +noANSI := colorprofile.NoTTY.Convert(c) +``` + +## Automatic downsampling with a Writer + +You can also magically downsample colors in ANSI output, when necessary. If +output is not a TTY ANSI will be dropped entirely. + +```go +myFancyANSI := "\x1b[38;2;107;80;255mCute \x1b[1;3mpuppy!!\x1b[m" + +// Automatically downsample for the terminal at stdout. +w := colorprofile.NewWriter(os.Stdout, os.Environ()) +fmt.Fprintf(w, myFancyANSI) + +// Downsample to 4-bit ANSI. +w.Profile = colorprofile.ANSI +fmt.Fprintf(w, myFancyANSI) + +// Ascii-fy, no colors. +w.Profile = colorprofile.Ascii +fmt.Fprintf(w, myFancyANSI) + +// Strip ANSI altogether. +w.Profile = colorprofile.NoTTY +fmt.Fprintf(w, myFancyANSI) // not as fancy +``` + +## Feedback + +We’d love to hear your thoughts on this project. Feel free to drop us a note! + +- [Twitter](https://twitter.com/charmcli) +- [The Fediverse](https://mastodon.social/@charmcli) +- [Discord](https://charm.sh/chat) + +## License + +[MIT](https://github.com/charmbracelet/bubbletea/raw/master/LICENSE) + +--- + +Part of [Charm](https://charm.sh). + +The Charm logo + +Charm热爱开源 • Charm loves open source • نحنُ نحب المصادر المفتوحة diff --git a/vendor/github.com/charmbracelet/colorprofile/env.go b/vendor/github.com/charmbracelet/colorprofile/env.go new file mode 100644 index 00000000..8df3d8f7 --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/env.go @@ -0,0 +1,287 @@ +package colorprofile + +import ( + "bytes" + "io" + "os/exec" + "runtime" + "strconv" + "strings" + + "github.com/charmbracelet/x/term" + "github.com/xo/terminfo" +) + +// Detect returns the color profile based on the terminal output, and +// environment variables. This respects NO_COLOR, CLICOLOR, and CLICOLOR_FORCE +// environment variables. +// +// The rules as follows: +// - TERM=dumb is always treated as NoTTY unless CLICOLOR_FORCE=1 is set. +// - If COLORTERM=truecolor, and the profile is not NoTTY, it gest upgraded to TrueColor. +// - Using any 256 color terminal (e.g. TERM=xterm-256color) will set the profile to ANSI256. +// - Using any color terminal (e.g. TERM=xterm-color) will set the profile to ANSI. +// - Using CLICOLOR=1 without TERM defined should be treated as ANSI if the +// output is a terminal. +// - NO_COLOR takes precedence over CLICOLOR/CLICOLOR_FORCE, and will disable +// colors but not text decoration, i.e. bold, italic, faint, etc. +// +// See https://no-color.org/ and https://bixense.com/clicolors/ for more information. +func Detect(output io.Writer, env []string) Profile { + out, ok := output.(term.File) + isatty := ok && term.IsTerminal(out.Fd()) + environ := newEnviron(env) + term := environ.get("TERM") + isDumb := term == "dumb" + envp := colorProfile(isatty, environ) + if envp == TrueColor || envNoColor(environ) { + // We already know we have TrueColor, or NO_COLOR is set. + return envp + } + + if isatty && !isDumb { + tip := Terminfo(term) + tmuxp := tmux(environ) + + // Color profile is the maximum of env, terminfo, and tmux. + return max(envp, max(tip, tmuxp)) + } + + return envp +} + +// Env returns the color profile based on the terminal environment variables. +// This respects NO_COLOR, CLICOLOR, and CLICOLOR_FORCE environment variables. +// +// The rules as follows: +// - TERM=dumb is always treated as NoTTY unless CLICOLOR_FORCE=1 is set. +// - If COLORTERM=truecolor, and the profile is not NoTTY, it gest upgraded to TrueColor. +// - Using any 256 color terminal (e.g. TERM=xterm-256color) will set the profile to ANSI256. +// - Using any color terminal (e.g. TERM=xterm-color) will set the profile to ANSI. +// - Using CLICOLOR=1 without TERM defined should be treated as ANSI if the +// output is a terminal. +// - NO_COLOR takes precedence over CLICOLOR/CLICOLOR_FORCE, and will disable +// colors but not text decoration, i.e. bold, italic, faint, etc. +// +// See https://no-color.org/ and https://bixense.com/clicolors/ for more information. +func Env(env []string) (p Profile) { + return colorProfile(true, newEnviron(env)) +} + +func colorProfile(isatty bool, env environ) (p Profile) { + isDumb := env.get("TERM") == "dumb" + envp := envColorProfile(env) + if !isatty || isDumb { + // Check if the output is a terminal. + // Treat dumb terminals as NoTTY + p = NoTTY + } else { + p = envp + } + + if envNoColor(env) && isatty { + if p > Ascii { + p = Ascii + } + return + } + + if cliColorForced(env) { + if p < ANSI { + p = ANSI + } + if envp > p { + p = envp + } + + return + } + + if cliColor(env) { + if isatty && !isDumb && p < ANSI { + p = ANSI + } + } + + return p +} + +// envNoColor returns true if the environment variables explicitly disable color output +// by setting NO_COLOR (https://no-color.org/). +func envNoColor(env environ) bool { + noColor, _ := strconv.ParseBool(env.get("NO_COLOR")) + return noColor +} + +func cliColor(env environ) bool { + cliColor, _ := strconv.ParseBool(env.get("CLICOLOR")) + return cliColor +} + +func cliColorForced(env environ) bool { + cliColorForce, _ := strconv.ParseBool(env.get("CLICOLOR_FORCE")) + return cliColorForce +} + +func colorTerm(env environ) bool { + colorTerm := strings.ToLower(env.get("COLORTERM")) + return colorTerm == "truecolor" || colorTerm == "24bit" || + colorTerm == "yes" || colorTerm == "true" +} + +// envColorProfile returns infers the color profile from the environment. +func envColorProfile(env environ) (p Profile) { + term, ok := env.lookup("TERM") + if !ok || len(term) == 0 || term == "dumb" { + p = NoTTY + if runtime.GOOS == "windows" { + // Use Windows API to detect color profile. Windows Terminal and + // cmd.exe don't define $TERM. + if wcp, ok := windowsColorProfile(env); ok { + p = wcp + } + } + } else { + p = ANSI + } + + parts := strings.Split(term, "-") + switch parts[0] { + case "alacritty", + "contour", + "foot", + "ghostty", + "kitty", + "rio", + "st", + "wezterm": + return TrueColor + case "xterm": + if len(parts) > 1 { + switch parts[1] { + case "ghostty", "kitty": + // These terminals can be defined as xterm-TERMNAME + return TrueColor + } + } + case "tmux", "screen": + if p < ANSI256 { + p = ANSI256 + } + } + + if isCloudShell, _ := strconv.ParseBool(env.get("GOOGLE_CLOUD_SHELL")); isCloudShell { + return TrueColor + } + + // GNU Screen doesn't support TrueColor + // Tmux doesn't support $COLORTERM + if colorTerm(env) && !strings.HasPrefix(term, "screen") && !strings.HasPrefix(term, "tmux") { + return TrueColor + } + + if strings.HasSuffix(term, "256color") && p < ANSI256 { + p = ANSI256 + } + + return +} + +// Terminfo returns the color profile based on the terminal's terminfo +// database. This relies on the Tc and RGB capabilities to determine if the +// terminal supports TrueColor. +// If term is empty or "dumb", it returns NoTTY. +func Terminfo(term string) (p Profile) { + if len(term) == 0 || term == "dumb" { + return NoTTY + } + + p = ANSI + ti, err := terminfo.Load(term) + if err != nil { + return + } + + extbools := ti.ExtBoolCapsShort() + if _, ok := extbools["Tc"]; ok { + return TrueColor + } + + if _, ok := extbools["RGB"]; ok { + return TrueColor + } + + return +} + +// Tmux returns the color profile based on `tmux info` output. Tmux supports +// overriding the terminal's color capabilities, so this function will return +// the color profile based on the tmux configuration. +func Tmux(env []string) Profile { + return tmux(newEnviron(env)) +} + +// tmux returns the color profile based on the tmux environment variables. +func tmux(env environ) (p Profile) { + if tmux, ok := env.lookup("TMUX"); !ok || len(tmux) == 0 { + // Not in tmux + return NoTTY + } + + // Check if tmux has either Tc or RGB capabilities. Otherwise, return + // ANSI256. + p = ANSI256 + cmd := exec.Command("tmux", "info") + out, err := cmd.Output() + if err != nil { + return + } + + for _, line := range bytes.Split(out, []byte("\n")) { + if (bytes.Contains(line, []byte("Tc")) || bytes.Contains(line, []byte("RGB"))) && + bytes.Contains(line, []byte("true")) { + return TrueColor + } + } + + return +} + +// environ is a map of environment variables. +type environ map[string]string + +// newEnviron returns a new environment map from a slice of environment +// variables. +func newEnviron(environ []string) environ { + m := make(map[string]string, len(environ)) + for _, e := range environ { + parts := strings.SplitN(e, "=", 2) + var value string + if len(parts) == 2 { + value = parts[1] + } + m[parts[0]] = value + } + return m +} + +// lookup returns the value of an environment variable and a boolean indicating +// if it exists. +func (e environ) lookup(key string) (string, bool) { + v, ok := e[key] + return v, ok +} + +// get returns the value of an environment variable and empty string if it +// doesn't exist. +func (e environ) get(key string) string { + v, _ := e.lookup(key) + return v +} + +func max[T ~byte | ~int](a, b T) T { + if a > b { + return a + } + return b +} diff --git a/vendor/github.com/charmbracelet/colorprofile/env_other.go b/vendor/github.com/charmbracelet/colorprofile/env_other.go new file mode 100644 index 00000000..080994bc --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/env_other.go @@ -0,0 +1,8 @@ +//go:build !windows +// +build !windows + +package colorprofile + +func windowsColorProfile(map[string]string) (Profile, bool) { + return 0, false +} diff --git a/vendor/github.com/charmbracelet/colorprofile/env_windows.go b/vendor/github.com/charmbracelet/colorprofile/env_windows.go new file mode 100644 index 00000000..3b9c28f9 --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/env_windows.go @@ -0,0 +1,45 @@ +//go:build windows +// +build windows + +package colorprofile + +import ( + "strconv" + + "golang.org/x/sys/windows" +) + +func windowsColorProfile(env map[string]string) (Profile, bool) { + if env["ConEmuANSI"] == "ON" { + return TrueColor, true + } + + if len(env["WT_SESSION"]) > 0 { + // Windows Terminal supports TrueColor + return TrueColor, true + } + + major, _, build := windows.RtlGetNtVersionNumbers() + if build < 10586 || major < 10 { + // No ANSI support before WindowsNT 10 build 10586 + if len(env["ANSICON"]) > 0 { + ansiconVer := env["ANSICON_VER"] + cv, err := strconv.Atoi(ansiconVer) + if err != nil || cv < 181 { + // No 8 bit color support before ANSICON 1.81 + return ANSI, true + } + + return ANSI256, true + } + + return NoTTY, true + } + + if build < 14931 { + // No true color support before build 14931 + return ANSI256, true + } + + return TrueColor, true +} diff --git a/vendor/github.com/charmbracelet/colorprofile/profile.go b/vendor/github.com/charmbracelet/colorprofile/profile.go new file mode 100644 index 00000000..97e37ac3 --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/profile.go @@ -0,0 +1,399 @@ +package colorprofile + +import ( + "image/color" + "math" + + "github.com/charmbracelet/x/ansi" + "github.com/lucasb-eyer/go-colorful" +) + +// Profile is a color profile: NoTTY, Ascii, ANSI, ANSI256, or TrueColor. +type Profile byte + +const ( + // NoTTY, not a terminal profile. + NoTTY Profile = iota + // Ascii, uncolored profile. + Ascii //nolint:revive + // ANSI, 4-bit color profile. + ANSI + // ANSI256, 8-bit color profile. + ANSI256 + // TrueColor, 24-bit color profile. + TrueColor +) + +// String returns the string representation of a Profile. +func (p Profile) String() string { + switch p { + case TrueColor: + return "TrueColor" + case ANSI256: + return "ANSI256" + case ANSI: + return "ANSI" + case Ascii: + return "Ascii" + case NoTTY: + return "NoTTY" + } + return "Unknown" +} + +// Convert transforms a given Color to a Color supported within the Profile. +func (p Profile) Convert(c color.Color) color.Color { + if p <= Ascii { + return nil + } + + switch c := c.(type) { + case ansi.BasicColor: + return c + + case ansi.ExtendedColor: + if p == ANSI { + return ansi256ToANSIColor(c) + } + return c + + case ansi.TrueColor, color.Color: + h, ok := colorful.MakeColor(c) + if !ok { + return nil + } + if p != TrueColor { + ac := hexToANSI256Color(h) + if p == ANSI { + return ansi256ToANSIColor(ac) + } + return ac + } + return c + } + + return c +} + +func hexToANSI256Color(c colorful.Color) ansi.ExtendedColor { + v2ci := func(v float64) int { + if v < 48 { + return 0 + } + if v < 115 { + return 1 + } + return int((v - 35) / 40) + } + + // Calculate the nearest 0-based color index at 16..231 + r := v2ci(c.R * 255.0) // 0..5 each + g := v2ci(c.G * 255.0) + b := v2ci(c.B * 255.0) + ci := 36*r + 6*g + b /* 0..215 */ + + // Calculate the represented colors back from the index + i2cv := [6]int{0, 0x5f, 0x87, 0xaf, 0xd7, 0xff} + cr := i2cv[r] // r/g/b, 0..255 each + cg := i2cv[g] + cb := i2cv[b] + + // Calculate the nearest 0-based gray index at 232..255 + var grayIdx int + average := (cr + cg + cb) / 3 + if average > 238 { + grayIdx = 23 + } else { + grayIdx = (average - 3) / 10 // 0..23 + } + gv := 8 + 10*grayIdx // same value for r/g/b, 0..255 + + // Return the one which is nearer to the original input rgb value + c2 := colorful.Color{R: float64(cr) / 255.0, G: float64(cg) / 255.0, B: float64(cb) / 255.0} + g2 := colorful.Color{R: float64(gv) / 255.0, G: float64(gv) / 255.0, B: float64(gv) / 255.0} + colorDist := c.DistanceHSLuv(c2) + grayDist := c.DistanceHSLuv(g2) + + if colorDist <= grayDist { + return ansi.ExtendedColor(16 + ci) //nolint:gosec + } + return ansi.ExtendedColor(232 + grayIdx) //nolint:gosec +} + +func ansi256ToANSIColor(c ansi.ExtendedColor) ansi.BasicColor { + var r int + md := math.MaxFloat64 + + h, _ := colorful.Hex(ansiHex[c]) + for i := 0; i <= 15; i++ { + hb, _ := colorful.Hex(ansiHex[i]) + d := h.DistanceHSLuv(hb) + + if d < md { + md = d + r = i + } + } + + return ansi.BasicColor(r) //nolint:gosec +} + +// RGB values of ANSI colors (0-255). +var ansiHex = []string{ + "#000000", + "#800000", + "#008000", + "#808000", + "#000080", + "#800080", + "#008080", + "#c0c0c0", + "#808080", + "#ff0000", + "#00ff00", + "#ffff00", + "#0000ff", + "#ff00ff", + "#00ffff", + "#ffffff", + "#000000", + "#00005f", + "#000087", + "#0000af", + "#0000d7", + "#0000ff", + "#005f00", + "#005f5f", + "#005f87", + "#005faf", + "#005fd7", + "#005fff", + "#008700", + "#00875f", + "#008787", + "#0087af", + "#0087d7", + "#0087ff", + "#00af00", + "#00af5f", + "#00af87", + "#00afaf", + "#00afd7", + "#00afff", + "#00d700", + "#00d75f", + "#00d787", + "#00d7af", + "#00d7d7", + "#00d7ff", + "#00ff00", + "#00ff5f", + "#00ff87", + "#00ffaf", + "#00ffd7", + "#00ffff", + "#5f0000", + "#5f005f", + "#5f0087", + "#5f00af", + "#5f00d7", + "#5f00ff", + "#5f5f00", + "#5f5f5f", + "#5f5f87", + "#5f5faf", + "#5f5fd7", + "#5f5fff", + "#5f8700", + "#5f875f", + "#5f8787", + "#5f87af", + "#5f87d7", + "#5f87ff", + "#5faf00", + "#5faf5f", + "#5faf87", + "#5fafaf", + "#5fafd7", + "#5fafff", + "#5fd700", + "#5fd75f", + "#5fd787", + "#5fd7af", + "#5fd7d7", + "#5fd7ff", + "#5fff00", + "#5fff5f", + "#5fff87", + "#5fffaf", + "#5fffd7", + "#5fffff", + "#870000", + "#87005f", + "#870087", + "#8700af", + "#8700d7", + "#8700ff", + "#875f00", + "#875f5f", + "#875f87", + "#875faf", + "#875fd7", + "#875fff", + "#878700", + "#87875f", + "#878787", + "#8787af", + "#8787d7", + "#8787ff", + "#87af00", + "#87af5f", + "#87af87", + "#87afaf", + "#87afd7", + "#87afff", + "#87d700", + "#87d75f", + "#87d787", + "#87d7af", + "#87d7d7", + "#87d7ff", + "#87ff00", + "#87ff5f", + "#87ff87", + "#87ffaf", + "#87ffd7", + "#87ffff", + "#af0000", + "#af005f", + "#af0087", + "#af00af", + "#af00d7", + "#af00ff", + "#af5f00", + "#af5f5f", + "#af5f87", + "#af5faf", + "#af5fd7", + "#af5fff", + "#af8700", + "#af875f", + "#af8787", + "#af87af", + "#af87d7", + "#af87ff", + "#afaf00", + "#afaf5f", + "#afaf87", + "#afafaf", + "#afafd7", + "#afafff", + "#afd700", + "#afd75f", + "#afd787", + "#afd7af", + "#afd7d7", + "#afd7ff", + "#afff00", + "#afff5f", + "#afff87", + "#afffaf", + "#afffd7", + "#afffff", + "#d70000", + "#d7005f", + "#d70087", + "#d700af", + "#d700d7", + "#d700ff", + "#d75f00", + "#d75f5f", + "#d75f87", + "#d75faf", + "#d75fd7", + "#d75fff", + "#d78700", + "#d7875f", + "#d78787", + "#d787af", + "#d787d7", + "#d787ff", + "#d7af00", + "#d7af5f", + "#d7af87", + "#d7afaf", + "#d7afd7", + "#d7afff", + "#d7d700", + "#d7d75f", + "#d7d787", + "#d7d7af", + "#d7d7d7", + "#d7d7ff", + "#d7ff00", + "#d7ff5f", + "#d7ff87", + "#d7ffaf", + "#d7ffd7", + "#d7ffff", + "#ff0000", + "#ff005f", + "#ff0087", + "#ff00af", + "#ff00d7", + "#ff00ff", + "#ff5f00", + "#ff5f5f", + "#ff5f87", + "#ff5faf", + "#ff5fd7", + "#ff5fff", + "#ff8700", + "#ff875f", + "#ff8787", + "#ff87af", + "#ff87d7", + "#ff87ff", + "#ffaf00", + "#ffaf5f", + "#ffaf87", + "#ffafaf", + "#ffafd7", + "#ffafff", + "#ffd700", + "#ffd75f", + "#ffd787", + "#ffd7af", + "#ffd7d7", + "#ffd7ff", + "#ffff00", + "#ffff5f", + "#ffff87", + "#ffffaf", + "#ffffd7", + "#ffffff", + "#080808", + "#121212", + "#1c1c1c", + "#262626", + "#303030", + "#3a3a3a", + "#444444", + "#4e4e4e", + "#585858", + "#626262", + "#6c6c6c", + "#767676", + "#808080", + "#8a8a8a", + "#949494", + "#9e9e9e", + "#a8a8a8", + "#b2b2b2", + "#bcbcbc", + "#c6c6c6", + "#d0d0d0", + "#dadada", + "#e4e4e4", + "#eeeeee", +} diff --git a/vendor/github.com/charmbracelet/colorprofile/writer.go b/vendor/github.com/charmbracelet/colorprofile/writer.go new file mode 100644 index 00000000..d04b3b99 --- /dev/null +++ b/vendor/github.com/charmbracelet/colorprofile/writer.go @@ -0,0 +1,166 @@ +package colorprofile + +import ( + "bytes" + "image/color" + "io" + "strconv" + + "github.com/charmbracelet/x/ansi" +) + +// NewWriter creates a new color profile writer that downgrades color sequences +// based on the detected color profile. +// +// If environ is nil, it will use os.Environ() to get the environment variables. +// +// It queries the given writer to determine if it supports ANSI escape codes. +// If it does, along with the given environment variables, it will determine +// the appropriate color profile to use for color formatting. +// +// This respects the NO_COLOR, CLICOLOR, and CLICOLOR_FORCE environment variables. +func NewWriter(w io.Writer, environ []string) *Writer { + return &Writer{ + Forward: w, + Profile: Detect(w, environ), + } +} + +// Writer represents a color profile writer that writes ANSI sequences to the +// underlying writer. +type Writer struct { + Forward io.Writer + Profile Profile +} + +// Write writes the given text to the underlying writer. +func (w *Writer) Write(p []byte) (int, error) { + switch w.Profile { + case TrueColor: + return w.Forward.Write(p) + case NoTTY: + return io.WriteString(w.Forward, ansi.Strip(string(p))) + default: + return w.downsample(p) + } +} + +// downsample downgrades the given text to the appropriate color profile. +func (w *Writer) downsample(p []byte) (int, error) { + var buf bytes.Buffer + var state byte + + parser := ansi.GetParser() + defer ansi.PutParser(parser) + + for len(p) > 0 { + parser.Reset() + seq, _, read, newState := ansi.DecodeSequence(p, state, parser) + + switch { + case ansi.HasCsiPrefix(seq) && parser.Command() == 'm': + handleSgr(w, parser, &buf) + default: + // If we're not a style SGR sequence, just write the bytes. + if n, err := buf.Write(seq); err != nil { + return n, err + } + } + + p = p[read:] + state = newState + } + + return w.Forward.Write(buf.Bytes()) +} + +// WriteString writes the given text to the underlying writer. +func (w *Writer) WriteString(s string) (n int, err error) { + return w.Write([]byte(s)) +} + +func handleSgr(w *Writer, p *ansi.Parser, buf *bytes.Buffer) { + var style ansi.Style + params := p.Params() + for i := 0; i < len(params); i++ { + param := params[i] + + switch param := param.Param(0); param { + case 0: + // SGR default parameter is 0. We use an empty string to reduce the + // number of bytes written to the buffer. + style = append(style, "") + case 30, 31, 32, 33, 34, 35, 36, 37: // 8-bit foreground color + if w.Profile < ANSI { + continue + } + style = style.ForegroundColor( + w.Profile.Convert(ansi.BasicColor(param - 30))) //nolint:gosec + case 38: // 16 or 24-bit foreground color + var c color.Color + if n := ansi.ReadStyleColor(params[i:], &c); n > 0 { + i += n - 1 + } + if w.Profile < ANSI { + continue + } + style = style.ForegroundColor(w.Profile.Convert(c)) + case 39: // default foreground color + if w.Profile < ANSI { + continue + } + style = style.DefaultForegroundColor() + case 40, 41, 42, 43, 44, 45, 46, 47: // 8-bit background color + if w.Profile < ANSI { + continue + } + style = style.BackgroundColor( + w.Profile.Convert(ansi.BasicColor(param - 40))) //nolint:gosec + case 48: // 16 or 24-bit background color + var c color.Color + if n := ansi.ReadStyleColor(params[i:], &c); n > 0 { + i += n - 1 + } + if w.Profile < ANSI { + continue + } + style = style.BackgroundColor(w.Profile.Convert(c)) + case 49: // default background color + if w.Profile < ANSI { + continue + } + style = style.DefaultBackgroundColor() + case 58: // 16 or 24-bit underline color + var c color.Color + if n := ansi.ReadStyleColor(params[i:], &c); n > 0 { + i += n - 1 + } + if w.Profile < ANSI { + continue + } + style = style.UnderlineColor(w.Profile.Convert(c)) + case 59: // default underline color + if w.Profile < ANSI { + continue + } + style = style.DefaultUnderlineColor() + case 90, 91, 92, 93, 94, 95, 96, 97: // 8-bit bright foreground color + if w.Profile < ANSI { + continue + } + style = style.ForegroundColor( + w.Profile.Convert(ansi.BasicColor(param - 90 + 8))) //nolint:gosec + case 100, 101, 102, 103, 104, 105, 106, 107: // 8-bit bright background color + if w.Profile < ANSI { + continue + } + style = style.BackgroundColor( + w.Profile.Convert(ansi.BasicColor(param - 100 + 8))) //nolint:gosec + default: + // If this is not a color attribute, just append it to the style. + style = append(style, strconv.Itoa(param)) + } + } + + _, _ = buf.WriteString(style.String()) +} diff --git a/vendor/github.com/charmbracelet/lipgloss/.gitignore b/vendor/github.com/charmbracelet/lipgloss/.gitignore new file mode 100644 index 00000000..db482015 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/.gitignore @@ -0,0 +1,2 @@ +ssh_example_ed25519* +dist/ diff --git a/vendor/github.com/charmbracelet/lipgloss/.golangci.yml b/vendor/github.com/charmbracelet/lipgloss/.golangci.yml new file mode 100644 index 00000000..90c5c08b --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/.golangci.yml @@ -0,0 +1,41 @@ +run: + tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - bodyclose + - exhaustive + - goconst + - godot + - godox + - gofumpt + - goimports + - gomoddirectives + - goprintffuncname + - gosec + - misspell + - nakedret + - nestif + - nilerr + - noctx + - nolintlint + - prealloc + - revive + - rowserrcheck + - sqlclosecheck + - tparallel + - unconvert + - unparam + - whitespace + - wrapcheck diff --git a/vendor/github.com/charmbracelet/lipgloss/.goreleaser.yml b/vendor/github.com/charmbracelet/lipgloss/.goreleaser.yml new file mode 100644 index 00000000..3353d020 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/.goreleaser.yml @@ -0,0 +1,5 @@ +# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json +version: 2 +includes: + - from_url: + url: charmbracelet/meta/main/goreleaser-lib.yaml diff --git a/vendor/github.com/charmbracelet/lipgloss/LICENSE b/vendor/github.com/charmbracelet/lipgloss/LICENSE new file mode 100644 index 00000000..6f5b1fa6 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021-2023 Charmbracelet, Inc + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/charmbracelet/lipgloss/README.md b/vendor/github.com/charmbracelet/lipgloss/README.md new file mode 100644 index 00000000..cee2371c --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/README.md @@ -0,0 +1,815 @@ +# Lip Gloss + +

+ Lip Gloss title treatment
+ Latest Release + GoDoc + Build Status + phorm.ai +

+ +Style definitions for nice terminal layouts. Built with TUIs in mind. + +![Lip Gloss example](https://github.com/user-attachments/assets/7950b1c1-e0e3-427e-8e7d-6f7f6ad17ca7) + +Lip Gloss takes an expressive, declarative approach to terminal rendering. +Users familiar with CSS will feel at home with Lip Gloss. + +```go + +import "github.com/charmbracelet/lipgloss" + +var style = lipgloss.NewStyle(). + Bold(true). + Foreground(lipgloss.Color("#FAFAFA")). + Background(lipgloss.Color("#7D56F4")). + PaddingTop(2). + PaddingLeft(4). + Width(22) + +fmt.Println(style.Render("Hello, kitty")) +``` + +## Colors + +Lip Gloss supports the following color profiles: + +### ANSI 16 colors (4-bit) + +```go +lipgloss.Color("5") // magenta +lipgloss.Color("9") // red +lipgloss.Color("12") // light blue +``` + +### ANSI 256 Colors (8-bit) + +```go +lipgloss.Color("86") // aqua +lipgloss.Color("201") // hot pink +lipgloss.Color("202") // orange +``` + +### True Color (16,777,216 colors; 24-bit) + +```go +lipgloss.Color("#0000FF") // good ol' 100% blue +lipgloss.Color("#04B575") // a green +lipgloss.Color("#3C3C3C") // a dark gray +``` + +...as well as a 1-bit ASCII profile, which is black and white only. + +The terminal's color profile will be automatically detected, and colors outside +the gamut of the current palette will be automatically coerced to their closest +available value. + +### Adaptive Colors + +You can also specify color options for light and dark backgrounds: + +```go +lipgloss.AdaptiveColor{Light: "236", Dark: "248"} +``` + +The terminal's background color will automatically be detected and the +appropriate color will be chosen at runtime. + +### Complete Colors + +CompleteColor specifies exact values for True Color, ANSI256, and ANSI color +profiles. + +```go +lipgloss.CompleteColor{TrueColor: "#0000FF", ANSI256: "86", ANSI: "5"} +``` + +Automatic color degradation will not be performed in this case and it will be +based on the color specified. + +### Complete Adaptive Colors + +You can use `CompleteColor` with `AdaptiveColor` to specify the exact values for +light and dark backgrounds without automatic color degradation. + +```go +lipgloss.CompleteAdaptiveColor{ + Light: CompleteColor{TrueColor: "#d7ffae", ANSI256: "193", ANSI: "11"}, + Dark: CompleteColor{TrueColor: "#d75fee", ANSI256: "163", ANSI: "5"}, +} +``` + +## Inline Formatting + +Lip Gloss supports the usual ANSI text formatting options: + +```go +var style = lipgloss.NewStyle(). + Bold(true). + Italic(true). + Faint(true). + Blink(true). + Strikethrough(true). + Underline(true). + Reverse(true) +``` + +## Block-Level Formatting + +Lip Gloss also supports rules for block-level formatting: + +```go +// Padding +var style = lipgloss.NewStyle(). + PaddingTop(2). + PaddingRight(4). + PaddingBottom(2). + PaddingLeft(4) + +// Margins +var style = lipgloss.NewStyle(). + MarginTop(2). + MarginRight(4). + MarginBottom(2). + MarginLeft(4) +``` + +There is also shorthand syntax for margins and padding, which follows the same +format as CSS: + +```go +// 2 cells on all sides +lipgloss.NewStyle().Padding(2) + +// 2 cells on the top and bottom, 4 cells on the left and right +lipgloss.NewStyle().Margin(2, 4) + +// 1 cell on the top, 4 cells on the sides, 2 cells on the bottom +lipgloss.NewStyle().Padding(1, 4, 2) + +// Clockwise, starting from the top: 2 cells on the top, 4 on the right, 3 on +// the bottom, and 1 on the left +lipgloss.NewStyle().Margin(2, 4, 3, 1) +``` + +## Aligning Text + +You can align paragraphs of text to the left, right, or center. + +```go +var style = lipgloss.NewStyle(). + Width(24). + Align(lipgloss.Left). // align it left + Align(lipgloss.Right). // no wait, align it right + Align(lipgloss.Center) // just kidding, align it in the center +``` + +## Width and Height + +Setting a minimum width and height is simple and straightforward. + +```go +var style = lipgloss.NewStyle(). + SetString("What’s for lunch?"). + Width(24). + Height(32). + Foreground(lipgloss.Color("63")) +``` + +## Borders + +Adding borders is easy: + +```go +// Add a purple, rectangular border +var style = lipgloss.NewStyle(). + BorderStyle(lipgloss.NormalBorder()). + BorderForeground(lipgloss.Color("63")) + +// Set a rounded, yellow-on-purple border to the top and left +var anotherStyle = lipgloss.NewStyle(). + BorderStyle(lipgloss.RoundedBorder()). + BorderForeground(lipgloss.Color("228")). + BorderBackground(lipgloss.Color("63")). + BorderTop(true). + BorderLeft(true) + +// Make your own border +var myCuteBorder = lipgloss.Border{ + Top: "._.:*:", + Bottom: "._.:*:", + Left: "|*", + Right: "|*", + TopLeft: "*", + TopRight: "*", + BottomLeft: "*", + BottomRight: "*", +} +``` + +There are also shorthand functions for defining borders, which follow a similar +pattern to the margin and padding shorthand functions. + +```go +// Add a thick border to the top and bottom +lipgloss.NewStyle(). + Border(lipgloss.ThickBorder(), true, false) + +// Add a double border to the top and left sides. Rules are set clockwise +// from top. +lipgloss.NewStyle(). + Border(lipgloss.DoubleBorder(), true, false, false, true) +``` + +For more on borders see [the docs][docs]. + +## Copying Styles + +Just use assignment: + +```go +style := lipgloss.NewStyle().Foreground(lipgloss.Color("219")) + +copiedStyle := style // this is a true copy + +wildStyle := style.Blink(true) // this is also true copy, with blink added + +``` + +Since `Style` data structures contains only primitive types, assigning a style +to another effectively creates a new copy of the style without mutating the +original. + +## Inheritance + +Styles can inherit rules from other styles. When inheriting, only unset rules +on the receiver are inherited. + +```go +var styleA = lipgloss.NewStyle(). + Foreground(lipgloss.Color("229")). + Background(lipgloss.Color("63")) + +// Only the background color will be inherited here, because the foreground +// color will have been already set: +var styleB = lipgloss.NewStyle(). + Foreground(lipgloss.Color("201")). + Inherit(styleA) +``` + +## Unsetting Rules + +All rules can be unset: + +```go +var style = lipgloss.NewStyle(). + Bold(true). // make it bold + UnsetBold(). // jk don't make it bold + Background(lipgloss.Color("227")). // yellow background + UnsetBackground() // never mind +``` + +When a rule is unset, it won't be inherited or copied. + +## Enforcing Rules + +Sometimes, such as when developing a component, you want to make sure style +definitions respect their intended purpose in the UI. This is where `Inline` +and `MaxWidth`, and `MaxHeight` come in: + +```go +// Force rendering onto a single line, ignoring margins, padding, and borders. +someStyle.Inline(true).Render("yadda yadda") + +// Also limit rendering to five cells +someStyle.Inline(true).MaxWidth(5).Render("yadda yadda") + +// Limit rendering to a 5x5 cell block +someStyle.MaxWidth(5).MaxHeight(5).Render("yadda yadda") +``` + +## Tabs + +The tab character (`\t`) is rendered differently in different terminals (often +as 8 spaces, sometimes 4). Because of this inconsistency, Lip Gloss converts +tabs to 4 spaces at render time. This behavior can be changed on a per-style +basis, however: + +```go +style := lipgloss.NewStyle() // tabs will render as 4 spaces, the default +style = style.TabWidth(2) // render tabs as 2 spaces +style = style.TabWidth(0) // remove tabs entirely +style = style.TabWidth(lipgloss.NoTabConversion) // leave tabs intact +``` + +## Rendering + +Generally, you just call the `Render(string...)` method on a `lipgloss.Style`: + +```go +style := lipgloss.NewStyle().Bold(true).SetString("Hello,") +fmt.Println(style.Render("kitty.")) // Hello, kitty. +fmt.Println(style.Render("puppy.")) // Hello, puppy. +``` + +But you could also use the Stringer interface: + +```go +var style = lipgloss.NewStyle().SetString("你好,猫咪。").Bold(true) +fmt.Println(style) // 你好,猫咪。 +``` + +### Custom Renderers + +Custom renderers allow you to render to a specific outputs. This is +particularly important when you want to render to different outputs and +correctly detect the color profile and dark background status for each, such as +in a server-client situation. + +```go +func myLittleHandler(sess ssh.Session) { + // Create a renderer for the client. + renderer := lipgloss.NewRenderer(sess) + + // Create a new style on the renderer. + style := renderer.NewStyle().Background(lipgloss.AdaptiveColor{Light: "63", Dark: "228"}) + + // Render. The color profile and dark background state will be correctly detected. + io.WriteString(sess, style.Render("Heyyyyyyy")) +} +``` + +For an example on using a custom renderer over SSH with [Wish][wish] see the +[SSH example][ssh-example]. + +## Utilities + +In addition to pure styling, Lip Gloss also ships with some utilities to help +assemble your layouts. + +### Joining Paragraphs + +Horizontally and vertically joining paragraphs is a cinch. + +```go +// Horizontally join three paragraphs along their bottom edges +lipgloss.JoinHorizontal(lipgloss.Bottom, paragraphA, paragraphB, paragraphC) + +// Vertically join two paragraphs along their center axes +lipgloss.JoinVertical(lipgloss.Center, paragraphA, paragraphB) + +// Horizontally join three paragraphs, with the shorter ones aligning 20% +// from the top of the tallest +lipgloss.JoinHorizontal(0.2, paragraphA, paragraphB, paragraphC) +``` + +### Measuring Width and Height + +Sometimes you’ll want to know the width and height of text blocks when building +your layouts. + +```go +// Render a block of text. +var style = lipgloss.NewStyle(). + Width(40). + Padding(2) +var block string = style.Render(someLongString) + +// Get the actual, physical dimensions of the text block. +width := lipgloss.Width(block) +height := lipgloss.Height(block) + +// Here's a shorthand function. +w, h := lipgloss.Size(block) +``` + +### Placing Text in Whitespace + +Sometimes you’ll simply want to place a block of text in whitespace. + +```go +// Center a paragraph horizontally in a space 80 cells wide. The height of +// the block returned will be as tall as the input paragraph. +block := lipgloss.PlaceHorizontal(80, lipgloss.Center, fancyStyledParagraph) + +// Place a paragraph at the bottom of a space 30 cells tall. The width of +// the text block returned will be as wide as the input paragraph. +block := lipgloss.PlaceVertical(30, lipgloss.Bottom, fancyStyledParagraph) + +// Place a paragraph in the bottom right corner of a 30x80 cell space. +block := lipgloss.Place(30, 80, lipgloss.Right, lipgloss.Bottom, fancyStyledParagraph) +``` + +You can also style the whitespace. For details, see [the docs][docs]. + +## Rendering Tables + +Lip Gloss ships with a table rendering sub-package. + +```go +import "github.com/charmbracelet/lipgloss/table" +``` + +Define some rows of data. + +```go +rows := [][]string{ + {"Chinese", "您好", "你好"}, + {"Japanese", "こんにちは", "やあ"}, + {"Arabic", "أهلين", "أهلا"}, + {"Russian", "Здравствуйте", "Привет"}, + {"Spanish", "Hola", "¿Qué tal?"}, +} +``` + +Use the table package to style and render the table. + +```go +var ( + purple = lipgloss.Color("99") + gray = lipgloss.Color("245") + lightGray = lipgloss.Color("241") + + headerStyle = lipgloss.NewStyle().Foreground(purple).Bold(true).Align(lipgloss.Center) + cellStyle = lipgloss.NewStyle().Padding(0, 1).Width(14) + oddRowStyle = cellStyle.Foreground(gray) + evenRowStyle = cellStyle.Foreground(lightGray) +) + +t := table.New(). + Border(lipgloss.NormalBorder()). + BorderStyle(lipgloss.NewStyle().Foreground(purple)). + StyleFunc(func(row, col int) lipgloss.Style { + switch { + case row == table.HeaderRow: + return headerStyle + case row%2 == 0: + return evenRowStyle + default: + return oddRowStyle + } + }). + Headers("LANGUAGE", "FORMAL", "INFORMAL"). + Rows(rows...) + +// You can also add tables row-by-row +t.Row("English", "You look absolutely fabulous.", "How's it going?") +``` + +Print the table. + +```go +fmt.Println(t) +``` + +![Table Example](https://github.com/charmbracelet/lipgloss/assets/42545625/6e4b70c4-f494-45da-a467-bdd27df30d5d) + +> [!WARNING] +> Table `Rows` need to be declared before `Offset` otherwise it does nothing. + +### Table Borders + +There are helpers to generate tables in markdown or ASCII style: + +#### Markdown Table + +```go +table.New().Border(lipgloss.MarkdownBorder()).BorderTop(false).BorderBottom(false) +``` + +``` +| LANGUAGE | FORMAL | INFORMAL | +|----------|--------------|-----------| +| Chinese | Nǐn hǎo | Nǐ hǎo | +| French | Bonjour | Salut | +| Russian | Zdravstvuyte | Privet | +| Spanish | Hola | ¿Qué tal? | +``` + +#### ASCII Table + +```go +table.New().Border(lipgloss.ASCIIBorder()) +``` + +``` ++----------+--------------+-----------+ +| LANGUAGE | FORMAL | INFORMAL | ++----------+--------------+-----------+ +| Chinese | Nǐn hǎo | Nǐ hǎo | +| French | Bonjour | Salut | +| Russian | Zdravstvuyte | Privet | +| Spanish | Hola | ¿Qué tal? | ++----------+--------------+-----------+ +``` + +For more on tables see [the docs](https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc) and [examples](https://github.com/charmbracelet/lipgloss/tree/master/examples/table). + +## Rendering Lists + +Lip Gloss ships with a list rendering sub-package. + +```go +import "github.com/charmbracelet/lipgloss/list" +``` + +Define a new list. + +```go +l := list.New("A", "B", "C") +``` + +Print the list. + +```go +fmt.Println(l) + +// • A +// • B +// • C +``` + +Lists have the ability to nest. + +```go +l := list.New( + "A", list.New("Artichoke"), + "B", list.New("Baking Flour", "Bananas", "Barley", "Bean Sprouts"), + "C", list.New("Cashew Apple", "Cashews", "Coconut Milk", "Curry Paste", "Currywurst"), + "D", list.New("Dill", "Dragonfruit", "Dried Shrimp"), + "E", list.New("Eggs"), + "F", list.New("Fish Cake", "Furikake"), + "J", list.New("Jicama"), + "K", list.New("Kohlrabi"), + "L", list.New("Leeks", "Lentils", "Licorice Root"), +) +``` + +Print the list. + +```go +fmt.Println(l) +``` + +

+image +

+ +Lists can be customized via their enumeration function as well as using +`lipgloss.Style`s. + +```go +enumeratorStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("99")).MarginRight(1) +itemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("212")).MarginRight(1) + +l := list.New( + "Glossier", + "Claire’s Boutique", + "Nyx", + "Mac", + "Milk", + ). + Enumerator(list.Roman). + EnumeratorStyle(enumeratorStyle). + ItemStyle(itemStyle) +``` + +Print the list. + +

+List example +

+ +In addition to the predefined enumerators (`Arabic`, `Alphabet`, `Roman`, `Bullet`, `Tree`), +you may also define your own custom enumerator: + +```go +l := list.New("Duck", "Duck", "Duck", "Duck", "Goose", "Duck", "Duck") + +func DuckDuckGooseEnumerator(l list.Items, i int) string { + if l.At(i).Value() == "Goose" { + return "Honk →" + } + return "" +} + +l = l.Enumerator(DuckDuckGooseEnumerator) +``` + +Print the list: + +

+image +

+ +If you need, you can also build lists incrementally: + +```go +l := list.New() + +for i := 0; i < repeat; i++ { + l.Item("Lip Gloss") +} +``` + +## Rendering Trees + +Lip Gloss ships with a tree rendering sub-package. + +```go +import "github.com/charmbracelet/lipgloss/tree" +``` + +Define a new tree. + +```go +t := tree.Root("."). + Child("A", "B", "C") +``` + +Print the tree. + +```go +fmt.Println(t) + +// . +// ├── A +// ├── B +// └── C +``` + +Trees have the ability to nest. + +```go +t := tree.Root("."). + Child("macOS"). + Child( + tree.New(). + Root("Linux"). + Child("NixOS"). + Child("Arch Linux (btw)"). + Child("Void Linux"), + ). + Child( + tree.New(). + Root("BSD"). + Child("FreeBSD"). + Child("OpenBSD"), + ) +``` + +Print the tree. + +```go +fmt.Println(t) +``` + +

+Tree Example (simple) +

+ +Trees can be customized via their enumeration function as well as using +`lipgloss.Style`s. + +```go +enumeratorStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("63")).MarginRight(1) +rootStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("35")) +itemStyle := lipgloss.NewStyle().Foreground(lipgloss.Color("212")) + +t := tree. + Root("⁜ Makeup"). + Child( + "Glossier", + "Fenty Beauty", + tree.New().Child( + "Gloss Bomb Universal Lip Luminizer", + "Hot Cheeks Velour Blushlighter", + ), + "Nyx", + "Mac", + "Milk", + ). + Enumerator(tree.RoundedEnumerator). + EnumeratorStyle(enumeratorStyle). + RootStyle(rootStyle). + ItemStyle(itemStyle) +``` + +Print the tree. + +

+Tree Example (makeup) +

+ +The predefined enumerators for trees are `DefaultEnumerator` and `RoundedEnumerator`. + +If you need, you can also build trees incrementally: + +```go +t := tree.New() + +for i := 0; i < repeat; i++ { + t.Child("Lip Gloss") +} +``` + +--- + +## FAQ + +
+ +Why are things misaligning? Why are borders at the wrong widths? + +

This is most likely due to your locale and encoding, particularly with +regard to Chinese, Japanese, and Korean (for example, zh_CN.UTF-8 +or ja_JP.UTF-8). The most direct way to fix this is to set +RUNEWIDTH_EASTASIAN=0 in your environment.

+ +

For details see https://github.com/charmbracelet/lipgloss/issues/40.

+
+ +
+ +Why isn't Lip Gloss displaying colors? + +

Lip Gloss automatically degrades colors to the best available option in the +given terminal, and if output's not a TTY it will remove color output entirely. +This is common when running tests, CI, or when piping output elsewhere.

+ +

If necessary, you can force a color profile in your tests with +SetColorProfile.

+ +```go +import ( + "github.com/charmbracelet/lipgloss" + "github.com/muesli/termenv" +) + +lipgloss.SetColorProfile(termenv.TrueColor) +``` + +_Note:_ this option limits the flexibility of your application and can cause +ANSI escape codes to be output in cases where that might not be desired. Take +careful note of your use case and environment before choosing to force a color +profile. + +
+ +## What about [Bubble Tea][tea]? + +Lip Gloss doesn’t replace Bubble Tea. Rather, it is an excellent Bubble Tea +companion. It was designed to make assembling terminal user interface views as +simple and fun as possible so that you can focus on building your application +instead of concerning yourself with low-level layout details. + +In simple terms, you can use Lip Gloss to help build your Bubble Tea views. + +[tea]: https://github.com/charmbracelet/tea + +## Under the Hood + +Lip Gloss is built on the excellent [Termenv][termenv] and [Reflow][reflow] +libraries which deal with color and ANSI-aware text operations, respectively. +For many use cases Termenv and Reflow will be sufficient for your needs. + +[termenv]: https://github.com/muesli/termenv +[reflow]: https://github.com/muesli/reflow + +## Rendering Markdown + +For a more document-centric rendering solution with support for things like +lists, tables, and syntax-highlighted code have a look at [Glamour][glamour], +the stylesheet-based Markdown renderer. + +[glamour]: https://github.com/charmbracelet/glamour + +## Contributing + +See [contributing][contribute]. + +[contribute]: https://github.com/charmbracelet/lipgloss/contribute + +## Feedback + +We’d love to hear your thoughts on this project. Feel free to drop us a note! + +- [Twitter](https://twitter.com/charmcli) +- [The Fediverse](https://mastodon.social/@charmcli) +- [Discord](https://charm.sh/chat) + +## License + +[MIT](https://github.com/charmbracelet/lipgloss/raw/master/LICENSE) + +--- + +Part of [Charm](https://charm.sh). + +The Charm logo + +Charm热爱开源 • Charm loves open source + +[docs]: https://pkg.go.dev/github.com/charmbracelet/lipgloss?tab=doc +[wish]: https://github.com/charmbracelet/wish +[ssh-example]: examples/ssh diff --git a/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml b/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml new file mode 100644 index 00000000..0b4a7711 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/Taskfile.yaml @@ -0,0 +1,19 @@ +# https://taskfile.dev + +version: '3' + +tasks: + lint: + desc: Run base linters + cmds: + - golangci-lint run + + test: + desc: Run tests + cmds: + - go test ./... {{.CLI_ARGS}} + + test:table: + desc: Run table tests + cmds: + - go test ./table {{.CLI_ARGS}} diff --git a/vendor/github.com/charmbracelet/lipgloss/align.go b/vendor/github.com/charmbracelet/lipgloss/align.go new file mode 100644 index 00000000..ce654b23 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/align.go @@ -0,0 +1,83 @@ +package lipgloss + +import ( + "strings" + + "github.com/charmbracelet/x/ansi" + "github.com/muesli/termenv" +) + +// Perform text alignment. If the string is multi-lined, we also make all lines +// the same width by padding them with spaces. If a termenv style is passed, +// use that to style the spaces added. +func alignTextHorizontal(str string, pos Position, width int, style *termenv.Style) string { + lines, widestLine := getLines(str) + var b strings.Builder + + for i, l := range lines { + lineWidth := ansi.StringWidth(l) + + shortAmount := widestLine - lineWidth // difference from the widest line + shortAmount += max(0, width-(shortAmount+lineWidth)) // difference from the total width, if set + + if shortAmount > 0 { + switch pos { //nolint:exhaustive + case Right: + s := strings.Repeat(" ", shortAmount) + if style != nil { + s = style.Styled(s) + } + l = s + l + case Center: + // Note: remainder goes on the right. + left := shortAmount / 2 //nolint:mnd + right := left + shortAmount%2 //nolint:mnd + + leftSpaces := strings.Repeat(" ", left) + rightSpaces := strings.Repeat(" ", right) + + if style != nil { + leftSpaces = style.Styled(leftSpaces) + rightSpaces = style.Styled(rightSpaces) + } + l = leftSpaces + l + rightSpaces + default: // Left + s := strings.Repeat(" ", shortAmount) + if style != nil { + s = style.Styled(s) + } + l += s + } + } + + b.WriteString(l) + if i < len(lines)-1 { + b.WriteRune('\n') + } + } + + return b.String() +} + +func alignTextVertical(str string, pos Position, height int, _ *termenv.Style) string { + strHeight := strings.Count(str, "\n") + 1 + if height < strHeight { + return str + } + + switch pos { + case Top: + return str + strings.Repeat("\n", height-strHeight) + case Center: + topPadding, bottomPadding := (height-strHeight)/2, (height-strHeight)/2 //nolint:mnd + if strHeight+topPadding+bottomPadding > height { + topPadding-- + } else if strHeight+topPadding+bottomPadding < height { + bottomPadding++ + } + return strings.Repeat("\n", topPadding) + str + strings.Repeat("\n", bottomPadding) + case Bottom: + return strings.Repeat("\n", height-strHeight) + str + } + return str +} diff --git a/vendor/github.com/charmbracelet/lipgloss/ansi_unix.go b/vendor/github.com/charmbracelet/lipgloss/ansi_unix.go new file mode 100644 index 00000000..d416b8c9 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/ansi_unix.go @@ -0,0 +1,7 @@ +//go:build !windows +// +build !windows + +package lipgloss + +// enableLegacyWindowsANSI is only needed on Windows. +func enableLegacyWindowsANSI() {} diff --git a/vendor/github.com/charmbracelet/lipgloss/ansi_windows.go b/vendor/github.com/charmbracelet/lipgloss/ansi_windows.go new file mode 100644 index 00000000..0cf56e4c --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/ansi_windows.go @@ -0,0 +1,22 @@ +//go:build windows +// +build windows + +package lipgloss + +import ( + "sync" + + "github.com/muesli/termenv" +) + +var enableANSI sync.Once + +// enableANSIColors enables support for ANSI color sequences in the Windows +// default console (cmd.exe and the PowerShell application). Note that this +// only works with Windows 10. Also note that Windows Terminal supports colors +// by default. +func enableLegacyWindowsANSI() { + enableANSI.Do(func() { + _, _ = termenv.EnableWindowsANSIConsole() + }) +} diff --git a/vendor/github.com/charmbracelet/lipgloss/borders.go b/vendor/github.com/charmbracelet/lipgloss/borders.go new file mode 100644 index 00000000..b36f8743 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/borders.go @@ -0,0 +1,490 @@ +package lipgloss + +import ( + "strings" + + "github.com/charmbracelet/x/ansi" + "github.com/muesli/termenv" + "github.com/rivo/uniseg" +) + +// Border contains a series of values which comprise the various parts of a +// border. +type Border struct { + Top string + Bottom string + Left string + Right string + TopLeft string + TopRight string + BottomLeft string + BottomRight string + MiddleLeft string + MiddleRight string + Middle string + MiddleTop string + MiddleBottom string +} + +// GetTopSize returns the width of the top border. If borders contain runes of +// varying widths, the widest rune is returned. If no border exists on the top +// edge, 0 is returned. +func (b Border) GetTopSize() int { + return getBorderEdgeWidth(b.TopLeft, b.Top, b.TopRight) +} + +// GetRightSize returns the width of the right border. If borders contain +// runes of varying widths, the widest rune is returned. If no border exists on +// the right edge, 0 is returned. +func (b Border) GetRightSize() int { + return getBorderEdgeWidth(b.TopRight, b.Right, b.BottomRight) +} + +// GetBottomSize returns the width of the bottom border. If borders contain +// runes of varying widths, the widest rune is returned. If no border exists on +// the bottom edge, 0 is returned. +func (b Border) GetBottomSize() int { + return getBorderEdgeWidth(b.BottomLeft, b.Bottom, b.BottomRight) +} + +// GetLeftSize returns the width of the left border. If borders contain runes +// of varying widths, the widest rune is returned. If no border exists on the +// left edge, 0 is returned. +func (b Border) GetLeftSize() int { + return getBorderEdgeWidth(b.TopLeft, b.Left, b.BottomLeft) +} + +func getBorderEdgeWidth(borderParts ...string) (maxWidth int) { + for _, piece := range borderParts { + w := maxRuneWidth(piece) + if w > maxWidth { + maxWidth = w + } + } + return maxWidth +} + +var ( + noBorder = Border{} + + normalBorder = Border{ + Top: "─", + Bottom: "─", + Left: "│", + Right: "│", + TopLeft: "┌", + TopRight: "┐", + BottomLeft: "└", + BottomRight: "┘", + MiddleLeft: "├", + MiddleRight: "┤", + Middle: "┼", + MiddleTop: "┬", + MiddleBottom: "┴", + } + + roundedBorder = Border{ + Top: "─", + Bottom: "─", + Left: "│", + Right: "│", + TopLeft: "╭", + TopRight: "╮", + BottomLeft: "╰", + BottomRight: "╯", + MiddleLeft: "├", + MiddleRight: "┤", + Middle: "┼", + MiddleTop: "┬", + MiddleBottom: "┴", + } + + blockBorder = Border{ + Top: "█", + Bottom: "█", + Left: "█", + Right: "█", + TopLeft: "█", + TopRight: "█", + BottomLeft: "█", + BottomRight: "█", + MiddleLeft: "█", + MiddleRight: "█", + Middle: "█", + MiddleTop: "█", + MiddleBottom: "█", + } + + outerHalfBlockBorder = Border{ + Top: "▀", + Bottom: "▄", + Left: "▌", + Right: "▐", + TopLeft: "▛", + TopRight: "▜", + BottomLeft: "▙", + BottomRight: "▟", + } + + innerHalfBlockBorder = Border{ + Top: "▄", + Bottom: "▀", + Left: "▐", + Right: "▌", + TopLeft: "▗", + TopRight: "▖", + BottomLeft: "▝", + BottomRight: "▘", + } + + thickBorder = Border{ + Top: "━", + Bottom: "━", + Left: "┃", + Right: "┃", + TopLeft: "┏", + TopRight: "┓", + BottomLeft: "┗", + BottomRight: "┛", + MiddleLeft: "┣", + MiddleRight: "┫", + Middle: "╋", + MiddleTop: "┳", + MiddleBottom: "┻", + } + + doubleBorder = Border{ + Top: "═", + Bottom: "═", + Left: "║", + Right: "║", + TopLeft: "╔", + TopRight: "╗", + BottomLeft: "╚", + BottomRight: "╝", + MiddleLeft: "╠", + MiddleRight: "╣", + Middle: "╬", + MiddleTop: "╦", + MiddleBottom: "╩", + } + + hiddenBorder = Border{ + Top: " ", + Bottom: " ", + Left: " ", + Right: " ", + TopLeft: " ", + TopRight: " ", + BottomLeft: " ", + BottomRight: " ", + MiddleLeft: " ", + MiddleRight: " ", + Middle: " ", + MiddleTop: " ", + MiddleBottom: " ", + } + + markdownBorder = Border{ + Top: "-", + Bottom: "-", + Left: "|", + Right: "|", + TopLeft: "|", + TopRight: "|", + BottomLeft: "|", + BottomRight: "|", + MiddleLeft: "|", + MiddleRight: "|", + Middle: "|", + MiddleTop: "|", + MiddleBottom: "|", + } + + asciiBorder = Border{ + Top: "-", + Bottom: "-", + Left: "|", + Right: "|", + TopLeft: "+", + TopRight: "+", + BottomLeft: "+", + BottomRight: "+", + MiddleLeft: "+", + MiddleRight: "+", + Middle: "+", + MiddleTop: "+", + MiddleBottom: "+", + } +) + +// NormalBorder returns a standard-type border with a normal weight and 90 +// degree corners. +func NormalBorder() Border { + return normalBorder +} + +// RoundedBorder returns a border with rounded corners. +func RoundedBorder() Border { + return roundedBorder +} + +// BlockBorder returns a border that takes the whole block. +func BlockBorder() Border { + return blockBorder +} + +// OuterHalfBlockBorder returns a half-block border that sits outside the frame. +func OuterHalfBlockBorder() Border { + return outerHalfBlockBorder +} + +// InnerHalfBlockBorder returns a half-block border that sits inside the frame. +func InnerHalfBlockBorder() Border { + return innerHalfBlockBorder +} + +// ThickBorder returns a border that's thicker than the one returned by +// NormalBorder. +func ThickBorder() Border { + return thickBorder +} + +// DoubleBorder returns a border comprised of two thin strokes. +func DoubleBorder() Border { + return doubleBorder +} + +// HiddenBorder returns a border that renders as a series of single-cell +// spaces. It's useful for cases when you want to remove a standard border but +// maintain layout positioning. This said, you can still apply a background +// color to a hidden border. +func HiddenBorder() Border { + return hiddenBorder +} + +// MarkdownBorder return a table border in markdown style. +// +// Make sure to disable top and bottom border for the best result. This will +// ensure that the output is valid markdown. +// +// table.New().Border(lipgloss.MarkdownBorder()).BorderTop(false).BorderBottom(false) +func MarkdownBorder() Border { + return markdownBorder +} + +// ASCIIBorder returns a table border with ASCII characters. +func ASCIIBorder() Border { + return asciiBorder +} + +func (s Style) applyBorder(str string) string { + var ( + border = s.getBorderStyle() + hasTop = s.getAsBool(borderTopKey, false) + hasRight = s.getAsBool(borderRightKey, false) + hasBottom = s.getAsBool(borderBottomKey, false) + hasLeft = s.getAsBool(borderLeftKey, false) + + topFG = s.getAsColor(borderTopForegroundKey) + rightFG = s.getAsColor(borderRightForegroundKey) + bottomFG = s.getAsColor(borderBottomForegroundKey) + leftFG = s.getAsColor(borderLeftForegroundKey) + + topBG = s.getAsColor(borderTopBackgroundKey) + rightBG = s.getAsColor(borderRightBackgroundKey) + bottomBG = s.getAsColor(borderBottomBackgroundKey) + leftBG = s.getAsColor(borderLeftBackgroundKey) + ) + + // If a border is set and no sides have been specifically turned on or off + // render borders on all sides. + if s.implicitBorders() { + hasTop = true + hasRight = true + hasBottom = true + hasLeft = true + } + + // If no border is set or all borders are been disabled, abort. + if border == noBorder || (!hasTop && !hasRight && !hasBottom && !hasLeft) { + return str + } + + lines, width := getLines(str) + + if hasLeft { + if border.Left == "" { + border.Left = " " + } + width += maxRuneWidth(border.Left) + } + + if hasRight && border.Right == "" { + border.Right = " " + } + + // If corners should be rendered but are set with the empty string, fill them + // with a single space. + if hasTop && hasLeft && border.TopLeft == "" { + border.TopLeft = " " + } + if hasTop && hasRight && border.TopRight == "" { + border.TopRight = " " + } + if hasBottom && hasLeft && border.BottomLeft == "" { + border.BottomLeft = " " + } + if hasBottom && hasRight && border.BottomRight == "" { + border.BottomRight = " " + } + + // Figure out which corners we should actually be using based on which + // sides are set to show. + if hasTop { + switch { + case !hasLeft && !hasRight: + border.TopLeft = "" + border.TopRight = "" + case !hasLeft: + border.TopLeft = "" + case !hasRight: + border.TopRight = "" + } + } + if hasBottom { + switch { + case !hasLeft && !hasRight: + border.BottomLeft = "" + border.BottomRight = "" + case !hasLeft: + border.BottomLeft = "" + case !hasRight: + border.BottomRight = "" + } + } + + // For now, limit corners to one rune. + border.TopLeft = getFirstRuneAsString(border.TopLeft) + border.TopRight = getFirstRuneAsString(border.TopRight) + border.BottomRight = getFirstRuneAsString(border.BottomRight) + border.BottomLeft = getFirstRuneAsString(border.BottomLeft) + + var out strings.Builder + + // Render top + if hasTop { + top := renderHorizontalEdge(border.TopLeft, border.Top, border.TopRight, width) + top = s.styleBorder(top, topFG, topBG) + out.WriteString(top) + out.WriteRune('\n') + } + + leftRunes := []rune(border.Left) + leftIndex := 0 + + rightRunes := []rune(border.Right) + rightIndex := 0 + + // Render sides + for i, l := range lines { + if hasLeft { + r := string(leftRunes[leftIndex]) + leftIndex++ + if leftIndex >= len(leftRunes) { + leftIndex = 0 + } + out.WriteString(s.styleBorder(r, leftFG, leftBG)) + } + out.WriteString(l) + if hasRight { + r := string(rightRunes[rightIndex]) + rightIndex++ + if rightIndex >= len(rightRunes) { + rightIndex = 0 + } + out.WriteString(s.styleBorder(r, rightFG, rightBG)) + } + if i < len(lines)-1 { + out.WriteRune('\n') + } + } + + // Render bottom + if hasBottom { + bottom := renderHorizontalEdge(border.BottomLeft, border.Bottom, border.BottomRight, width) + bottom = s.styleBorder(bottom, bottomFG, bottomBG) + out.WriteRune('\n') + out.WriteString(bottom) + } + + return out.String() +} + +// Render the horizontal (top or bottom) portion of a border. +func renderHorizontalEdge(left, middle, right string, width int) string { + if middle == "" { + middle = " " + } + + leftWidth := ansi.StringWidth(left) + rightWidth := ansi.StringWidth(right) + + runes := []rune(middle) + j := 0 + + out := strings.Builder{} + out.WriteString(left) + for i := leftWidth + rightWidth; i < width+rightWidth; { + out.WriteRune(runes[j]) + j++ + if j >= len(runes) { + j = 0 + } + i += ansi.StringWidth(string(runes[j])) + } + out.WriteString(right) + + return out.String() +} + +// Apply foreground and background styling to a border. +func (s Style) styleBorder(border string, fg, bg TerminalColor) string { + if fg == noColor && bg == noColor { + return border + } + + style := termenv.Style{} + + if fg != noColor { + style = style.Foreground(fg.color(s.r)) + } + if bg != noColor { + style = style.Background(bg.color(s.r)) + } + + return style.Styled(border) +} + +func maxRuneWidth(str string) int { + var width int + + state := -1 + for len(str) > 0 { + var w int + _, str, w, state = uniseg.FirstGraphemeClusterInString(str, state) + if w > width { + width = w + } + } + + return width +} + +func getFirstRuneAsString(str string) string { + if str == "" { + return str + } + r := []rune(str) + return string(r[0]) +} diff --git a/vendor/github.com/charmbracelet/lipgloss/color.go b/vendor/github.com/charmbracelet/lipgloss/color.go new file mode 100644 index 00000000..6caf3a3d --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/color.go @@ -0,0 +1,172 @@ +package lipgloss + +import ( + "strconv" + + "github.com/muesli/termenv" +) + +// TerminalColor is a color intended to be rendered in the terminal. +type TerminalColor interface { + color(*Renderer) termenv.Color + RGBA() (r, g, b, a uint32) +} + +var noColor = NoColor{} + +// NoColor is used to specify the absence of color styling. When this is active +// foreground colors will be rendered with the terminal's default text color, +// and background colors will not be drawn at all. +// +// Example usage: +// +// var style = someStyle.Background(lipgloss.NoColor{}) +type NoColor struct{} + +func (NoColor) color(*Renderer) termenv.Color { + return termenv.NoColor{} +} + +// RGBA returns the RGBA value of this color. Because we have to return +// something, despite this color being the absence of color, we're returning +// black with 100% opacity. +// +// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF. +// +// Deprecated. +func (n NoColor) RGBA() (r, g, b, a uint32) { + return 0x0, 0x0, 0x0, 0xFFFF //nolint:mnd +} + +// Color specifies a color by hex or ANSI value. For example: +// +// ansiColor := lipgloss.Color("21") +// hexColor := lipgloss.Color("#0000ff") +type Color string + +func (c Color) color(r *Renderer) termenv.Color { + return r.ColorProfile().Color(string(c)) +} + +// RGBA returns the RGBA value of this color. This satisfies the Go Color +// interface. Note that on error we return black with 100% opacity, or: +// +// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF. +// +// Deprecated. +func (c Color) RGBA() (r, g, b, a uint32) { + return termenv.ConvertToRGB(c.color(renderer)).RGBA() +} + +// ANSIColor is a color specified by an ANSI color value. It's merely syntactic +// sugar for the more general Color function. Invalid colors will render as +// black. +// +// Example usage: +// +// // These two statements are equivalent. +// colorA := lipgloss.ANSIColor(21) +// colorB := lipgloss.Color("21") +type ANSIColor uint + +func (ac ANSIColor) color(r *Renderer) termenv.Color { + return Color(strconv.FormatUint(uint64(ac), 10)).color(r) +} + +// RGBA returns the RGBA value of this color. This satisfies the Go Color +// interface. Note that on error we return black with 100% opacity, or: +// +// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF. +// +// Deprecated. +func (ac ANSIColor) RGBA() (r, g, b, a uint32) { + cf := Color(strconv.FormatUint(uint64(ac), 10)) + return cf.RGBA() +} + +// AdaptiveColor provides color options for light and dark backgrounds. The +// appropriate color will be returned at runtime based on the darkness of the +// terminal background color. +// +// Example usage: +// +// color := lipgloss.AdaptiveColor{Light: "#0000ff", Dark: "#000099"} +type AdaptiveColor struct { + Light string + Dark string +} + +func (ac AdaptiveColor) color(r *Renderer) termenv.Color { + if r.HasDarkBackground() { + return Color(ac.Dark).color(r) + } + return Color(ac.Light).color(r) +} + +// RGBA returns the RGBA value of this color. This satisfies the Go Color +// interface. Note that on error we return black with 100% opacity, or: +// +// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF. +// +// Deprecated. +func (ac AdaptiveColor) RGBA() (r, g, b, a uint32) { + return termenv.ConvertToRGB(ac.color(renderer)).RGBA() +} + +// CompleteColor specifies exact values for truecolor, ANSI256, and ANSI color +// profiles. Automatic color degradation will not be performed. +type CompleteColor struct { + TrueColor string + ANSI256 string + ANSI string +} + +func (c CompleteColor) color(r *Renderer) termenv.Color { + p := r.ColorProfile() + switch p { //nolint:exhaustive + case termenv.TrueColor: + return p.Color(c.TrueColor) + case termenv.ANSI256: + return p.Color(c.ANSI256) + case termenv.ANSI: + return p.Color(c.ANSI) + default: + return termenv.NoColor{} + } +} + +// RGBA returns the RGBA value of this color. This satisfies the Go Color +// interface. Note that on error we return black with 100% opacity, or: +// +// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF. +// CompleteAdaptiveColor specifies exact values for truecolor, ANSI256, and ANSI color +// +// Deprecated. +func (c CompleteColor) RGBA() (r, g, b, a uint32) { + return termenv.ConvertToRGB(c.color(renderer)).RGBA() +} + +// CompleteAdaptiveColor specifies exact values for truecolor, ANSI256, and ANSI color +// profiles, with separate options for light and dark backgrounds. Automatic +// color degradation will not be performed. +type CompleteAdaptiveColor struct { + Light CompleteColor + Dark CompleteColor +} + +func (cac CompleteAdaptiveColor) color(r *Renderer) termenv.Color { + if r.HasDarkBackground() { + return cac.Dark.color(r) + } + return cac.Light.color(r) +} + +// RGBA returns the RGBA value of this color. This satisfies the Go Color +// interface. Note that on error we return black with 100% opacity, or: +// +// Red: 0x0, Green: 0x0, Blue: 0x0, Alpha: 0xFFFF. +// +// Deprecated. +func (cac CompleteAdaptiveColor) RGBA() (r, g, b, a uint32) { + return termenv.ConvertToRGB(cac.color(renderer)).RGBA() +} diff --git a/vendor/github.com/charmbracelet/lipgloss/get.go b/vendor/github.com/charmbracelet/lipgloss/get.go new file mode 100644 index 00000000..422b4ce9 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/get.go @@ -0,0 +1,556 @@ +package lipgloss + +import ( + "strings" + + "github.com/charmbracelet/x/ansi" +) + +// GetBold returns the style's bold value. If no value is set false is returned. +func (s Style) GetBold() bool { + return s.getAsBool(boldKey, false) +} + +// GetItalic returns the style's italic value. If no value is set false is +// returned. +func (s Style) GetItalic() bool { + return s.getAsBool(italicKey, false) +} + +// GetUnderline returns the style's underline value. If no value is set false is +// returned. +func (s Style) GetUnderline() bool { + return s.getAsBool(underlineKey, false) +} + +// GetStrikethrough returns the style's strikethrough value. If no value is set false +// is returned. +func (s Style) GetStrikethrough() bool { + return s.getAsBool(strikethroughKey, false) +} + +// GetReverse returns the style's reverse value. If no value is set false is +// returned. +func (s Style) GetReverse() bool { + return s.getAsBool(reverseKey, false) +} + +// GetBlink returns the style's blink value. If no value is set false is +// returned. +func (s Style) GetBlink() bool { + return s.getAsBool(blinkKey, false) +} + +// GetFaint returns the style's faint value. If no value is set false is +// returned. +func (s Style) GetFaint() bool { + return s.getAsBool(faintKey, false) +} + +// GetForeground returns the style's foreground color. If no value is set +// NoColor{} is returned. +func (s Style) GetForeground() TerminalColor { + return s.getAsColor(foregroundKey) +} + +// GetBackground returns the style's background color. If no value is set +// NoColor{} is returned. +func (s Style) GetBackground() TerminalColor { + return s.getAsColor(backgroundKey) +} + +// GetWidth returns the style's width setting. If no width is set 0 is +// returned. +func (s Style) GetWidth() int { + return s.getAsInt(widthKey) +} + +// GetHeight returns the style's height setting. If no height is set 0 is +// returned. +func (s Style) GetHeight() int { + return s.getAsInt(heightKey) +} + +// GetAlign returns the style's implicit horizontal alignment setting. +// If no alignment is set Position.Left is returned. +func (s Style) GetAlign() Position { + v := s.getAsPosition(alignHorizontalKey) + if v == Position(0) { + return Left + } + return v +} + +// GetAlignHorizontal returns the style's implicit horizontal alignment setting. +// If no alignment is set Position.Left is returned. +func (s Style) GetAlignHorizontal() Position { + v := s.getAsPosition(alignHorizontalKey) + if v == Position(0) { + return Left + } + return v +} + +// GetAlignVertical returns the style's implicit vertical alignment setting. +// If no alignment is set Position.Top is returned. +func (s Style) GetAlignVertical() Position { + v := s.getAsPosition(alignVerticalKey) + if v == Position(0) { + return Top + } + return v +} + +// GetPadding returns the style's top, right, bottom, and left padding values, +// in that order. 0 is returned for unset values. +func (s Style) GetPadding() (top, right, bottom, left int) { + return s.getAsInt(paddingTopKey), + s.getAsInt(paddingRightKey), + s.getAsInt(paddingBottomKey), + s.getAsInt(paddingLeftKey) +} + +// GetPaddingTop returns the style's top padding. If no value is set 0 is +// returned. +func (s Style) GetPaddingTop() int { + return s.getAsInt(paddingTopKey) +} + +// GetPaddingRight returns the style's right padding. If no value is set 0 is +// returned. +func (s Style) GetPaddingRight() int { + return s.getAsInt(paddingRightKey) +} + +// GetPaddingBottom returns the style's bottom padding. If no value is set 0 is +// returned. +func (s Style) GetPaddingBottom() int { + return s.getAsInt(paddingBottomKey) +} + +// GetPaddingLeft returns the style's left padding. If no value is set 0 is +// returned. +func (s Style) GetPaddingLeft() int { + return s.getAsInt(paddingLeftKey) +} + +// GetHorizontalPadding returns the style's left and right padding. Unset +// values are measured as 0. +func (s Style) GetHorizontalPadding() int { + return s.getAsInt(paddingLeftKey) + s.getAsInt(paddingRightKey) +} + +// GetVerticalPadding returns the style's top and bottom padding. Unset values +// are measured as 0. +func (s Style) GetVerticalPadding() int { + return s.getAsInt(paddingTopKey) + s.getAsInt(paddingBottomKey) +} + +// GetColorWhitespace returns the style's whitespace coloring setting. If no +// value is set false is returned. +func (s Style) GetColorWhitespace() bool { + return s.getAsBool(colorWhitespaceKey, false) +} + +// GetMargin returns the style's top, right, bottom, and left margins, in that +// order. 0 is returned for unset values. +func (s Style) GetMargin() (top, right, bottom, left int) { + return s.getAsInt(marginTopKey), + s.getAsInt(marginRightKey), + s.getAsInt(marginBottomKey), + s.getAsInt(marginLeftKey) +} + +// GetMarginTop returns the style's top margin. If no value is set 0 is +// returned. +func (s Style) GetMarginTop() int { + return s.getAsInt(marginTopKey) +} + +// GetMarginRight returns the style's right margin. If no value is set 0 is +// returned. +func (s Style) GetMarginRight() int { + return s.getAsInt(marginRightKey) +} + +// GetMarginBottom returns the style's bottom margin. If no value is set 0 is +// returned. +func (s Style) GetMarginBottom() int { + return s.getAsInt(marginBottomKey) +} + +// GetMarginLeft returns the style's left margin. If no value is set 0 is +// returned. +func (s Style) GetMarginLeft() int { + return s.getAsInt(marginLeftKey) +} + +// GetHorizontalMargins returns the style's left and right margins. Unset +// values are measured as 0. +func (s Style) GetHorizontalMargins() int { + return s.getAsInt(marginLeftKey) + s.getAsInt(marginRightKey) +} + +// GetVerticalMargins returns the style's top and bottom margins. Unset values +// are measured as 0. +func (s Style) GetVerticalMargins() int { + return s.getAsInt(marginTopKey) + s.getAsInt(marginBottomKey) +} + +// GetBorder returns the style's border style (type Border) and value for the +// top, right, bottom, and left in that order. If no value is set for the +// border style, Border{} is returned. For all other unset values false is +// returned. +func (s Style) GetBorder() (b Border, top, right, bottom, left bool) { + return s.getBorderStyle(), + s.getAsBool(borderTopKey, false), + s.getAsBool(borderRightKey, false), + s.getAsBool(borderBottomKey, false), + s.getAsBool(borderLeftKey, false) +} + +// GetBorderStyle returns the style's border style (type Border). If no value +// is set Border{} is returned. +func (s Style) GetBorderStyle() Border { + return s.getBorderStyle() +} + +// GetBorderTop returns the style's top border setting. If no value is set +// false is returned. +func (s Style) GetBorderTop() bool { + return s.getAsBool(borderTopKey, false) +} + +// GetBorderRight returns the style's right border setting. If no value is set +// false is returned. +func (s Style) GetBorderRight() bool { + return s.getAsBool(borderRightKey, false) +} + +// GetBorderBottom returns the style's bottom border setting. If no value is +// set false is returned. +func (s Style) GetBorderBottom() bool { + return s.getAsBool(borderBottomKey, false) +} + +// GetBorderLeft returns the style's left border setting. If no value is +// set false is returned. +func (s Style) GetBorderLeft() bool { + return s.getAsBool(borderLeftKey, false) +} + +// GetBorderTopForeground returns the style's border top foreground color. If +// no value is set NoColor{} is returned. +func (s Style) GetBorderTopForeground() TerminalColor { + return s.getAsColor(borderTopForegroundKey) +} + +// GetBorderRightForeground returns the style's border right foreground color. +// If no value is set NoColor{} is returned. +func (s Style) GetBorderRightForeground() TerminalColor { + return s.getAsColor(borderRightForegroundKey) +} + +// GetBorderBottomForeground returns the style's border bottom foreground +// color. If no value is set NoColor{} is returned. +func (s Style) GetBorderBottomForeground() TerminalColor { + return s.getAsColor(borderBottomForegroundKey) +} + +// GetBorderLeftForeground returns the style's border left foreground +// color. If no value is set NoColor{} is returned. +func (s Style) GetBorderLeftForeground() TerminalColor { + return s.getAsColor(borderLeftForegroundKey) +} + +// GetBorderTopBackground returns the style's border top background color. If +// no value is set NoColor{} is returned. +func (s Style) GetBorderTopBackground() TerminalColor { + return s.getAsColor(borderTopBackgroundKey) +} + +// GetBorderRightBackground returns the style's border right background color. +// If no value is set NoColor{} is returned. +func (s Style) GetBorderRightBackground() TerminalColor { + return s.getAsColor(borderRightBackgroundKey) +} + +// GetBorderBottomBackground returns the style's border bottom background +// color. If no value is set NoColor{} is returned. +func (s Style) GetBorderBottomBackground() TerminalColor { + return s.getAsColor(borderBottomBackgroundKey) +} + +// GetBorderLeftBackground returns the style's border left background +// color. If no value is set NoColor{} is returned. +func (s Style) GetBorderLeftBackground() TerminalColor { + return s.getAsColor(borderLeftBackgroundKey) +} + +// GetBorderTopWidth returns the width of the top border. If borders contain +// runes of varying widths, the widest rune is returned. If no border exists on +// the top edge, 0 is returned. +// +// Deprecated: This function simply calls Style.GetBorderTopSize. +func (s Style) GetBorderTopWidth() int { + return s.GetBorderTopSize() +} + +// GetBorderTopSize returns the width of the top border. If borders contain +// runes of varying widths, the widest rune is returned. If no border exists on +// the top edge, 0 is returned. +func (s Style) GetBorderTopSize() int { + if !s.getAsBool(borderTopKey, false) && !s.implicitBorders() { + return 0 + } + return s.getBorderStyle().GetTopSize() +} + +// GetBorderLeftSize returns the width of the left border. If borders contain +// runes of varying widths, the widest rune is returned. If no border exists on +// the left edge, 0 is returned. +func (s Style) GetBorderLeftSize() int { + if !s.getAsBool(borderLeftKey, false) && !s.implicitBorders() { + return 0 + } + return s.getBorderStyle().GetLeftSize() +} + +// GetBorderBottomSize returns the width of the bottom border. If borders +// contain runes of varying widths, the widest rune is returned. If no border +// exists on the left edge, 0 is returned. +func (s Style) GetBorderBottomSize() int { + if !s.getAsBool(borderBottomKey, false) && !s.implicitBorders() { + return 0 + } + return s.getBorderStyle().GetBottomSize() +} + +// GetBorderRightSize returns the width of the right border. If borders +// contain runes of varying widths, the widest rune is returned. If no border +// exists on the right edge, 0 is returned. +func (s Style) GetBorderRightSize() int { + if !s.getAsBool(borderRightKey, false) && !s.implicitBorders() { + return 0 + } + return s.getBorderStyle().GetRightSize() +} + +// GetHorizontalBorderSize returns the width of the horizontal borders. If +// borders contain runes of varying widths, the widest rune is returned. If no +// border exists on the horizontal edges, 0 is returned. +func (s Style) GetHorizontalBorderSize() int { + return s.GetBorderLeftSize() + s.GetBorderRightSize() +} + +// GetVerticalBorderSize returns the width of the vertical borders. If +// borders contain runes of varying widths, the widest rune is returned. If no +// border exists on the vertical edges, 0 is returned. +func (s Style) GetVerticalBorderSize() int { + return s.GetBorderTopSize() + s.GetBorderBottomSize() +} + +// GetInline returns the style's inline setting. If no value is set false is +// returned. +func (s Style) GetInline() bool { + return s.getAsBool(inlineKey, false) +} + +// GetMaxWidth returns the style's max width setting. If no value is set 0 is +// returned. +func (s Style) GetMaxWidth() int { + return s.getAsInt(maxWidthKey) +} + +// GetMaxHeight returns the style's max height setting. If no value is set 0 is +// returned. +func (s Style) GetMaxHeight() int { + return s.getAsInt(maxHeightKey) +} + +// GetTabWidth returns the style's tab width setting. If no value is set 4 is +// returned which is the implicit default. +func (s Style) GetTabWidth() int { + return s.getAsInt(tabWidthKey) +} + +// GetUnderlineSpaces returns whether or not the style is set to underline +// spaces. If not value is set false is returned. +func (s Style) GetUnderlineSpaces() bool { + return s.getAsBool(underlineSpacesKey, false) +} + +// GetStrikethroughSpaces returns whether or not the style is set to strikethrough +// spaces. If not value is set false is returned. +func (s Style) GetStrikethroughSpaces() bool { + return s.getAsBool(strikethroughSpacesKey, false) +} + +// GetHorizontalFrameSize returns the sum of the style's horizontal margins, padding +// and border widths. +// +// Provisional: this method may be renamed. +func (s Style) GetHorizontalFrameSize() int { + return s.GetHorizontalMargins() + s.GetHorizontalPadding() + s.GetHorizontalBorderSize() +} + +// GetVerticalFrameSize returns the sum of the style's vertical margins, padding +// and border widths. +// +// Provisional: this method may be renamed. +func (s Style) GetVerticalFrameSize() int { + return s.GetVerticalMargins() + s.GetVerticalPadding() + s.GetVerticalBorderSize() +} + +// GetFrameSize returns the sum of the margins, padding and border width for +// both the horizontal and vertical margins. +func (s Style) GetFrameSize() (x, y int) { + return s.GetHorizontalFrameSize(), s.GetVerticalFrameSize() +} + +// GetTransform returns the transform set on the style. If no transform is set +// nil is returned. +func (s Style) GetTransform() func(string) string { + return s.getAsTransform(transformKey) +} + +// Returns whether or not the given property is set. +func (s Style) isSet(k propKey) bool { + return s.props.has(k) +} + +func (s Style) getAsBool(k propKey, defaultVal bool) bool { + if !s.isSet(k) { + return defaultVal + } + return s.attrs&int(k) != 0 +} + +func (s Style) getAsColor(k propKey) TerminalColor { + if !s.isSet(k) { + return noColor + } + + var c TerminalColor + switch k { //nolint:exhaustive + case foregroundKey: + c = s.fgColor + case backgroundKey: + c = s.bgColor + case marginBackgroundKey: + c = s.marginBgColor + case borderTopForegroundKey: + c = s.borderTopFgColor + case borderRightForegroundKey: + c = s.borderRightFgColor + case borderBottomForegroundKey: + c = s.borderBottomFgColor + case borderLeftForegroundKey: + c = s.borderLeftFgColor + case borderTopBackgroundKey: + c = s.borderTopBgColor + case borderRightBackgroundKey: + c = s.borderRightBgColor + case borderBottomBackgroundKey: + c = s.borderBottomBgColor + case borderLeftBackgroundKey: + c = s.borderLeftBgColor + } + + if c != nil { + return c + } + + return noColor +} + +func (s Style) getAsInt(k propKey) int { + if !s.isSet(k) { + return 0 + } + switch k { //nolint:exhaustive + case widthKey: + return s.width + case heightKey: + return s.height + case paddingTopKey: + return s.paddingTop + case paddingRightKey: + return s.paddingRight + case paddingBottomKey: + return s.paddingBottom + case paddingLeftKey: + return s.paddingLeft + case marginTopKey: + return s.marginTop + case marginRightKey: + return s.marginRight + case marginBottomKey: + return s.marginBottom + case marginLeftKey: + return s.marginLeft + case maxWidthKey: + return s.maxWidth + case maxHeightKey: + return s.maxHeight + case tabWidthKey: + return s.tabWidth + } + return 0 +} + +func (s Style) getAsPosition(k propKey) Position { + if !s.isSet(k) { + return Position(0) + } + switch k { //nolint:exhaustive + case alignHorizontalKey: + return s.alignHorizontal + case alignVerticalKey: + return s.alignVertical + } + return Position(0) +} + +func (s Style) getBorderStyle() Border { + if !s.isSet(borderStyleKey) { + return noBorder + } + return s.borderStyle +} + +// Returns whether or not the style has implicit borders. This happens when +// a border style has been set but no border sides have been explicitly turned +// on or off. +func (s Style) implicitBorders() bool { + var ( + borderStyle = s.getBorderStyle() + topSet = s.isSet(borderTopKey) + rightSet = s.isSet(borderRightKey) + bottomSet = s.isSet(borderBottomKey) + leftSet = s.isSet(borderLeftKey) + ) + return borderStyle != noBorder && !(topSet || rightSet || bottomSet || leftSet) +} + +func (s Style) getAsTransform(propKey) func(string) string { + if !s.isSet(transformKey) { + return nil + } + return s.transform +} + +// Split a string into lines, additionally returning the size of the widest +// line. +func getLines(s string) (lines []string, widest int) { + lines = strings.Split(s, "\n") + + for _, l := range lines { + w := ansi.StringWidth(l) + if widest < w { + widest = w + } + } + + return lines, widest +} diff --git a/vendor/github.com/charmbracelet/lipgloss/join.go b/vendor/github.com/charmbracelet/lipgloss/join.go new file mode 100644 index 00000000..b0a23a54 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/join.go @@ -0,0 +1,175 @@ +package lipgloss + +import ( + "math" + "strings" + + "github.com/charmbracelet/x/ansi" +) + +// JoinHorizontal is a utility function for horizontally joining two +// potentially multi-lined strings along a vertical axis. The first argument is +// the position, with 0 being all the way at the top and 1 being all the way +// at the bottom. +// +// If you just want to align to the top, center or bottom you may as well just +// use the helper constants Top, Center, and Bottom. +// +// Example: +// +// blockB := "...\n...\n..." +// blockA := "...\n...\n...\n...\n..." +// +// // Join 20% from the top +// str := lipgloss.JoinHorizontal(0.2, blockA, blockB) +// +// // Join on the top edge +// str := lipgloss.JoinHorizontal(lipgloss.Top, blockA, blockB) +func JoinHorizontal(pos Position, strs ...string) string { + if len(strs) == 0 { + return "" + } + if len(strs) == 1 { + return strs[0] + } + + var ( + // Groups of strings broken into multiple lines + blocks = make([][]string, len(strs)) + + // Max line widths for the above text blocks + maxWidths = make([]int, len(strs)) + + // Height of the tallest block + maxHeight int + ) + + // Break text blocks into lines and get max widths for each text block + for i, str := range strs { + blocks[i], maxWidths[i] = getLines(str) + if len(blocks[i]) > maxHeight { + maxHeight = len(blocks[i]) + } + } + + // Add extra lines to make each side the same height + for i := range blocks { + if len(blocks[i]) >= maxHeight { + continue + } + + extraLines := make([]string, maxHeight-len(blocks[i])) + + switch pos { //nolint:exhaustive + case Top: + blocks[i] = append(blocks[i], extraLines...) + + case Bottom: + blocks[i] = append(extraLines, blocks[i]...) + + default: // Somewhere in the middle + n := len(extraLines) + split := int(math.Round(float64(n) * pos.value())) + top := n - split + bottom := n - top + + blocks[i] = append(extraLines[top:], blocks[i]...) + blocks[i] = append(blocks[i], extraLines[bottom:]...) + } + } + + // Merge lines + var b strings.Builder + for i := range blocks[0] { // remember, all blocks have the same number of members now + for j, block := range blocks { + b.WriteString(block[i]) + + // Also make lines the same length + b.WriteString(strings.Repeat(" ", maxWidths[j]-ansi.StringWidth(block[i]))) + } + if i < len(blocks[0])-1 { + b.WriteRune('\n') + } + } + + return b.String() +} + +// JoinVertical is a utility function for vertically joining two potentially +// multi-lined strings along a horizontal axis. The first argument is the +// position, with 0 being all the way to the left and 1 being all the way to +// the right. +// +// If you just want to align to the left, right or center you may as well just +// use the helper constants Left, Center, and Right. +// +// Example: +// +// blockB := "...\n...\n..." +// blockA := "...\n...\n...\n...\n..." +// +// // Join 20% from the top +// str := lipgloss.JoinVertical(0.2, blockA, blockB) +// +// // Join on the right edge +// str := lipgloss.JoinVertical(lipgloss.Right, blockA, blockB) +func JoinVertical(pos Position, strs ...string) string { + if len(strs) == 0 { + return "" + } + if len(strs) == 1 { + return strs[0] + } + + var ( + blocks = make([][]string, len(strs)) + maxWidth int + ) + + for i := range strs { + var w int + blocks[i], w = getLines(strs[i]) + if w > maxWidth { + maxWidth = w + } + } + + var b strings.Builder + for i, block := range blocks { + for j, line := range block { + w := maxWidth - ansi.StringWidth(line) + + switch pos { //nolint:exhaustive + case Left: + b.WriteString(line) + b.WriteString(strings.Repeat(" ", w)) + + case Right: + b.WriteString(strings.Repeat(" ", w)) + b.WriteString(line) + + default: // Somewhere in the middle + if w < 1 { + b.WriteString(line) + break + } + + split := int(math.Round(float64(w) * pos.value())) + right := w - split + left := w - right + + b.WriteString(strings.Repeat(" ", left)) + b.WriteString(line) + b.WriteString(strings.Repeat(" ", right)) + } + + // Write a newline as long as we're not on the last line of the + // last block. + if !(i == len(blocks)-1 && j == len(block)-1) { + b.WriteRune('\n') + } + } + } + + return b.String() +} diff --git a/vendor/github.com/charmbracelet/lipgloss/position.go b/vendor/github.com/charmbracelet/lipgloss/position.go new file mode 100644 index 00000000..185f5af3 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/position.go @@ -0,0 +1,154 @@ +package lipgloss + +import ( + "math" + "strings" + + "github.com/charmbracelet/x/ansi" +) + +// Position represents a position along a horizontal or vertical axis. It's in +// situations where an axis is involved, like alignment, joining, placement and +// so on. +// +// A value of 0 represents the start (the left or top) and 1 represents the end +// (the right or bottom). 0.5 represents the center. +// +// There are constants Top, Bottom, Center, Left and Right in this package that +// can be used to aid readability. +type Position float64 + +func (p Position) value() float64 { + return math.Min(1, math.Max(0, float64(p))) +} + +// Position aliases. +const ( + Top Position = 0.0 + Bottom Position = 1.0 + Center Position = 0.5 + Left Position = 0.0 + Right Position = 1.0 +) + +// Place places a string or text block vertically in an unstyled box of a given +// width or height. +func Place(width, height int, hPos, vPos Position, str string, opts ...WhitespaceOption) string { + return renderer.Place(width, height, hPos, vPos, str, opts...) +} + +// Place places a string or text block vertically in an unstyled box of a given +// width or height. +func (r *Renderer) Place(width, height int, hPos, vPos Position, str string, opts ...WhitespaceOption) string { + return r.PlaceVertical(height, vPos, r.PlaceHorizontal(width, hPos, str, opts...), opts...) +} + +// PlaceHorizontal places a string or text block horizontally in an unstyled +// block of a given width. If the given width is shorter than the max width of +// the string (measured by its longest line) this will be a noop. +func PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string { + return renderer.PlaceHorizontal(width, pos, str, opts...) +} + +// PlaceHorizontal places a string or text block horizontally in an unstyled +// block of a given width. If the given width is shorter than the max width of +// the string (measured by its longest line) this will be a noöp. +func (r *Renderer) PlaceHorizontal(width int, pos Position, str string, opts ...WhitespaceOption) string { + lines, contentWidth := getLines(str) + gap := width - contentWidth + + if gap <= 0 { + return str + } + + ws := newWhitespace(r, opts...) + + var b strings.Builder + for i, l := range lines { + // Is this line shorter than the longest line? + short := max(0, contentWidth-ansi.StringWidth(l)) + + switch pos { //nolint:exhaustive + case Left: + b.WriteString(l) + b.WriteString(ws.render(gap + short)) + + case Right: + b.WriteString(ws.render(gap + short)) + b.WriteString(l) + + default: // somewhere in the middle + totalGap := gap + short + + split := int(math.Round(float64(totalGap) * pos.value())) + left := totalGap - split + right := totalGap - left + + b.WriteString(ws.render(left)) + b.WriteString(l) + b.WriteString(ws.render(right)) + } + + if i < len(lines)-1 { + b.WriteRune('\n') + } + } + + return b.String() +} + +// PlaceVertical places a string or text block vertically in an unstyled block +// of a given height. If the given height is shorter than the height of the +// string (measured by its newlines) then this will be a noop. +func PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string { + return renderer.PlaceVertical(height, pos, str, opts...) +} + +// PlaceVertical places a string or text block vertically in an unstyled block +// of a given height. If the given height is shorter than the height of the +// string (measured by its newlines) then this will be a noöp. +func (r *Renderer) PlaceVertical(height int, pos Position, str string, opts ...WhitespaceOption) string { + contentHeight := strings.Count(str, "\n") + 1 + gap := height - contentHeight + + if gap <= 0 { + return str + } + + ws := newWhitespace(r, opts...) + + _, width := getLines(str) + emptyLine := ws.render(width) + b := strings.Builder{} + + switch pos { //nolint:exhaustive + case Top: + b.WriteString(str) + b.WriteRune('\n') + for i := 0; i < gap; i++ { + b.WriteString(emptyLine) + if i < gap-1 { + b.WriteRune('\n') + } + } + + case Bottom: + b.WriteString(strings.Repeat(emptyLine+"\n", gap)) + b.WriteString(str) + + default: // Somewhere in the middle + split := int(math.Round(float64(gap) * pos.value())) + top := gap - split + bottom := gap - top + + b.WriteString(strings.Repeat(emptyLine+"\n", top)) + b.WriteString(str) + + for i := 0; i < bottom; i++ { + b.WriteRune('\n') + b.WriteString(emptyLine) + } + } + + return b.String() +} diff --git a/vendor/github.com/charmbracelet/lipgloss/ranges.go b/vendor/github.com/charmbracelet/lipgloss/ranges.go new file mode 100644 index 00000000..d1716998 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/ranges.go @@ -0,0 +1,48 @@ +package lipgloss + +import ( + "strings" + + "github.com/charmbracelet/x/ansi" +) + +// StyleRanges allows to, given a string, style ranges of it differently. +// The function will take into account existing styles. +// Ranges should not overlap. +func StyleRanges(s string, ranges ...Range) string { + if len(ranges) == 0 { + return s + } + + var buf strings.Builder + lastIdx := 0 + stripped := ansi.Strip(s) + + // Use Truncate and TruncateLeft to style match.MatchedIndexes without + // losing the original option style: + for _, rng := range ranges { + // Add the text before this match + if rng.Start > lastIdx { + buf.WriteString(ansi.Cut(s, lastIdx, rng.Start)) + } + // Add the matched range with its highlight + buf.WriteString(rng.Style.Render(ansi.Cut(stripped, rng.Start, rng.End))) + lastIdx = rng.End + } + + // Add any remaining text after the last match + buf.WriteString(ansi.TruncateLeft(s, lastIdx, "")) + + return buf.String() +} + +// NewRange returns a range that can be used with [StyleRanges]. +func NewRange(start, end int, style Style) Range { + return Range{start, end, style} +} + +// Range to be used with [StyleRanges]. +type Range struct { + Start, End int + Style Style +} diff --git a/vendor/github.com/charmbracelet/lipgloss/renderer.go b/vendor/github.com/charmbracelet/lipgloss/renderer.go new file mode 100644 index 00000000..233aa7c0 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/renderer.go @@ -0,0 +1,181 @@ +package lipgloss + +import ( + "io" + "sync" + + "github.com/muesli/termenv" +) + +// We're manually creating the struct here to avoid initializing the output and +// query the terminal multiple times. +var renderer = &Renderer{ + output: termenv.DefaultOutput(), +} + +// Renderer is a lipgloss terminal renderer. +type Renderer struct { + output *termenv.Output + colorProfile termenv.Profile + hasDarkBackground bool + + getColorProfile sync.Once + explicitColorProfile bool + + getBackgroundColor sync.Once + explicitBackgroundColor bool + + mtx sync.RWMutex +} + +// DefaultRenderer returns the default renderer. +func DefaultRenderer() *Renderer { + return renderer +} + +// SetDefaultRenderer sets the default global renderer. +func SetDefaultRenderer(r *Renderer) { + renderer = r +} + +// NewRenderer creates a new Renderer. +// +// w will be used to determine the terminal's color capabilities. +func NewRenderer(w io.Writer, opts ...termenv.OutputOption) *Renderer { + r := &Renderer{ + output: termenv.NewOutput(w, opts...), + } + return r +} + +// Output returns the termenv output. +func (r *Renderer) Output() *termenv.Output { + r.mtx.RLock() + defer r.mtx.RUnlock() + return r.output +} + +// SetOutput sets the termenv output. +func (r *Renderer) SetOutput(o *termenv.Output) { + r.mtx.Lock() + defer r.mtx.Unlock() + r.output = o +} + +// ColorProfile returns the detected termenv color profile. +func (r *Renderer) ColorProfile() termenv.Profile { + r.mtx.RLock() + defer r.mtx.RUnlock() + + if !r.explicitColorProfile { + r.getColorProfile.Do(func() { + // NOTE: we don't need to lock here because sync.Once provides its + // own locking mechanism. + r.colorProfile = r.output.EnvColorProfile() + }) + } + + return r.colorProfile +} + +// ColorProfile returns the detected termenv color profile. +func ColorProfile() termenv.Profile { + return renderer.ColorProfile() +} + +// SetColorProfile sets the color profile on the renderer. This function exists +// mostly for testing purposes so that you can assure you're testing against +// a specific profile. +// +// Outside of testing you likely won't want to use this function as the color +// profile will detect and cache the terminal's color capabilities and choose +// the best available profile. +// +// Available color profiles are: +// +// termenv.Ascii // no color, 1-bit +// termenv.ANSI //16 colors, 4-bit +// termenv.ANSI256 // 256 colors, 8-bit +// termenv.TrueColor // 16,777,216 colors, 24-bit +// +// This function is thread-safe. +func (r *Renderer) SetColorProfile(p termenv.Profile) { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.colorProfile = p + r.explicitColorProfile = true +} + +// SetColorProfile sets the color profile on the default renderer. This +// function exists mostly for testing purposes so that you can assure you're +// testing against a specific profile. +// +// Outside of testing you likely won't want to use this function as the color +// profile will detect and cache the terminal's color capabilities and choose +// the best available profile. +// +// Available color profiles are: +// +// termenv.Ascii // no color, 1-bit +// termenv.ANSI //16 colors, 4-bit +// termenv.ANSI256 // 256 colors, 8-bit +// termenv.TrueColor // 16,777,216 colors, 24-bit +// +// This function is thread-safe. +func SetColorProfile(p termenv.Profile) { + renderer.SetColorProfile(p) +} + +// HasDarkBackground returns whether or not the terminal has a dark background. +func HasDarkBackground() bool { + return renderer.HasDarkBackground() +} + +// HasDarkBackground returns whether or not the renderer will render to a dark +// background. A dark background can either be auto-detected, or set explicitly +// on the renderer. +func (r *Renderer) HasDarkBackground() bool { + r.mtx.RLock() + defer r.mtx.RUnlock() + + if !r.explicitBackgroundColor { + r.getBackgroundColor.Do(func() { + // NOTE: we don't need to lock here because sync.Once provides its + // own locking mechanism. + r.hasDarkBackground = r.output.HasDarkBackground() + }) + } + + return r.hasDarkBackground +} + +// SetHasDarkBackground sets the background color detection value for the +// default renderer. This function exists mostly for testing purposes so that +// you can assure you're testing against a specific background color setting. +// +// Outside of testing you likely won't want to use this function as the +// backgrounds value will be automatically detected and cached against the +// terminal's current background color setting. +// +// This function is thread-safe. +func SetHasDarkBackground(b bool) { + renderer.SetHasDarkBackground(b) +} + +// SetHasDarkBackground sets the background color detection value on the +// renderer. This function exists mostly for testing purposes so that you can +// assure you're testing against a specific background color setting. +// +// Outside of testing you likely won't want to use this function as the +// backgrounds value will be automatically detected and cached against the +// terminal's current background color setting. +// +// This function is thread-safe. +func (r *Renderer) SetHasDarkBackground(b bool) { + r.mtx.Lock() + defer r.mtx.Unlock() + + r.hasDarkBackground = b + r.explicitBackgroundColor = true +} diff --git a/vendor/github.com/charmbracelet/lipgloss/runes.go b/vendor/github.com/charmbracelet/lipgloss/runes.go new file mode 100644 index 00000000..7a49e326 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/runes.go @@ -0,0 +1,43 @@ +package lipgloss + +import ( + "strings" +) + +// StyleRunes apply a given style to runes at the given indices in the string. +// Note that you must provide styling options for both matched and unmatched +// runes. Indices out of bounds will be ignored. +func StyleRunes(str string, indices []int, matched, unmatched Style) string { + // Convert slice of indices to a map for easier lookups + m := make(map[int]struct{}) + for _, i := range indices { + m[i] = struct{}{} + } + + var ( + out strings.Builder + group strings.Builder + style Style + runes = []rune(str) + ) + + for i, r := range runes { + group.WriteRune(r) + + _, matches := m[i] + _, nextMatches := m[i+1] + + if matches != nextMatches || i == len(runes)-1 { + // Flush + if matches { + style = matched + } else { + style = unmatched + } + out.WriteString(style.Render(group.String())) + group.Reset() + } + } + + return out.String() +} diff --git a/vendor/github.com/charmbracelet/lipgloss/set.go b/vendor/github.com/charmbracelet/lipgloss/set.go new file mode 100644 index 00000000..fde38fae --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/set.go @@ -0,0 +1,799 @@ +package lipgloss + +// Set a value on the underlying rules map. +func (s *Style) set(key propKey, value interface{}) { + // We don't allow negative integers on any of our other values, so just keep + // them at zero or above. We could use uints instead, but the + // conversions are a little tedious, so we're sticking with ints for + // sake of usability. + switch key { //nolint:exhaustive + case foregroundKey: + s.fgColor = colorOrNil(value) + case backgroundKey: + s.bgColor = colorOrNil(value) + case widthKey: + s.width = max(0, value.(int)) + case heightKey: + s.height = max(0, value.(int)) + case alignHorizontalKey: + s.alignHorizontal = value.(Position) + case alignVerticalKey: + s.alignVertical = value.(Position) + case paddingTopKey: + s.paddingTop = max(0, value.(int)) + case paddingRightKey: + s.paddingRight = max(0, value.(int)) + case paddingBottomKey: + s.paddingBottom = max(0, value.(int)) + case paddingLeftKey: + s.paddingLeft = max(0, value.(int)) + case marginTopKey: + s.marginTop = max(0, value.(int)) + case marginRightKey: + s.marginRight = max(0, value.(int)) + case marginBottomKey: + s.marginBottom = max(0, value.(int)) + case marginLeftKey: + s.marginLeft = max(0, value.(int)) + case marginBackgroundKey: + s.marginBgColor = colorOrNil(value) + case borderStyleKey: + s.borderStyle = value.(Border) + case borderTopForegroundKey: + s.borderTopFgColor = colorOrNil(value) + case borderRightForegroundKey: + s.borderRightFgColor = colorOrNil(value) + case borderBottomForegroundKey: + s.borderBottomFgColor = colorOrNil(value) + case borderLeftForegroundKey: + s.borderLeftFgColor = colorOrNil(value) + case borderTopBackgroundKey: + s.borderTopBgColor = colorOrNil(value) + case borderRightBackgroundKey: + s.borderRightBgColor = colorOrNil(value) + case borderBottomBackgroundKey: + s.borderBottomBgColor = colorOrNil(value) + case borderLeftBackgroundKey: + s.borderLeftBgColor = colorOrNil(value) + case maxWidthKey: + s.maxWidth = max(0, value.(int)) + case maxHeightKey: + s.maxHeight = max(0, value.(int)) + case tabWidthKey: + // TabWidth is the only property that may have a negative value (and + // that negative value can be no less than -1). + s.tabWidth = value.(int) + case transformKey: + s.transform = value.(func(string) string) + default: + if v, ok := value.(bool); ok { //nolint:nestif + if v { + s.attrs |= int(key) + } else { + s.attrs &^= int(key) + } + } else if attrs, ok := value.(int); ok { + // bool attrs + if attrs&int(key) != 0 { + s.attrs |= int(key) + } else { + s.attrs &^= int(key) + } + } + } + + // Set the prop on + s.props = s.props.set(key) +} + +// setFrom sets the property from another style. +func (s *Style) setFrom(key propKey, i Style) { + switch key { //nolint:exhaustive + case foregroundKey: + s.set(foregroundKey, i.fgColor) + case backgroundKey: + s.set(backgroundKey, i.bgColor) + case widthKey: + s.set(widthKey, i.width) + case heightKey: + s.set(heightKey, i.height) + case alignHorizontalKey: + s.set(alignHorizontalKey, i.alignHorizontal) + case alignVerticalKey: + s.set(alignVerticalKey, i.alignVertical) + case paddingTopKey: + s.set(paddingTopKey, i.paddingTop) + case paddingRightKey: + s.set(paddingRightKey, i.paddingRight) + case paddingBottomKey: + s.set(paddingBottomKey, i.paddingBottom) + case paddingLeftKey: + s.set(paddingLeftKey, i.paddingLeft) + case marginTopKey: + s.set(marginTopKey, i.marginTop) + case marginRightKey: + s.set(marginRightKey, i.marginRight) + case marginBottomKey: + s.set(marginBottomKey, i.marginBottom) + case marginLeftKey: + s.set(marginLeftKey, i.marginLeft) + case marginBackgroundKey: + s.set(marginBackgroundKey, i.marginBgColor) + case borderStyleKey: + s.set(borderStyleKey, i.borderStyle) + case borderTopForegroundKey: + s.set(borderTopForegroundKey, i.borderTopFgColor) + case borderRightForegroundKey: + s.set(borderRightForegroundKey, i.borderRightFgColor) + case borderBottomForegroundKey: + s.set(borderBottomForegroundKey, i.borderBottomFgColor) + case borderLeftForegroundKey: + s.set(borderLeftForegroundKey, i.borderLeftFgColor) + case borderTopBackgroundKey: + s.set(borderTopBackgroundKey, i.borderTopBgColor) + case borderRightBackgroundKey: + s.set(borderRightBackgroundKey, i.borderRightBgColor) + case borderBottomBackgroundKey: + s.set(borderBottomBackgroundKey, i.borderBottomBgColor) + case borderLeftBackgroundKey: + s.set(borderLeftBackgroundKey, i.borderLeftBgColor) + case maxWidthKey: + s.set(maxWidthKey, i.maxWidth) + case maxHeightKey: + s.set(maxHeightKey, i.maxHeight) + case tabWidthKey: + s.set(tabWidthKey, i.tabWidth) + case transformKey: + s.set(transformKey, i.transform) + default: + // Set attributes for set bool properties + s.set(key, i.attrs) + } +} + +func colorOrNil(c interface{}) TerminalColor { + if c, ok := c.(TerminalColor); ok { + return c + } + return nil +} + +// Bold sets a bold formatting rule. +func (s Style) Bold(v bool) Style { + s.set(boldKey, v) + return s +} + +// Italic sets an italic formatting rule. In some terminal emulators this will +// render with "reverse" coloring if not italic font variant is available. +func (s Style) Italic(v bool) Style { + s.set(italicKey, v) + return s +} + +// Underline sets an underline rule. By default, underlines will not be drawn on +// whitespace like margins and padding. To change this behavior set +// UnderlineSpaces. +func (s Style) Underline(v bool) Style { + s.set(underlineKey, v) + return s +} + +// Strikethrough sets a strikethrough rule. By default, strikes will not be +// drawn on whitespace like margins and padding. To change this behavior set +// StrikethroughSpaces. +func (s Style) Strikethrough(v bool) Style { + s.set(strikethroughKey, v) + return s +} + +// Reverse sets a rule for inverting foreground and background colors. +func (s Style) Reverse(v bool) Style { + s.set(reverseKey, v) + return s +} + +// Blink sets a rule for blinking foreground text. +func (s Style) Blink(v bool) Style { + s.set(blinkKey, v) + return s +} + +// Faint sets a rule for rendering the foreground color in a dimmer shade. +func (s Style) Faint(v bool) Style { + s.set(faintKey, v) + return s +} + +// Foreground sets a foreground color. +// +// // Sets the foreground to blue +// s := lipgloss.NewStyle().Foreground(lipgloss.Color("#0000ff")) +// +// // Removes the foreground color +// s.Foreground(lipgloss.NoColor) +func (s Style) Foreground(c TerminalColor) Style { + s.set(foregroundKey, c) + return s +} + +// Background sets a background color. +func (s Style) Background(c TerminalColor) Style { + s.set(backgroundKey, c) + return s +} + +// Width sets the width of the block before applying margins. The width, if +// set, also determines where text will wrap. +func (s Style) Width(i int) Style { + s.set(widthKey, i) + return s +} + +// Height sets the height of the block before applying margins. If the height of +// the text block is less than this value after applying padding (or not), the +// block will be set to this height. +func (s Style) Height(i int) Style { + s.set(heightKey, i) + return s +} + +// Align is a shorthand method for setting horizontal and vertical alignment. +// +// With one argument, the position value is applied to the horizontal alignment. +// +// With two arguments, the value is applied to the horizontal and vertical +// alignments, in that order. +func (s Style) Align(p ...Position) Style { + if len(p) > 0 { + s.set(alignHorizontalKey, p[0]) + } + if len(p) > 1 { + s.set(alignVerticalKey, p[1]) + } + return s +} + +// AlignHorizontal sets a horizontal text alignment rule. +func (s Style) AlignHorizontal(p Position) Style { + s.set(alignHorizontalKey, p) + return s +} + +// AlignVertical sets a vertical text alignment rule. +func (s Style) AlignVertical(p Position) Style { + s.set(alignVerticalKey, p) + return s +} + +// Padding is a shorthand method for setting padding on all sides at once. +// +// With one argument, the value is applied to all sides. +// +// With two arguments, the value is applied to the vertical and horizontal +// sides, in that order. +// +// With three arguments, the value is applied to the top side, the horizontal +// sides, and the bottom side, in that order. +// +// With four arguments, the value is applied clockwise starting from the top +// side, followed by the right side, then the bottom, and finally the left. +// +// With more than four arguments no padding will be added. +func (s Style) Padding(i ...int) Style { + top, right, bottom, left, ok := whichSidesInt(i...) + if !ok { + return s + } + + s.set(paddingTopKey, top) + s.set(paddingRightKey, right) + s.set(paddingBottomKey, bottom) + s.set(paddingLeftKey, left) + return s +} + +// PaddingLeft adds padding on the left. +func (s Style) PaddingLeft(i int) Style { + s.set(paddingLeftKey, i) + return s +} + +// PaddingRight adds padding on the right. +func (s Style) PaddingRight(i int) Style { + s.set(paddingRightKey, i) + return s +} + +// PaddingTop adds padding to the top of the block. +func (s Style) PaddingTop(i int) Style { + s.set(paddingTopKey, i) + return s +} + +// PaddingBottom adds padding to the bottom of the block. +func (s Style) PaddingBottom(i int) Style { + s.set(paddingBottomKey, i) + return s +} + +// ColorWhitespace determines whether or not the background color should be +// applied to the padding. This is true by default as it's more than likely the +// desired and expected behavior, but it can be disabled for certain graphic +// effects. +// +// Deprecated: Just use margins and padding. +func (s Style) ColorWhitespace(v bool) Style { + s.set(colorWhitespaceKey, v) + return s +} + +// Margin is a shorthand method for setting margins on all sides at once. +// +// With one argument, the value is applied to all sides. +// +// With two arguments, the value is applied to the vertical and horizontal +// sides, in that order. +// +// With three arguments, the value is applied to the top side, the horizontal +// sides, and the bottom side, in that order. +// +// With four arguments, the value is applied clockwise starting from the top +// side, followed by the right side, then the bottom, and finally the left. +// +// With more than four arguments no margin will be added. +func (s Style) Margin(i ...int) Style { + top, right, bottom, left, ok := whichSidesInt(i...) + if !ok { + return s + } + + s.set(marginTopKey, top) + s.set(marginRightKey, right) + s.set(marginBottomKey, bottom) + s.set(marginLeftKey, left) + return s +} + +// MarginLeft sets the value of the left margin. +func (s Style) MarginLeft(i int) Style { + s.set(marginLeftKey, i) + return s +} + +// MarginRight sets the value of the right margin. +func (s Style) MarginRight(i int) Style { + s.set(marginRightKey, i) + return s +} + +// MarginTop sets the value of the top margin. +func (s Style) MarginTop(i int) Style { + s.set(marginTopKey, i) + return s +} + +// MarginBottom sets the value of the bottom margin. +func (s Style) MarginBottom(i int) Style { + s.set(marginBottomKey, i) + return s +} + +// MarginBackground sets the background color of the margin. Note that this is +// also set when inheriting from a style with a background color. In that case +// the background color on that style will set the margin color on this style. +func (s Style) MarginBackground(c TerminalColor) Style { + s.set(marginBackgroundKey, c) + return s +} + +// Border is shorthand for setting the border style and which sides should +// have a border at once. The variadic argument sides works as follows: +// +// With one value, the value is applied to all sides. +// +// With two values, the values are applied to the vertical and horizontal +// sides, in that order. +// +// With three values, the values are applied to the top side, the horizontal +// sides, and the bottom side, in that order. +// +// With four values, the values are applied clockwise starting from the top +// side, followed by the right side, then the bottom, and finally the left. +// +// With more than four arguments the border will be applied to all sides. +// +// Examples: +// +// // Applies borders to the top and bottom only +// lipgloss.NewStyle().Border(lipgloss.NormalBorder(), true, false) +// +// // Applies rounded borders to the right and bottom only +// lipgloss.NewStyle().Border(lipgloss.RoundedBorder(), false, true, true, false) +func (s Style) Border(b Border, sides ...bool) Style { + s.set(borderStyleKey, b) + + top, right, bottom, left, ok := whichSidesBool(sides...) + if !ok { + top = true + right = true + bottom = true + left = true + } + + s.set(borderTopKey, top) + s.set(borderRightKey, right) + s.set(borderBottomKey, bottom) + s.set(borderLeftKey, left) + + return s +} + +// BorderStyle defines the Border on a style. A Border contains a series of +// definitions for the sides and corners of a border. +// +// Note that if border visibility has not been set for any sides when setting +// the border style, the border will be enabled for all sides during rendering. +// +// You can define border characters as you'd like, though several default +// styles are included: NormalBorder(), RoundedBorder(), BlockBorder(), +// OuterHalfBlockBorder(), InnerHalfBlockBorder(), ThickBorder(), +// and DoubleBorder(). +// +// Example: +// +// lipgloss.NewStyle().BorderStyle(lipgloss.ThickBorder()) +func (s Style) BorderStyle(b Border) Style { + s.set(borderStyleKey, b) + return s +} + +// BorderTop determines whether or not to draw a top border. +func (s Style) BorderTop(v bool) Style { + s.set(borderTopKey, v) + return s +} + +// BorderRight determines whether or not to draw a right border. +func (s Style) BorderRight(v bool) Style { + s.set(borderRightKey, v) + return s +} + +// BorderBottom determines whether or not to draw a bottom border. +func (s Style) BorderBottom(v bool) Style { + s.set(borderBottomKey, v) + return s +} + +// BorderLeft determines whether or not to draw a left border. +func (s Style) BorderLeft(v bool) Style { + s.set(borderLeftKey, v) + return s +} + +// BorderForeground is a shorthand function for setting all of the +// foreground colors of the borders at once. The arguments work as follows: +// +// With one argument, the argument is applied to all sides. +// +// With two arguments, the arguments are applied to the vertical and horizontal +// sides, in that order. +// +// With three arguments, the arguments are applied to the top side, the +// horizontal sides, and the bottom side, in that order. +// +// With four arguments, the arguments are applied clockwise starting from the +// top side, followed by the right side, then the bottom, and finally the left. +// +// With more than four arguments nothing will be set. +func (s Style) BorderForeground(c ...TerminalColor) Style { + if len(c) == 0 { + return s + } + + top, right, bottom, left, ok := whichSidesColor(c...) + if !ok { + return s + } + + s.set(borderTopForegroundKey, top) + s.set(borderRightForegroundKey, right) + s.set(borderBottomForegroundKey, bottom) + s.set(borderLeftForegroundKey, left) + + return s +} + +// BorderTopForeground set the foreground color for the top of the border. +func (s Style) BorderTopForeground(c TerminalColor) Style { + s.set(borderTopForegroundKey, c) + return s +} + +// BorderRightForeground sets the foreground color for the right side of the +// border. +func (s Style) BorderRightForeground(c TerminalColor) Style { + s.set(borderRightForegroundKey, c) + return s +} + +// BorderBottomForeground sets the foreground color for the bottom of the +// border. +func (s Style) BorderBottomForeground(c TerminalColor) Style { + s.set(borderBottomForegroundKey, c) + return s +} + +// BorderLeftForeground sets the foreground color for the left side of the +// border. +func (s Style) BorderLeftForeground(c TerminalColor) Style { + s.set(borderLeftForegroundKey, c) + return s +} + +// BorderBackground is a shorthand function for setting all of the +// background colors of the borders at once. The arguments work as follows: +// +// With one argument, the argument is applied to all sides. +// +// With two arguments, the arguments are applied to the vertical and horizontal +// sides, in that order. +// +// With three arguments, the arguments are applied to the top side, the +// horizontal sides, and the bottom side, in that order. +// +// With four arguments, the arguments are applied clockwise starting from the +// top side, followed by the right side, then the bottom, and finally the left. +// +// With more than four arguments nothing will be set. +func (s Style) BorderBackground(c ...TerminalColor) Style { + if len(c) == 0 { + return s + } + + top, right, bottom, left, ok := whichSidesColor(c...) + if !ok { + return s + } + + s.set(borderTopBackgroundKey, top) + s.set(borderRightBackgroundKey, right) + s.set(borderBottomBackgroundKey, bottom) + s.set(borderLeftBackgroundKey, left) + + return s +} + +// BorderTopBackground sets the background color of the top of the border. +func (s Style) BorderTopBackground(c TerminalColor) Style { + s.set(borderTopBackgroundKey, c) + return s +} + +// BorderRightBackground sets the background color of right side the border. +func (s Style) BorderRightBackground(c TerminalColor) Style { + s.set(borderRightBackgroundKey, c) + return s +} + +// BorderBottomBackground sets the background color of the bottom of the +// border. +func (s Style) BorderBottomBackground(c TerminalColor) Style { + s.set(borderBottomBackgroundKey, c) + return s +} + +// BorderLeftBackground set the background color of the left side of the +// border. +func (s Style) BorderLeftBackground(c TerminalColor) Style { + s.set(borderLeftBackgroundKey, c) + return s +} + +// Inline makes rendering output one line and disables the rendering of +// margins, padding and borders. This is useful when you need a style to apply +// only to font rendering and don't want it to change any physical dimensions. +// It works well with Style.MaxWidth. +// +// Because this in intended to be used at the time of render, this method will +// not mutate the style and instead return a copy. +// +// Example: +// +// var userInput string = "..." +// var userStyle = text.Style{ /* ... */ } +// fmt.Println(userStyle.Inline(true).Render(userInput)) +func (s Style) Inline(v bool) Style { + o := s // copy + o.set(inlineKey, v) + return o +} + +// MaxWidth applies a max width to a given style. This is useful in enforcing +// a certain width at render time, particularly with arbitrary strings and +// styles. +// +// Because this in intended to be used at the time of render, this method will +// not mutate the style and instead return a copy. +// +// Example: +// +// var userInput string = "..." +// var userStyle = text.Style{ /* ... */ } +// fmt.Println(userStyle.MaxWidth(16).Render(userInput)) +func (s Style) MaxWidth(n int) Style { + o := s // copy + o.set(maxWidthKey, n) + return o +} + +// MaxHeight applies a max height to a given style. This is useful in enforcing +// a certain height at render time, particularly with arbitrary strings and +// styles. +// +// Because this in intended to be used at the time of render, this method will +// not mutate the style and instead returns a copy. +func (s Style) MaxHeight(n int) Style { + o := s // copy + o.set(maxHeightKey, n) + return o +} + +// NoTabConversion can be passed to [Style.TabWidth] to disable the replacement +// of tabs with spaces at render time. +const NoTabConversion = -1 + +// TabWidth sets the number of spaces that a tab (/t) should be rendered as. +// When set to 0, tabs will be removed. To disable the replacement of tabs with +// spaces entirely, set this to [NoTabConversion]. +// +// By default, tabs will be replaced with 4 spaces. +func (s Style) TabWidth(n int) Style { + if n <= -1 { + n = -1 + } + s.set(tabWidthKey, n) + return s +} + +// UnderlineSpaces determines whether to underline spaces between words. By +// default, this is true. Spaces can also be underlined without underlining the +// text itself. +func (s Style) UnderlineSpaces(v bool) Style { + s.set(underlineSpacesKey, v) + return s +} + +// StrikethroughSpaces determines whether to apply strikethroughs to spaces +// between words. By default, this is true. Spaces can also be struck without +// underlining the text itself. +func (s Style) StrikethroughSpaces(v bool) Style { + s.set(strikethroughSpacesKey, v) + return s +} + +// Transform applies a given function to a string at render time, allowing for +// the string being rendered to be manipuated. +// +// Example: +// +// s := NewStyle().Transform(strings.ToUpper) +// fmt.Println(s.Render("raow!") // "RAOW!" +func (s Style) Transform(fn func(string) string) Style { + s.set(transformKey, fn) + return s +} + +// Renderer sets the renderer for the style. This is useful for changing the +// renderer for a style that is being used in a different context. +func (s Style) Renderer(r *Renderer) Style { + s.r = r + return s +} + +// whichSidesInt is a helper method for setting values on sides of a block based +// on the number of arguments. It follows the CSS shorthand rules for blocks +// like margin, padding. and borders. Here are how the rules work: +// +// 0 args: do nothing +// 1 arg: all sides +// 2 args: top -> bottom +// 3 args: top -> horizontal -> bottom +// 4 args: top -> right -> bottom -> left +// 5+ args: do nothing. +func whichSidesInt(i ...int) (top, right, bottom, left int, ok bool) { + switch len(i) { + case 1: + top = i[0] + bottom = i[0] + left = i[0] + right = i[0] + ok = true + case 2: //nolint:mnd + top = i[0] + bottom = i[0] + left = i[1] + right = i[1] + ok = true + case 3: //nolint:mnd + top = i[0] + left = i[1] + right = i[1] + bottom = i[2] + ok = true + case 4: //nolint:mnd + top = i[0] + right = i[1] + bottom = i[2] + left = i[3] + ok = true + } + return top, right, bottom, left, ok +} + +// whichSidesBool is like whichSidesInt, except it operates on a series of +// boolean values. See the comment on whichSidesInt for details on how this +// works. +func whichSidesBool(i ...bool) (top, right, bottom, left bool, ok bool) { + switch len(i) { + case 1: + top = i[0] + bottom = i[0] + left = i[0] + right = i[0] + ok = true + case 2: //nolint:mnd + top = i[0] + bottom = i[0] + left = i[1] + right = i[1] + ok = true + case 3: //nolint:mnd + top = i[0] + left = i[1] + right = i[1] + bottom = i[2] + ok = true + case 4: //nolint:mnd + top = i[0] + right = i[1] + bottom = i[2] + left = i[3] + ok = true + } + return top, right, bottom, left, ok +} + +// whichSidesColor is like whichSides, except it operates on a series of +// boolean values. See the comment on whichSidesInt for details on how this +// works. +func whichSidesColor(i ...TerminalColor) (top, right, bottom, left TerminalColor, ok bool) { + switch len(i) { + case 1: + top = i[0] + bottom = i[0] + left = i[0] + right = i[0] + ok = true + case 2: //nolint:mnd + top = i[0] + bottom = i[0] + left = i[1] + right = i[1] + ok = true + case 3: //nolint:mnd + top = i[0] + left = i[1] + right = i[1] + bottom = i[2] + ok = true + case 4: //nolint:mnd + top = i[0] + right = i[1] + bottom = i[2] + left = i[3] + ok = true + } + return top, right, bottom, left, ok +} diff --git a/vendor/github.com/charmbracelet/lipgloss/size.go b/vendor/github.com/charmbracelet/lipgloss/size.go new file mode 100644 index 00000000..e169ff5e --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/size.go @@ -0,0 +1,41 @@ +package lipgloss + +import ( + "strings" + + "github.com/charmbracelet/x/ansi" +) + +// Width returns the cell width of characters in the string. ANSI sequences are +// ignored and characters wider than one cell (such as Chinese characters and +// emojis) are appropriately measured. +// +// You should use this instead of len(string) len([]rune(string) as neither +// will give you accurate results. +func Width(str string) (width int) { + for _, l := range strings.Split(str, "\n") { + w := ansi.StringWidth(l) + if w > width { + width = w + } + } + + return width +} + +// Height returns height of a string in cells. This is done simply by +// counting \n characters. If your strings use \r\n for newlines you should +// convert them to \n first, or simply write a separate function for measuring +// height. +func Height(str string) int { + return strings.Count(str, "\n") + 1 +} + +// Size returns the width and height of the string in cells. ANSI sequences are +// ignored and characters wider than one cell (such as Chinese characters and +// emojis) are appropriately measured. +func Size(str string) (width, height int) { + width = Width(str) + height = Height(str) + return width, height +} diff --git a/vendor/github.com/charmbracelet/lipgloss/style.go b/vendor/github.com/charmbracelet/lipgloss/style.go new file mode 100644 index 00000000..59fa3ab2 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/style.go @@ -0,0 +1,588 @@ +package lipgloss + +import ( + "strings" + "unicode" + + "github.com/charmbracelet/x/ansi" + "github.com/charmbracelet/x/cellbuf" + "github.com/muesli/termenv" +) + +const tabWidthDefault = 4 + +// Property for a key. +type propKey int64 + +// Available properties. +const ( + // Boolean props come first. + boldKey propKey = 1 << iota + italicKey + underlineKey + strikethroughKey + reverseKey + blinkKey + faintKey + underlineSpacesKey + strikethroughSpacesKey + colorWhitespaceKey + + // Non-boolean props. + foregroundKey + backgroundKey + widthKey + heightKey + alignHorizontalKey + alignVerticalKey + + // Padding. + paddingTopKey + paddingRightKey + paddingBottomKey + paddingLeftKey + + // Margins. + marginTopKey + marginRightKey + marginBottomKey + marginLeftKey + marginBackgroundKey + + // Border runes. + borderStyleKey + + // Border edges. + borderTopKey + borderRightKey + borderBottomKey + borderLeftKey + + // Border foreground colors. + borderTopForegroundKey + borderRightForegroundKey + borderBottomForegroundKey + borderLeftForegroundKey + + // Border background colors. + borderTopBackgroundKey + borderRightBackgroundKey + borderBottomBackgroundKey + borderLeftBackgroundKey + + inlineKey + maxWidthKey + maxHeightKey + tabWidthKey + + transformKey +) + +// props is a set of properties. +type props int64 + +// set sets a property. +func (p props) set(k propKey) props { + return p | props(k) +} + +// unset unsets a property. +func (p props) unset(k propKey) props { + return p &^ props(k) +} + +// has checks if a property is set. +func (p props) has(k propKey) bool { + return p&props(k) != 0 +} + +// NewStyle returns a new, empty Style. While it's syntactic sugar for the +// Style{} primitive, it's recommended to use this function for creating styles +// in case the underlying implementation changes. It takes an optional string +// value to be set as the underlying string value for this style. +func NewStyle() Style { + return renderer.NewStyle() +} + +// NewStyle returns a new, empty Style. While it's syntactic sugar for the +// Style{} primitive, it's recommended to use this function for creating styles +// in case the underlying implementation changes. It takes an optional string +// value to be set as the underlying string value for this style. +func (r *Renderer) NewStyle() Style { + s := Style{r: r} + return s +} + +// Style contains a set of rules that comprise a style as a whole. +type Style struct { + r *Renderer + props props + value string + + // we store bool props values here + attrs int + + // props that have values + fgColor TerminalColor + bgColor TerminalColor + + width int + height int + + alignHorizontal Position + alignVertical Position + + paddingTop int + paddingRight int + paddingBottom int + paddingLeft int + + marginTop int + marginRight int + marginBottom int + marginLeft int + marginBgColor TerminalColor + + borderStyle Border + borderTopFgColor TerminalColor + borderRightFgColor TerminalColor + borderBottomFgColor TerminalColor + borderLeftFgColor TerminalColor + borderTopBgColor TerminalColor + borderRightBgColor TerminalColor + borderBottomBgColor TerminalColor + borderLeftBgColor TerminalColor + + maxWidth int + maxHeight int + tabWidth int + + transform func(string) string +} + +// joinString joins a list of strings into a single string separated with a +// space. +func joinString(strs ...string) string { + return strings.Join(strs, " ") +} + +// SetString sets the underlying string value for this style. To render once +// the underlying string is set, use the Style.String. This method is +// a convenience for cases when having a stringer implementation is handy, such +// as when using fmt.Sprintf. You can also simply define a style and render out +// strings directly with Style.Render. +func (s Style) SetString(strs ...string) Style { + s.value = joinString(strs...) + return s +} + +// Value returns the raw, unformatted, underlying string value for this style. +func (s Style) Value() string { + return s.value +} + +// String implements stringer for a Style, returning the rendered result based +// on the rules in this style. An underlying string value must be set with +// Style.SetString prior to using this method. +func (s Style) String() string { + return s.Render() +} + +// Copy returns a copy of this style, including any underlying string values. +// +// Deprecated: to copy just use assignment (i.e. a := b). All methods also +// return a new style. +func (s Style) Copy() Style { + return s +} + +// Inherit overlays the style in the argument onto this style by copying each explicitly +// set value from the argument style onto this style if it is not already explicitly set. +// Existing set values are kept intact and not overwritten. +// +// Margins, padding, and underlying string values are not inherited. +func (s Style) Inherit(i Style) Style { + for k := boldKey; k <= transformKey; k <<= 1 { + if !i.isSet(k) { + continue + } + + switch k { //nolint:exhaustive + case marginTopKey, marginRightKey, marginBottomKey, marginLeftKey: + // Margins are not inherited + continue + case paddingTopKey, paddingRightKey, paddingBottomKey, paddingLeftKey: + // Padding is not inherited + continue + case backgroundKey: + // The margins also inherit the background color + if !s.isSet(marginBackgroundKey) && !i.isSet(marginBackgroundKey) { + s.set(marginBackgroundKey, i.bgColor) + } + } + + if s.isSet(k) { + continue + } + + s.setFrom(k, i) + } + return s +} + +// Render applies the defined style formatting to a given string. +func (s Style) Render(strs ...string) string { + if s.r == nil { + s.r = renderer + } + if s.value != "" { + strs = append([]string{s.value}, strs...) + } + + var ( + str = joinString(strs...) + + p = s.r.ColorProfile() + te = p.String() + teSpace = p.String() + teWhitespace = p.String() + + bold = s.getAsBool(boldKey, false) + italic = s.getAsBool(italicKey, false) + underline = s.getAsBool(underlineKey, false) + strikethrough = s.getAsBool(strikethroughKey, false) + reverse = s.getAsBool(reverseKey, false) + blink = s.getAsBool(blinkKey, false) + faint = s.getAsBool(faintKey, false) + + fg = s.getAsColor(foregroundKey) + bg = s.getAsColor(backgroundKey) + + width = s.getAsInt(widthKey) + height = s.getAsInt(heightKey) + horizontalAlign = s.getAsPosition(alignHorizontalKey) + verticalAlign = s.getAsPosition(alignVerticalKey) + + topPadding = s.getAsInt(paddingTopKey) + rightPadding = s.getAsInt(paddingRightKey) + bottomPadding = s.getAsInt(paddingBottomKey) + leftPadding = s.getAsInt(paddingLeftKey) + + colorWhitespace = s.getAsBool(colorWhitespaceKey, true) + inline = s.getAsBool(inlineKey, false) + maxWidth = s.getAsInt(maxWidthKey) + maxHeight = s.getAsInt(maxHeightKey) + + underlineSpaces = s.getAsBool(underlineSpacesKey, false) || (underline && s.getAsBool(underlineSpacesKey, true)) + strikethroughSpaces = s.getAsBool(strikethroughSpacesKey, false) || (strikethrough && s.getAsBool(strikethroughSpacesKey, true)) + + // Do we need to style whitespace (padding and space outside + // paragraphs) separately? + styleWhitespace = reverse + + // Do we need to style spaces separately? + useSpaceStyler = (underline && !underlineSpaces) || (strikethrough && !strikethroughSpaces) || underlineSpaces || strikethroughSpaces + + transform = s.getAsTransform(transformKey) + ) + + if transform != nil { + str = transform(str) + } + + if s.props == 0 { + return s.maybeConvertTabs(str) + } + + // Enable support for ANSI on the legacy Windows cmd.exe console. This is a + // no-op on non-Windows systems and on Windows runs only once. + enableLegacyWindowsANSI() + + if bold { + te = te.Bold() + } + if italic { + te = te.Italic() + } + if underline { + te = te.Underline() + } + if reverse { + teWhitespace = teWhitespace.Reverse() + te = te.Reverse() + } + if blink { + te = te.Blink() + } + if faint { + te = te.Faint() + } + + if fg != noColor { + te = te.Foreground(fg.color(s.r)) + if styleWhitespace { + teWhitespace = teWhitespace.Foreground(fg.color(s.r)) + } + if useSpaceStyler { + teSpace = teSpace.Foreground(fg.color(s.r)) + } + } + + if bg != noColor { + te = te.Background(bg.color(s.r)) + if colorWhitespace { + teWhitespace = teWhitespace.Background(bg.color(s.r)) + } + if useSpaceStyler { + teSpace = teSpace.Background(bg.color(s.r)) + } + } + + if underline { + te = te.Underline() + } + if strikethrough { + te = te.CrossOut() + } + + if underlineSpaces { + teSpace = teSpace.Underline() + } + if strikethroughSpaces { + teSpace = teSpace.CrossOut() + } + + // Potentially convert tabs to spaces + str = s.maybeConvertTabs(str) + // carriage returns can cause strange behaviour when rendering. + str = strings.ReplaceAll(str, "\r\n", "\n") + + // Strip newlines in single line mode + if inline { + str = strings.ReplaceAll(str, "\n", "") + } + + // Word wrap + if !inline && width > 0 { + wrapAt := width - leftPadding - rightPadding + str = cellbuf.Wrap(str, wrapAt, "") + } + + // Render core text + { + var b strings.Builder + + l := strings.Split(str, "\n") + for i := range l { + if useSpaceStyler { + // Look for spaces and apply a different styler + for _, r := range l[i] { + if unicode.IsSpace(r) { + b.WriteString(teSpace.Styled(string(r))) + continue + } + b.WriteString(te.Styled(string(r))) + } + } else { + b.WriteString(te.Styled(l[i])) + } + if i != len(l)-1 { + b.WriteRune('\n') + } + } + + str = b.String() + } + + // Padding + if !inline { //nolint:nestif + if leftPadding > 0 { + var st *termenv.Style + if colorWhitespace || styleWhitespace { + st = &teWhitespace + } + str = padLeft(str, leftPadding, st) + } + + if rightPadding > 0 { + var st *termenv.Style + if colorWhitespace || styleWhitespace { + st = &teWhitespace + } + str = padRight(str, rightPadding, st) + } + + if topPadding > 0 { + str = strings.Repeat("\n", topPadding) + str + } + + if bottomPadding > 0 { + str += strings.Repeat("\n", bottomPadding) + } + } + + // Height + if height > 0 { + str = alignTextVertical(str, verticalAlign, height, nil) + } + + // Set alignment. This will also pad short lines with spaces so that all + // lines are the same length, so we run it under a few different conditions + // beyond alignment. + { + numLines := strings.Count(str, "\n") + + if numLines != 0 || width != 0 { + var st *termenv.Style + if colorWhitespace || styleWhitespace { + st = &teWhitespace + } + str = alignTextHorizontal(str, horizontalAlign, width, st) + } + } + + if !inline { + str = s.applyBorder(str) + str = s.applyMargins(str, inline) + } + + // Truncate according to MaxWidth + if maxWidth > 0 { + lines := strings.Split(str, "\n") + + for i := range lines { + lines[i] = ansi.Truncate(lines[i], maxWidth, "") + } + + str = strings.Join(lines, "\n") + } + + // Truncate according to MaxHeight + if maxHeight > 0 { + lines := strings.Split(str, "\n") + height := min(maxHeight, len(lines)) + if len(lines) > 0 { + str = strings.Join(lines[:height], "\n") + } + } + + return str +} + +func (s Style) maybeConvertTabs(str string) string { + tw := tabWidthDefault + if s.isSet(tabWidthKey) { + tw = s.getAsInt(tabWidthKey) + } + switch tw { + case -1: + return str + case 0: + return strings.ReplaceAll(str, "\t", "") + default: + return strings.ReplaceAll(str, "\t", strings.Repeat(" ", tw)) + } +} + +func (s Style) applyMargins(str string, inline bool) string { + var ( + topMargin = s.getAsInt(marginTopKey) + rightMargin = s.getAsInt(marginRightKey) + bottomMargin = s.getAsInt(marginBottomKey) + leftMargin = s.getAsInt(marginLeftKey) + + styler termenv.Style + ) + + bgc := s.getAsColor(marginBackgroundKey) + if bgc != noColor { + styler = styler.Background(bgc.color(s.r)) + } + + // Add left and right margin + str = padLeft(str, leftMargin, &styler) + str = padRight(str, rightMargin, &styler) + + // Top/bottom margin + if !inline { + _, width := getLines(str) + spaces := strings.Repeat(" ", width) + + if topMargin > 0 { + str = styler.Styled(strings.Repeat(spaces+"\n", topMargin)) + str + } + if bottomMargin > 0 { + str += styler.Styled(strings.Repeat("\n"+spaces, bottomMargin)) + } + } + + return str +} + +// Apply left padding. +func padLeft(str string, n int, style *termenv.Style) string { + return pad(str, -n, style) +} + +// Apply right padding. +func padRight(str string, n int, style *termenv.Style) string { + return pad(str, n, style) +} + +// pad adds padding to either the left or right side of a string. +// Positive values add to the right side while negative values +// add to the left side. +func pad(str string, n int, style *termenv.Style) string { + if n == 0 { + return str + } + + sp := strings.Repeat(" ", abs(n)) + if style != nil { + sp = style.Styled(sp) + } + + b := strings.Builder{} + l := strings.Split(str, "\n") + + for i := range l { + switch { + // pad right + case n > 0: + b.WriteString(l[i]) + b.WriteString(sp) + // pad left + default: + b.WriteString(sp) + b.WriteString(l[i]) + } + + if i != len(l)-1 { + b.WriteRune('\n') + } + } + + return b.String() +} + +func max(a, b int) int { //nolint:unparam,predeclared + if a > b { + return a + } + return b +} + +func min(a, b int) int { //nolint:predeclared + if a < b { + return a + } + return b +} + +func abs(a int) int { + if a < 0 { + return -a + } + + return a +} diff --git a/vendor/github.com/charmbracelet/lipgloss/unset.go b/vendor/github.com/charmbracelet/lipgloss/unset.go new file mode 100644 index 00000000..1086e722 --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/unset.go @@ -0,0 +1,331 @@ +package lipgloss + +// unset unsets a property from a style. +func (s *Style) unset(key propKey) { + s.props = s.props.unset(key) +} + +// UnsetBold removes the bold style rule, if set. +func (s Style) UnsetBold() Style { + s.unset(boldKey) + return s +} + +// UnsetItalic removes the italic style rule, if set. +func (s Style) UnsetItalic() Style { + s.unset(italicKey) + return s +} + +// UnsetUnderline removes the underline style rule, if set. +func (s Style) UnsetUnderline() Style { + s.unset(underlineKey) + return s +} + +// UnsetStrikethrough removes the strikethrough style rule, if set. +func (s Style) UnsetStrikethrough() Style { + s.unset(strikethroughKey) + return s +} + +// UnsetReverse removes the reverse style rule, if set. +func (s Style) UnsetReverse() Style { + s.unset(reverseKey) + return s +} + +// UnsetBlink removes the blink style rule, if set. +func (s Style) UnsetBlink() Style { + s.unset(blinkKey) + return s +} + +// UnsetFaint removes the faint style rule, if set. +func (s Style) UnsetFaint() Style { + s.unset(faintKey) + return s +} + +// UnsetForeground removes the foreground style rule, if set. +func (s Style) UnsetForeground() Style { + s.unset(foregroundKey) + return s +} + +// UnsetBackground removes the background style rule, if set. +func (s Style) UnsetBackground() Style { + s.unset(backgroundKey) + return s +} + +// UnsetWidth removes the width style rule, if set. +func (s Style) UnsetWidth() Style { + s.unset(widthKey) + return s +} + +// UnsetHeight removes the height style rule, if set. +func (s Style) UnsetHeight() Style { + s.unset(heightKey) + return s +} + +// UnsetAlign removes the horizontal and vertical text alignment style rule, if set. +func (s Style) UnsetAlign() Style { + s.unset(alignHorizontalKey) + s.unset(alignVerticalKey) + return s +} + +// UnsetAlignHorizontal removes the horizontal text alignment style rule, if set. +func (s Style) UnsetAlignHorizontal() Style { + s.unset(alignHorizontalKey) + return s +} + +// UnsetAlignVertical removes the vertical text alignment style rule, if set. +func (s Style) UnsetAlignVertical() Style { + s.unset(alignVerticalKey) + return s +} + +// UnsetPadding removes all padding style rules. +func (s Style) UnsetPadding() Style { + s.unset(paddingLeftKey) + s.unset(paddingRightKey) + s.unset(paddingTopKey) + s.unset(paddingBottomKey) + return s +} + +// UnsetPaddingLeft removes the left padding style rule, if set. +func (s Style) UnsetPaddingLeft() Style { + s.unset(paddingLeftKey) + return s +} + +// UnsetPaddingRight removes the right padding style rule, if set. +func (s Style) UnsetPaddingRight() Style { + s.unset(paddingRightKey) + return s +} + +// UnsetPaddingTop removes the top padding style rule, if set. +func (s Style) UnsetPaddingTop() Style { + s.unset(paddingTopKey) + return s +} + +// UnsetPaddingBottom removes the bottom padding style rule, if set. +func (s Style) UnsetPaddingBottom() Style { + s.unset(paddingBottomKey) + return s +} + +// UnsetColorWhitespace removes the rule for coloring padding, if set. +func (s Style) UnsetColorWhitespace() Style { + s.unset(colorWhitespaceKey) + return s +} + +// UnsetMargins removes all margin style rules. +func (s Style) UnsetMargins() Style { + s.unset(marginLeftKey) + s.unset(marginRightKey) + s.unset(marginTopKey) + s.unset(marginBottomKey) + return s +} + +// UnsetMarginLeft removes the left margin style rule, if set. +func (s Style) UnsetMarginLeft() Style { + s.unset(marginLeftKey) + return s +} + +// UnsetMarginRight removes the right margin style rule, if set. +func (s Style) UnsetMarginRight() Style { + s.unset(marginRightKey) + return s +} + +// UnsetMarginTop removes the top margin style rule, if set. +func (s Style) UnsetMarginTop() Style { + s.unset(marginTopKey) + return s +} + +// UnsetMarginBottom removes the bottom margin style rule, if set. +func (s Style) UnsetMarginBottom() Style { + s.unset(marginBottomKey) + return s +} + +// UnsetMarginBackground removes the margin's background color. Note that the +// margin's background color can be set from the background color of another +// style during inheritance. +func (s Style) UnsetMarginBackground() Style { + s.unset(marginBackgroundKey) + return s +} + +// UnsetBorderStyle removes the border style rule, if set. +func (s Style) UnsetBorderStyle() Style { + s.unset(borderStyleKey) + return s +} + +// UnsetBorderTop removes the border top style rule, if set. +func (s Style) UnsetBorderTop() Style { + s.unset(borderTopKey) + return s +} + +// UnsetBorderRight removes the border right style rule, if set. +func (s Style) UnsetBorderRight() Style { + s.unset(borderRightKey) + return s +} + +// UnsetBorderBottom removes the border bottom style rule, if set. +func (s Style) UnsetBorderBottom() Style { + s.unset(borderBottomKey) + return s +} + +// UnsetBorderLeft removes the border left style rule, if set. +func (s Style) UnsetBorderLeft() Style { + s.unset(borderLeftKey) + return s +} + +// UnsetBorderForeground removes all border foreground color styles, if set. +func (s Style) UnsetBorderForeground() Style { + s.unset(borderTopForegroundKey) + s.unset(borderRightForegroundKey) + s.unset(borderBottomForegroundKey) + s.unset(borderLeftForegroundKey) + return s +} + +// UnsetBorderTopForeground removes the top border foreground color rule, +// if set. +func (s Style) UnsetBorderTopForeground() Style { + s.unset(borderTopForegroundKey) + return s +} + +// UnsetBorderRightForeground removes the right border foreground color rule, +// if set. +func (s Style) UnsetBorderRightForeground() Style { + s.unset(borderRightForegroundKey) + return s +} + +// UnsetBorderBottomForeground removes the bottom border foreground color +// rule, if set. +func (s Style) UnsetBorderBottomForeground() Style { + s.unset(borderBottomForegroundKey) + return s +} + +// UnsetBorderLeftForeground removes the left border foreground color rule, +// if set. +func (s Style) UnsetBorderLeftForeground() Style { + s.unset(borderLeftForegroundKey) + return s +} + +// UnsetBorderBackground removes all border background color styles, if +// set. +func (s Style) UnsetBorderBackground() Style { + s.unset(borderTopBackgroundKey) + s.unset(borderRightBackgroundKey) + s.unset(borderBottomBackgroundKey) + s.unset(borderLeftBackgroundKey) + return s +} + +// UnsetBorderTopBackgroundColor removes the top border background color rule, +// if set. +// +// Deprecated: This function simply calls Style.UnsetBorderTopBackground. +func (s Style) UnsetBorderTopBackgroundColor() Style { + return s.UnsetBorderTopBackground() +} + +// UnsetBorderTopBackground removes the top border background color rule, +// if set. +func (s Style) UnsetBorderTopBackground() Style { + s.unset(borderTopBackgroundKey) + return s +} + +// UnsetBorderRightBackground removes the right border background color +// rule, if set. +func (s Style) UnsetBorderRightBackground() Style { + s.unset(borderRightBackgroundKey) + return s +} + +// UnsetBorderBottomBackground removes the bottom border background color +// rule, if set. +func (s Style) UnsetBorderBottomBackground() Style { + s.unset(borderBottomBackgroundKey) + return s +} + +// UnsetBorderLeftBackground removes the left border color rule, if set. +func (s Style) UnsetBorderLeftBackground() Style { + s.unset(borderLeftBackgroundKey) + return s +} + +// UnsetInline removes the inline style rule, if set. +func (s Style) UnsetInline() Style { + s.unset(inlineKey) + return s +} + +// UnsetMaxWidth removes the max width style rule, if set. +func (s Style) UnsetMaxWidth() Style { + s.unset(maxWidthKey) + return s +} + +// UnsetMaxHeight removes the max height style rule, if set. +func (s Style) UnsetMaxHeight() Style { + s.unset(maxHeightKey) + return s +} + +// UnsetTabWidth removes the tab width style rule, if set. +func (s Style) UnsetTabWidth() Style { + s.unset(tabWidthKey) + return s +} + +// UnsetUnderlineSpaces removes the value set by UnderlineSpaces. +func (s Style) UnsetUnderlineSpaces() Style { + s.unset(underlineSpacesKey) + return s +} + +// UnsetStrikethroughSpaces removes the value set by StrikethroughSpaces. +func (s Style) UnsetStrikethroughSpaces() Style { + s.unset(strikethroughSpacesKey) + return s +} + +// UnsetTransform removes the value set by Transform. +func (s Style) UnsetTransform() Style { + s.unset(transformKey) + return s +} + +// UnsetString sets the underlying string value to the empty string. +func (s Style) UnsetString() Style { + s.value = "" + return s +} diff --git a/vendor/github.com/charmbracelet/lipgloss/whitespace.go b/vendor/github.com/charmbracelet/lipgloss/whitespace.go new file mode 100644 index 00000000..040dc98e --- /dev/null +++ b/vendor/github.com/charmbracelet/lipgloss/whitespace.go @@ -0,0 +1,83 @@ +package lipgloss + +import ( + "strings" + + "github.com/charmbracelet/x/ansi" + "github.com/muesli/termenv" +) + +// whitespace is a whitespace renderer. +type whitespace struct { + re *Renderer + style termenv.Style + chars string +} + +// newWhitespace creates a new whitespace renderer. The order of the options +// matters, if you're using WithWhitespaceRenderer, make sure it comes first as +// other options might depend on it. +func newWhitespace(r *Renderer, opts ...WhitespaceOption) *whitespace { + w := &whitespace{ + re: r, + style: r.ColorProfile().String(), + } + for _, opt := range opts { + opt(w) + } + return w +} + +// Render whitespaces. +func (w whitespace) render(width int) string { + if w.chars == "" { + w.chars = " " + } + + r := []rune(w.chars) + j := 0 + b := strings.Builder{} + + // Cycle through runes and print them into the whitespace. + for i := 0; i < width; { + b.WriteRune(r[j]) + j++ + if j >= len(r) { + j = 0 + } + i += ansi.StringWidth(string(r[j])) + } + + // Fill any extra gaps white spaces. This might be necessary if any runes + // are more than one cell wide, which could leave a one-rune gap. + short := width - ansi.StringWidth(b.String()) + if short > 0 { + b.WriteString(strings.Repeat(" ", short)) + } + + return w.style.Styled(b.String()) +} + +// WhitespaceOption sets a styling rule for rendering whitespace. +type WhitespaceOption func(*whitespace) + +// WithWhitespaceForeground sets the color of the characters in the whitespace. +func WithWhitespaceForeground(c TerminalColor) WhitespaceOption { + return func(w *whitespace) { + w.style = w.style.Foreground(c.color(w.re)) + } +} + +// WithWhitespaceBackground sets the background color of the whitespace. +func WithWhitespaceBackground(c TerminalColor) WhitespaceOption { + return func(w *whitespace) { + w.style = w.style.Background(c.color(w.re)) + } +} + +// WithWhitespaceChars sets the characters to be rendered in the whitespace. +func WithWhitespaceChars(s string) WhitespaceOption { + return func(w *whitespace) { + w.chars = s + } +} diff --git a/vendor/github.com/charmbracelet/x/ansi/LICENSE b/vendor/github.com/charmbracelet/x/ansi/LICENSE new file mode 100644 index 00000000..65a5654e --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Charmbracelet, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/charmbracelet/x/ansi/ansi.go b/vendor/github.com/charmbracelet/x/ansi/ansi.go new file mode 100644 index 00000000..48d873c3 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/ansi.go @@ -0,0 +1,11 @@ +package ansi + +import "io" + +// Execute is a function that "execute" the given escape sequence by writing it +// to the provided output writter. +// +// This is a syntactic sugar over [io.WriteString]. +func Execute(w io.Writer, s string) (int, error) { + return io.WriteString(w, s) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/ascii.go b/vendor/github.com/charmbracelet/x/ansi/ascii.go new file mode 100644 index 00000000..188582f7 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/ascii.go @@ -0,0 +1,8 @@ +package ansi + +const ( + // SP is the space character (Char: \x20). + SP = 0x20 + // DEL is the delete character (Caret: ^?, Char: \x7f). + DEL = 0x7F +) diff --git a/vendor/github.com/charmbracelet/x/ansi/background.go b/vendor/github.com/charmbracelet/x/ansi/background.go new file mode 100644 index 00000000..46f82142 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/background.go @@ -0,0 +1,178 @@ +package ansi + +import ( + "fmt" + "image/color" + + "github.com/lucasb-eyer/go-colorful" +) + +// HexColor is a [color.Color] that can be formatted as a hex string. +type HexColor string + +// RGBA returns the RGBA values of the color. +func (h HexColor) RGBA() (r, g, b, a uint32) { + hex := h.color() + if hex == nil { + return 0, 0, 0, 0 + } + return hex.RGBA() +} + +// Hex returns the hex representation of the color. If the color is invalid, it +// returns an empty string. +func (h HexColor) Hex() string { + hex := h.color() + if hex == nil { + return "" + } + return hex.Hex() +} + +// String returns the color as a hex string. If the color is nil, an empty +// string is returned. +func (h HexColor) String() string { + return h.Hex() +} + +// color returns the underlying color of the HexColor. +func (h HexColor) color() *colorful.Color { + hex, err := colorful.Hex(string(h)) + if err != nil { + return nil + } + return &hex +} + +// XRGBColor is a [color.Color] that can be formatted as an XParseColor +// rgb: string. +// +// See: https://linux.die.net/man/3/xparsecolor +type XRGBColor struct { + color.Color +} + +// RGBA returns the RGBA values of the color. +func (x XRGBColor) RGBA() (r, g, b, a uint32) { + if x.Color == nil { + return 0, 0, 0, 0 + } + return x.Color.RGBA() +} + +// String returns the color as an XParseColor rgb: string. If the color is nil, +// an empty string is returned. +func (x XRGBColor) String() string { + if x.Color == nil { + return "" + } + r, g, b, _ := x.Color.RGBA() + // Get the lower 8 bits + return fmt.Sprintf("rgb:%04x/%04x/%04x", r, g, b) +} + +// XRGBAColor is a [color.Color] that can be formatted as an XParseColor +// rgba: string. +// +// See: https://linux.die.net/man/3/xparsecolor +type XRGBAColor struct { + color.Color +} + +// RGBA returns the RGBA values of the color. +func (x XRGBAColor) RGBA() (r, g, b, a uint32) { + if x.Color == nil { + return 0, 0, 0, 0 + } + return x.Color.RGBA() +} + +// String returns the color as an XParseColor rgba: string. If the color is nil, +// an empty string is returned. +func (x XRGBAColor) String() string { + if x.Color == nil { + return "" + } + r, g, b, a := x.RGBA() + // Get the lower 8 bits + return fmt.Sprintf("rgba:%04x/%04x/%04x/%04x", r, g, b, a) +} + +// SetForegroundColor returns a sequence that sets the default terminal +// foreground color. +// +// OSC 10 ; color ST +// OSC 10 ; color BEL +// +// Where color is the encoded color number. Most terminals support hex, +// XParseColor rgb: and rgba: strings. You could use [HexColor], [XRGBColor], +// or [XRGBAColor] to format the color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +func SetForegroundColor(s string) string { + return "\x1b]10;" + s + "\x07" +} + +// RequestForegroundColor is a sequence that requests the current default +// terminal foreground color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +const RequestForegroundColor = "\x1b]10;?\x07" + +// ResetForegroundColor is a sequence that resets the default terminal +// foreground color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +const ResetForegroundColor = "\x1b]110\x07" + +// SetBackgroundColor returns a sequence that sets the default terminal +// background color. +// +// OSC 11 ; color ST +// OSC 11 ; color BEL +// +// Where color is the encoded color number. Most terminals support hex, +// XParseColor rgb: and rgba: strings. You could use [HexColor], [XRGBColor], +// or [XRGBAColor] to format the color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +func SetBackgroundColor(s string) string { + return "\x1b]11;" + s + "\x07" +} + +// RequestBackgroundColor is a sequence that requests the current default +// terminal background color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +const RequestBackgroundColor = "\x1b]11;?\x07" + +// ResetBackgroundColor is a sequence that resets the default terminal +// background color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +const ResetBackgroundColor = "\x1b]111\x07" + +// SetCursorColor returns a sequence that sets the terminal cursor color. +// +// OSC 12 ; color ST +// OSC 12 ; color BEL +// +// Where color is the encoded color number. Most terminals support hex, +// XParseColor rgb: and rgba: strings. You could use [HexColor], [XRGBColor], +// or [XRGBAColor] to format the color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +func SetCursorColor(s string) string { + return "\x1b]12;" + s + "\x07" +} + +// RequestCursorColor is a sequence that requests the current terminal cursor +// color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +const RequestCursorColor = "\x1b]12;?\x07" + +// ResetCursorColor is a sequence that resets the terminal cursor color. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +const ResetCursorColor = "\x1b]112\x07" diff --git a/vendor/github.com/charmbracelet/x/ansi/c0.go b/vendor/github.com/charmbracelet/x/ansi/c0.go new file mode 100644 index 00000000..28ff7c2a --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/c0.go @@ -0,0 +1,79 @@ +package ansi + +// C0 control characters. +// +// These range from (0x00-0x1F) as defined in ISO 646 (ASCII). +// See: https://en.wikipedia.org/wiki/C0_and_C1_control_codes +const ( + // NUL is the null character (Caret: ^@, Char: \0). + NUL = 0x00 + // SOH is the start of heading character (Caret: ^A). + SOH = 0x01 + // STX is the start of text character (Caret: ^B). + STX = 0x02 + // ETX is the end of text character (Caret: ^C). + ETX = 0x03 + // EOT is the end of transmission character (Caret: ^D). + EOT = 0x04 + // ENQ is the enquiry character (Caret: ^E). + ENQ = 0x05 + // ACK is the acknowledge character (Caret: ^F). + ACK = 0x06 + // BEL is the bell character (Caret: ^G, Char: \a). + BEL = 0x07 + // BS is the backspace character (Caret: ^H, Char: \b). + BS = 0x08 + // HT is the horizontal tab character (Caret: ^I, Char: \t). + HT = 0x09 + // LF is the line feed character (Caret: ^J, Char: \n). + LF = 0x0A + // VT is the vertical tab character (Caret: ^K, Char: \v). + VT = 0x0B + // FF is the form feed character (Caret: ^L, Char: \f). + FF = 0x0C + // CR is the carriage return character (Caret: ^M, Char: \r). + CR = 0x0D + // SO is the shift out character (Caret: ^N). + SO = 0x0E + // SI is the shift in character (Caret: ^O). + SI = 0x0F + // DLE is the data link escape character (Caret: ^P). + DLE = 0x10 + // DC1 is the device control 1 character (Caret: ^Q). + DC1 = 0x11 + // DC2 is the device control 2 character (Caret: ^R). + DC2 = 0x12 + // DC3 is the device control 3 character (Caret: ^S). + DC3 = 0x13 + // DC4 is the device control 4 character (Caret: ^T). + DC4 = 0x14 + // NAK is the negative acknowledge character (Caret: ^U). + NAK = 0x15 + // SYN is the synchronous idle character (Caret: ^V). + SYN = 0x16 + // ETB is the end of transmission block character (Caret: ^W). + ETB = 0x17 + // CAN is the cancel character (Caret: ^X). + CAN = 0x18 + // EM is the end of medium character (Caret: ^Y). + EM = 0x19 + // SUB is the substitute character (Caret: ^Z). + SUB = 0x1A + // ESC is the escape character (Caret: ^[, Char: \e). + ESC = 0x1B + // FS is the file separator character (Caret: ^\). + FS = 0x1C + // GS is the group separator character (Caret: ^]). + GS = 0x1D + // RS is the record separator character (Caret: ^^). + RS = 0x1E + // US is the unit separator character (Caret: ^_). + US = 0x1F + + // LS0 is the locking shift 0 character. + // This is an alias for [SI]. + LS0 = SI + // LS1 is the locking shift 1 character. + // This is an alias for [SO]. + LS1 = SO +) diff --git a/vendor/github.com/charmbracelet/x/ansi/c1.go b/vendor/github.com/charmbracelet/x/ansi/c1.go new file mode 100644 index 00000000..71058f53 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/c1.go @@ -0,0 +1,72 @@ +package ansi + +// C1 control characters. +// +// These range from (0x80-0x9F) as defined in ISO 6429 (ECMA-48). +// See: https://en.wikipedia.org/wiki/C0_and_C1_control_codes +const ( + // PAD is the padding character. + PAD = 0x80 + // HOP is the high octet preset character. + HOP = 0x81 + // BPH is the break permitted here character. + BPH = 0x82 + // NBH is the no break here character. + NBH = 0x83 + // IND is the index character. + IND = 0x84 + // NEL is the next line character. + NEL = 0x85 + // SSA is the start of selected area character. + SSA = 0x86 + // ESA is the end of selected area character. + ESA = 0x87 + // HTS is the horizontal tab set character. + HTS = 0x88 + // HTJ is the horizontal tab with justification character. + HTJ = 0x89 + // VTS is the vertical tab set character. + VTS = 0x8A + // PLD is the partial line forward character. + PLD = 0x8B + // PLU is the partial line backward character. + PLU = 0x8C + // RI is the reverse index character. + RI = 0x8D + // SS2 is the single shift 2 character. + SS2 = 0x8E + // SS3 is the single shift 3 character. + SS3 = 0x8F + // DCS is the device control string character. + DCS = 0x90 + // PU1 is the private use 1 character. + PU1 = 0x91 + // PU2 is the private use 2 character. + PU2 = 0x92 + // STS is the set transmit state character. + STS = 0x93 + // CCH is the cancel character. + CCH = 0x94 + // MW is the message waiting character. + MW = 0x95 + // SPA is the start of guarded area character. + SPA = 0x96 + // EPA is the end of guarded area character. + EPA = 0x97 + // SOS is the start of string character. + SOS = 0x98 + // SGCI is the single graphic character introducer character. + SGCI = 0x99 + // SCI is the single character introducer character. + SCI = 0x9A + // CSI is the control sequence introducer character. + CSI = 0x9B + // ST is the string terminator character. + ST = 0x9C + // OSC is the operating system command character. + OSC = 0x9D + // PM is the privacy message character. + PM = 0x9E + // APC is the application program command character. + APC = 0x9F +) diff --git a/vendor/github.com/charmbracelet/x/ansi/charset.go b/vendor/github.com/charmbracelet/x/ansi/charset.go new file mode 100644 index 00000000..50fff51f --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/charset.go @@ -0,0 +1,55 @@ +package ansi + +// SelectCharacterSet sets the G-set character designator to the specified +// character set. +// +// ESC Ps Pd +// +// Where Ps is the G-set character designator, and Pd is the identifier. +// For 94-character sets, the designator can be one of: +// - ( G0 +// - ) G1 +// - * G2 +// - + G3 +// +// For 96-character sets, the designator can be one of: +// - - G1 +// - . G2 +// - / G3 +// +// Some common 94-character sets are: +// - 0 DEC Special Drawing Set +// - A United Kingdom (UK) +// - B United States (USASCII) +// +// Examples: +// +// ESC ( B Select character set G0 = United States (USASCII) +// ESC ( 0 Select character set G0 = Special Character and Line Drawing Set +// ESC ) 0 Select character set G1 = Special Character and Line Drawing Set +// ESC * A Select character set G2 = United Kingdom (UK) +// +// See: https://vt100.net/docs/vt510-rm/SCS.html +func SelectCharacterSet(gset byte, charset byte) string { + return "\x1b" + string(gset) + string(charset) +} + +// SCS is an alias for SelectCharacterSet. +func SCS(gset byte, charset byte) string { + return SelectCharacterSet(gset, charset) +} + +// Locking Shift 1 Right (LS1R) shifts G1 into GR character set. +const LS1R = "\x1b~" + +// Locking Shift 2 (LS2) shifts G2 into GL character set. +const LS2 = "\x1bn" + +// Locking Shift 2 Right (LS2R) shifts G2 into GR character set. +const LS2R = "\x1b}" + +// Locking Shift 3 (LS3) shifts G3 into GL character set. +const LS3 = "\x1bo" + +// Locking Shift 3 Right (LS3R) shifts G3 into GR character set. +const LS3R = "\x1b|" diff --git a/vendor/github.com/charmbracelet/x/ansi/clipboard.go b/vendor/github.com/charmbracelet/x/ansi/clipboard.go new file mode 100644 index 00000000..94d26c36 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/clipboard.go @@ -0,0 +1,75 @@ +package ansi + +import "encoding/base64" + +// Clipboard names. +const ( + SystemClipboard = 'c' + PrimaryClipboard = 'p' +) + +// SetClipboard returns a sequence for manipulating the clipboard. +// +// OSC 52 ; Pc ; Pd ST +// OSC 52 ; Pc ; Pd BEL +// +// Where Pc is the clipboard name and Pd is the base64 encoded data. +// Empty data or invalid base64 data will reset the clipboard. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +func SetClipboard(c byte, d string) string { + if d != "" { + d = base64.StdEncoding.EncodeToString([]byte(d)) + } + return "\x1b]52;" + string(c) + ";" + d + "\x07" +} + +// SetSystemClipboard returns a sequence for setting the system clipboard. +// +// This is equivalent to SetClipboard(SystemClipboard, d). +func SetSystemClipboard(d string) string { + return SetClipboard(SystemClipboard, d) +} + +// SetPrimaryClipboard returns a sequence for setting the primary clipboard. +// +// This is equivalent to SetClipboard(PrimaryClipboard, d). +func SetPrimaryClipboard(d string) string { + return SetClipboard(PrimaryClipboard, d) +} + +// ResetClipboard returns a sequence for resetting the clipboard. +// +// This is equivalent to SetClipboard(c, ""). +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +func ResetClipboard(c byte) string { + return SetClipboard(c, "") +} + +// ResetSystemClipboard is a sequence for resetting the system clipboard. +// +// This is equivalent to ResetClipboard(SystemClipboard). +const ResetSystemClipboard = "\x1b]52;c;\x07" + +// ResetPrimaryClipboard is a sequence for resetting the primary clipboard. +// +// This is equivalent to ResetClipboard(PrimaryClipboard). +const ResetPrimaryClipboard = "\x1b]52;p;\x07" + +// RequestClipboard returns a sequence for requesting the clipboard. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +func RequestClipboard(c byte) string { + return "\x1b]52;" + string(c) + ";?\x07" +} + +// RequestSystemClipboard is a sequence for requesting the system clipboard. +// +// This is equivalent to RequestClipboard(SystemClipboard). +const RequestSystemClipboard = "\x1b]52;c;?\x07" + +// RequestPrimaryClipboard is a sequence for requesting the primary clipboard. +// +// This is equivalent to RequestClipboard(PrimaryClipboard). +const RequestPrimaryClipboard = "\x1b]52;p;?\x07" diff --git a/vendor/github.com/charmbracelet/x/ansi/color.go b/vendor/github.com/charmbracelet/x/ansi/color.go new file mode 100644 index 00000000..09feb975 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/color.go @@ -0,0 +1,784 @@ +package ansi + +import ( + "image/color" + + "github.com/lucasb-eyer/go-colorful" +) + +// Color is a color that can be used in a terminal. ANSI (including +// ANSI256) and 24-bit "true colors" fall under this category. +type Color interface { + color.Color +} + +// BasicColor is an ANSI 3-bit or 4-bit color with a value from 0 to 15. +type BasicColor uint8 + +var _ Color = BasicColor(0) + +const ( + // Black is the ANSI black color. + Black BasicColor = iota + + // Red is the ANSI red color. + Red + + // Green is the ANSI green color. + Green + + // Yellow is the ANSI yellow color. + Yellow + + // Blue is the ANSI blue color. + Blue + + // Magenta is the ANSI magenta color. + Magenta + + // Cyan is the ANSI cyan color. + Cyan + + // White is the ANSI white color. + White + + // BrightBlack is the ANSI bright black color. + BrightBlack + + // BrightRed is the ANSI bright red color. + BrightRed + + // BrightGreen is the ANSI bright green color. + BrightGreen + + // BrightYellow is the ANSI bright yellow color. + BrightYellow + + // BrightBlue is the ANSI bright blue color. + BrightBlue + + // BrightMagenta is the ANSI bright magenta color. + BrightMagenta + + // BrightCyan is the ANSI bright cyan color. + BrightCyan + + // BrightWhite is the ANSI bright white color. + BrightWhite +) + +// RGBA returns the red, green, blue and alpha components of the color. It +// satisfies the color.Color interface. +func (c BasicColor) RGBA() (uint32, uint32, uint32, uint32) { + ansi := uint32(c) + if ansi > 15 { + return 0, 0, 0, 0xffff + } + + return ansiToRGB(byte(ansi)).RGBA() +} + +// IndexedColor is an ANSI 256 (8-bit) color with a value from 0 to 255. +type IndexedColor uint8 + +var _ Color = IndexedColor(0) + +// RGBA returns the red, green, blue and alpha components of the color. It +// satisfies the color.Color interface. +func (c IndexedColor) RGBA() (uint32, uint32, uint32, uint32) { + return ansiToRGB(byte(c)).RGBA() +} + +// ExtendedColor is an ANSI 256 (8-bit) color with a value from 0 to 255. +// +// Deprecated: use [IndexedColor] instead. +type ExtendedColor = IndexedColor + +// TrueColor is a 24-bit color that can be used in the terminal. +// This can be used to represent RGB colors. +// +// For example, the color red can be represented as: +// +// TrueColor(0xff0000) +// +// Deprecated: use [RGBColor] instead. +type TrueColor uint32 + +var _ Color = TrueColor(0) + +// RGBA returns the red, green, blue and alpha components of the color. It +// satisfies the color.Color interface. +func (c TrueColor) RGBA() (uint32, uint32, uint32, uint32) { + r, g, b := hexToRGB(uint32(c)) + return toRGBA(r, g, b) +} + +// RGBColor is a 24-bit color that can be used in the terminal. +// This can be used to represent RGB colors. +type RGBColor struct { + R uint8 + G uint8 + B uint8 +} + +// RGBA returns the red, green, blue and alpha components of the color. It +// satisfies the color.Color interface. +func (c RGBColor) RGBA() (uint32, uint32, uint32, uint32) { + return toRGBA(uint32(c.R), uint32(c.G), uint32(c.B)) +} + +// ansiToRGB converts an ANSI color to a 24-bit RGB color. +// +// r, g, b := ansiToRGB(57) +func ansiToRGB(ansi byte) color.Color { + return ansiHex[ansi] +} + +// hexToRGB converts a number in hexadecimal format to red, green, and blue +// values. +// +// r, g, b := hexToRGB(0x0000FF) +func hexToRGB(hex uint32) (uint32, uint32, uint32) { + return hex >> 16 & 0xff, hex >> 8 & 0xff, hex & 0xff +} + +// toRGBA converts an RGB 8-bit color values to 32-bit color values suitable +// for color.Color. +// +// color.Color requires 16-bit color values, so we duplicate the 8-bit values +// to fill the 16-bit values. +// +// This always returns 0xffff (opaque) for the alpha channel. +func toRGBA(r, g, b uint32) (uint32, uint32, uint32, uint32) { + r |= r << 8 + g |= g << 8 + b |= b << 8 + return r, g, b, 0xffff +} + +//nolint:unused +func distSq(r1, g1, b1, r2, g2, b2 int) int { + return ((r1-r2)*(r1-r2) + (g1-g2)*(g1-g2) + (b1-b2)*(b1-b2)) +} + +func to6Cube[T int | float64](v T) int { + if v < 48 { + return 0 + } + if v < 115 { + return 1 + } + return int((v - 35) / 40) +} + +// Convert256 converts a [color.Color], usually a 24-bit color, to xterm(1) 256 +// color palette. +// +// xterm provides a 6x6x6 color cube (16 - 231) and 24 greys (232 - 255). We +// map our RGB color to the closest in the cube, also work out the closest +// grey, and use the nearest of the two based on the lightness of the color. +// +// Note that the xterm has much lower resolution for darker colors (they are +// not evenly spread out), so our 6 levels are not evenly spread: 0x0, 0x5f +// (95), 0x87 (135), 0xaf (175), 0xd7 (215) and 0xff (255). Greys are more +// evenly spread (8, 18, 28 ... 238). +func Convert256(c color.Color) IndexedColor { + // If the color is already an IndexedColor, return it. + if i, ok := c.(IndexedColor); ok { + return i + } + + // Note: this is mostly ported from tmux/colour.c. + col, ok := colorful.MakeColor(c) + if !ok { + return IndexedColor(0) + } + + r := col.R * 255 + g := col.G * 255 + b := col.B * 255 + + q2c := [6]int{0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff} + + // Map RGB to 6x6x6 cube. + qr := to6Cube(r) + cr := q2c[qr] + qg := to6Cube(g) + cg := q2c[qg] + qb := to6Cube(b) + cb := q2c[qb] + + // If we have hit the color exactly, return early. + ci := (36 * qr) + (6 * qg) + qb + if cr == int(r) && cg == int(g) && cb == int(b) { + return IndexedColor(16 + ci) //nolint:gosec + } + + // Work out the closest grey (average of RGB). + greyAvg := int(r+g+b) / 3 + var greyIdx int + if greyAvg > 238 { + greyIdx = 23 + } else { + greyIdx = (greyAvg - 3) / 10 + } + grey := 8 + (10 * greyIdx) + + // Return the one which is nearer to the original input rgb value + // XXX: This is where it differs from tmux's implementation, we prefer the + // closer color to the original in terms of light distances rather than the + // cube distance. + c2 := colorful.Color{R: float64(cr) / 255.0, G: float64(cg) / 255.0, B: float64(cb) / 255.0} + g2 := colorful.Color{R: float64(grey) / 255.0, G: float64(grey) / 255.0, B: float64(grey) / 255.0} + colorDist := col.DistanceHSLuv(c2) + grayDist := col.DistanceHSLuv(g2) + + if colorDist <= grayDist { + return IndexedColor(16 + ci) //nolint:gosec + } + return IndexedColor(232 + greyIdx) //nolint:gosec + + // // Is grey or 6x6x6 color closest? + // d := distSq(cr, cg, cb, int(r), int(g), int(b)) + // if distSq(grey, grey, grey, int(r), int(g), int(b)) < d { + // return IndexedColor(232 + greyIdx) //nolint:gosec + // } + // return IndexedColor(16 + ci) //nolint:gosec +} + +// Convert16 converts a [color.Color] to a 16-color ANSI color. It will first +// try to find a match in the 256 xterm(1) color palette, and then map that to +// the 16-color ANSI palette. +func Convert16(c color.Color) BasicColor { + switch c := c.(type) { + case BasicColor: + // If the color is already a BasicColor, return it. + return c + case IndexedColor: + // If the color is already an IndexedColor, return the corresponding + // BasicColor. + return ansi256To16[c] + default: + c256 := Convert256(c) + return ansi256To16[c256] + } +} + +// RGB values of ANSI colors (0-255). +var ansiHex = [...]color.RGBA{ + 0: {R: 0x00, G: 0x00, B: 0x00, A: 0xff}, // "#000000" + 1: {R: 0x80, G: 0x00, B: 0x00, A: 0xff}, // "#800000" + 2: {R: 0x00, G: 0x80, B: 0x00, A: 0xff}, // "#008000" + 3: {R: 0x80, G: 0x80, B: 0x00, A: 0xff}, // "#808000" + 4: {R: 0x00, G: 0x00, B: 0x80, A: 0xff}, // "#000080" + 5: {R: 0x80, G: 0x00, B: 0x80, A: 0xff}, // "#800080" + 6: {R: 0x00, G: 0x80, B: 0x80, A: 0xff}, // "#008080" + 7: {R: 0xc0, G: 0xc0, B: 0xc0, A: 0xff}, // "#c0c0c0" + 8: {R: 0x80, G: 0x80, B: 0x80, A: 0xff}, // "#808080" + 9: {R: 0xff, G: 0x00, B: 0x00, A: 0xff}, // "#ff0000" + 10: {R: 0x00, G: 0xff, B: 0x00, A: 0xff}, // "#00ff00" + 11: {R: 0xff, G: 0xff, B: 0x00, A: 0xff}, // "#ffff00" + 12: {R: 0x00, G: 0x00, B: 0xff, A: 0xff}, // "#0000ff" + 13: {R: 0xff, G: 0x00, B: 0xff, A: 0xff}, // "#ff00ff" + 14: {R: 0x00, G: 0xff, B: 0xff, A: 0xff}, // "#00ffff" + 15: {R: 0xff, G: 0xff, B: 0xff, A: 0xff}, // "#ffffff" + 16: {R: 0x00, G: 0x00, B: 0x00, A: 0xff}, // "#000000" + 17: {R: 0x00, G: 0x00, B: 0x5f, A: 0xff}, // "#00005f" + 18: {R: 0x00, G: 0x00, B: 0x87, A: 0xff}, // "#000087" + 19: {R: 0x00, G: 0x00, B: 0xaf, A: 0xff}, // "#0000af" + 20: {R: 0x00, G: 0x00, B: 0xd7, A: 0xff}, // "#0000d7" + 21: {R: 0x00, G: 0x00, B: 0xff, A: 0xff}, // "#0000ff" + 22: {R: 0x00, G: 0x5f, B: 0x00, A: 0xff}, // "#005f00" + 23: {R: 0x00, G: 0x5f, B: 0x5f, A: 0xff}, // "#005f5f" + 24: {R: 0x00, G: 0x5f, B: 0x87, A: 0xff}, // "#005f87" + 25: {R: 0x00, G: 0x5f, B: 0xaf, A: 0xff}, // "#005faf" + 26: {R: 0x00, G: 0x5f, B: 0xd7, A: 0xff}, // "#005fd7" + 27: {R: 0x00, G: 0x5f, B: 0xff, A: 0xff}, // "#005fff" + 28: {R: 0x00, G: 0x87, B: 0x00, A: 0xff}, // "#008700" + 29: {R: 0x00, G: 0x87, B: 0x5f, A: 0xff}, // "#00875f" + 30: {R: 0x00, G: 0x87, B: 0x87, A: 0xff}, // "#008787" + 31: {R: 0x00, G: 0x87, B: 0xaf, A: 0xff}, // "#0087af" + 32: {R: 0x00, G: 0x87, B: 0xd7, A: 0xff}, // "#0087d7" + 33: {R: 0x00, G: 0x87, B: 0xff, A: 0xff}, // "#0087ff" + 34: {R: 0x00, G: 0xaf, B: 0x00, A: 0xff}, // "#00af00" + 35: {R: 0x00, G: 0xaf, B: 0x5f, A: 0xff}, // "#00af5f" + 36: {R: 0x00, G: 0xaf, B: 0x87, A: 0xff}, // "#00af87" + 37: {R: 0x00, G: 0xaf, B: 0xaf, A: 0xff}, // "#00afaf" + 38: {R: 0x00, G: 0xaf, B: 0xd7, A: 0xff}, // "#00afd7" + 39: {R: 0x00, G: 0xaf, B: 0xff, A: 0xff}, // "#00afff" + 40: {R: 0x00, G: 0xd7, B: 0x00, A: 0xff}, // "#00d700" + 41: {R: 0x00, G: 0xd7, B: 0x5f, A: 0xff}, // "#00d75f" + 42: {R: 0x00, G: 0xd7, B: 0x87, A: 0xff}, // "#00d787" + 43: {R: 0x00, G: 0xd7, B: 0xaf, A: 0xff}, // "#00d7af" + 44: {R: 0x00, G: 0xd7, B: 0xd7, A: 0xff}, // "#00d7d7" + 45: {R: 0x00, G: 0xd7, B: 0xff, A: 0xff}, // "#00d7ff" + 46: {R: 0x00, G: 0xff, B: 0x00, A: 0xff}, // "#00ff00" + 47: {R: 0x00, G: 0xff, B: 0x5f, A: 0xff}, // "#00ff5f" + 48: {R: 0x00, G: 0xff, B: 0x87, A: 0xff}, // "#00ff87" + 49: {R: 0x00, G: 0xff, B: 0xaf, A: 0xff}, // "#00ffaf" + 50: {R: 0x00, G: 0xff, B: 0xd7, A: 0xff}, // "#00ffd7" + 51: {R: 0x00, G: 0xff, B: 0xff, A: 0xff}, // "#00ffff" + 52: {R: 0x5f, G: 0x00, B: 0x00, A: 0xff}, // "#5f0000" + 53: {R: 0x5f, G: 0x00, B: 0x5f, A: 0xff}, // "#5f005f" + 54: {R: 0x5f, G: 0x00, B: 0x87, A: 0xff}, // "#5f0087" + 55: {R: 0x5f, G: 0x00, B: 0xaf, A: 0xff}, // "#5f00af" + 56: {R: 0x5f, G: 0x00, B: 0xd7, A: 0xff}, // "#5f00d7" + 57: {R: 0x5f, G: 0x00, B: 0xff, A: 0xff}, // "#5f00ff" + 58: {R: 0x5f, G: 0x5f, B: 0x00, A: 0xff}, // "#5f5f00" + 59: {R: 0x5f, G: 0x5f, B: 0x5f, A: 0xff}, // "#5f5f5f" + 60: {R: 0x5f, G: 0x5f, B: 0x87, A: 0xff}, // "#5f5f87" + 61: {R: 0x5f, G: 0x5f, B: 0xaf, A: 0xff}, // "#5f5faf" + 62: {R: 0x5f, G: 0x5f, B: 0xd7, A: 0xff}, // "#5f5fd7" + 63: {R: 0x5f, G: 0x5f, B: 0xff, A: 0xff}, // "#5f5fff" + 64: {R: 0x5f, G: 0x87, B: 0x00, A: 0xff}, // "#5f8700" + 65: {R: 0x5f, G: 0x87, B: 0x5f, A: 0xff}, // "#5f875f" + 66: {R: 0x5f, G: 0x87, B: 0x87, A: 0xff}, // "#5f8787" + 67: {R: 0x5f, G: 0x87, B: 0xaf, A: 0xff}, // "#5f87af" + 68: {R: 0x5f, G: 0x87, B: 0xd7, A: 0xff}, // "#5f87d7" + 69: {R: 0x5f, G: 0x87, B: 0xff, A: 0xff}, // "#5f87ff" + 70: {R: 0x5f, G: 0xaf, B: 0x00, A: 0xff}, // "#5faf00" + 71: {R: 0x5f, G: 0xaf, B: 0x5f, A: 0xff}, // "#5faf5f" + 72: {R: 0x5f, G: 0xaf, B: 0x87, A: 0xff}, // "#5faf87" + 73: {R: 0x5f, G: 0xaf, B: 0xaf, A: 0xff}, // "#5fafaf" + 74: {R: 0x5f, G: 0xaf, B: 0xd7, A: 0xff}, // "#5fafd7" + 75: {R: 0x5f, G: 0xaf, B: 0xff, A: 0xff}, // "#5fafff" + 76: {R: 0x5f, G: 0xd7, B: 0x00, A: 0xff}, // "#5fd700" + 77: {R: 0x5f, G: 0xd7, B: 0x5f, A: 0xff}, // "#5fd75f" + 78: {R: 0x5f, G: 0xd7, B: 0x87, A: 0xff}, // "#5fd787" + 79: {R: 0x5f, G: 0xd7, B: 0xaf, A: 0xff}, // "#5fd7af" + 80: {R: 0x5f, G: 0xd7, B: 0xd7, A: 0xff}, // "#5fd7d7" + 81: {R: 0x5f, G: 0xd7, B: 0xff, A: 0xff}, // "#5fd7ff" + 82: {R: 0x5f, G: 0xff, B: 0x00, A: 0xff}, // "#5fff00" + 83: {R: 0x5f, G: 0xff, B: 0x5f, A: 0xff}, // "#5fff5f" + 84: {R: 0x5f, G: 0xff, B: 0x87, A: 0xff}, // "#5fff87" + 85: {R: 0x5f, G: 0xff, B: 0xaf, A: 0xff}, // "#5fffaf" + 86: {R: 0x5f, G: 0xff, B: 0xd7, A: 0xff}, // "#5fffd7" + 87: {R: 0x5f, G: 0xff, B: 0xff, A: 0xff}, // "#5fffff" + 88: {R: 0x87, G: 0x00, B: 0x00, A: 0xff}, // "#870000" + 89: {R: 0x87, G: 0x00, B: 0x5f, A: 0xff}, // "#87005f" + 90: {R: 0x87, G: 0x00, B: 0x87, A: 0xff}, // "#870087" + 91: {R: 0x87, G: 0x00, B: 0xaf, A: 0xff}, // "#8700af" + 92: {R: 0x87, G: 0x00, B: 0xd7, A: 0xff}, // "#8700d7" + 93: {R: 0x87, G: 0x00, B: 0xff, A: 0xff}, // "#8700ff" + 94: {R: 0x87, G: 0x5f, B: 0x00, A: 0xff}, // "#875f00" + 95: {R: 0x87, G: 0x5f, B: 0x5f, A: 0xff}, // "#875f5f" + 96: {R: 0x87, G: 0x5f, B: 0x87, A: 0xff}, // "#875f87" + 97: {R: 0x87, G: 0x5f, B: 0xaf, A: 0xff}, // "#875faf" + 98: {R: 0x87, G: 0x5f, B: 0xd7, A: 0xff}, // "#875fd7" + 99: {R: 0x87, G: 0x5f, B: 0xff, A: 0xff}, // "#875fff" + 100: {R: 0x87, G: 0x87, B: 0x00, A: 0xff}, // "#878700" + 101: {R: 0x87, G: 0x87, B: 0x5f, A: 0xff}, // "#87875f" + 102: {R: 0x87, G: 0x87, B: 0x87, A: 0xff}, // "#878787" + 103: {R: 0x87, G: 0x87, B: 0xaf, A: 0xff}, // "#8787af" + 104: {R: 0x87, G: 0x87, B: 0xd7, A: 0xff}, // "#8787d7" + 105: {R: 0x87, G: 0x87, B: 0xff, A: 0xff}, // "#8787ff" + 106: {R: 0x87, G: 0xaf, B: 0x00, A: 0xff}, // "#87af00" + 107: {R: 0x87, G: 0xaf, B: 0x5f, A: 0xff}, // "#87af5f" + 108: {R: 0x87, G: 0xaf, B: 0x87, A: 0xff}, // "#87af87" + 109: {R: 0x87, G: 0xaf, B: 0xaf, A: 0xff}, // "#87afaf" + 110: {R: 0x87, G: 0xaf, B: 0xd7, A: 0xff}, // "#87afd7" + 111: {R: 0x87, G: 0xaf, B: 0xff, A: 0xff}, // "#87afff" + 112: {R: 0x87, G: 0xd7, B: 0x00, A: 0xff}, // "#87d700" + 113: {R: 0x87, G: 0xd7, B: 0x5f, A: 0xff}, // "#87d75f" + 114: {R: 0x87, G: 0xd7, B: 0x87, A: 0xff}, // "#87d787" + 115: {R: 0x87, G: 0xd7, B: 0xaf, A: 0xff}, // "#87d7af" + 116: {R: 0x87, G: 0xd7, B: 0xd7, A: 0xff}, // "#87d7d7" + 117: {R: 0x87, G: 0xd7, B: 0xff, A: 0xff}, // "#87d7ff" + 118: {R: 0x87, G: 0xff, B: 0x00, A: 0xff}, // "#87ff00" + 119: {R: 0x87, G: 0xff, B: 0x5f, A: 0xff}, // "#87ff5f" + 120: {R: 0x87, G: 0xff, B: 0x87, A: 0xff}, // "#87ff87" + 121: {R: 0x87, G: 0xff, B: 0xaf, A: 0xff}, // "#87ffaf" + 122: {R: 0x87, G: 0xff, B: 0xd7, A: 0xff}, // "#87ffd7" + 123: {R: 0x87, G: 0xff, B: 0xff, A: 0xff}, // "#87ffff" + 124: {R: 0xaf, G: 0x00, B: 0x00, A: 0xff}, // "#af0000" + 125: {R: 0xaf, G: 0x00, B: 0x5f, A: 0xff}, // "#af005f" + 126: {R: 0xaf, G: 0x00, B: 0x87, A: 0xff}, // "#af0087" + 127: {R: 0xaf, G: 0x00, B: 0xaf, A: 0xff}, // "#af00af" + 128: {R: 0xaf, G: 0x00, B: 0xd7, A: 0xff}, // "#af00d7" + 129: {R: 0xaf, G: 0x00, B: 0xff, A: 0xff}, // "#af00ff" + 130: {R: 0xaf, G: 0x5f, B: 0x00, A: 0xff}, // "#af5f00" + 131: {R: 0xaf, G: 0x5f, B: 0x5f, A: 0xff}, // "#af5f5f" + 132: {R: 0xaf, G: 0x5f, B: 0x87, A: 0xff}, // "#af5f87" + 133: {R: 0xaf, G: 0x5f, B: 0xaf, A: 0xff}, // "#af5faf" + 134: {R: 0xaf, G: 0x5f, B: 0xd7, A: 0xff}, // "#af5fd7" + 135: {R: 0xaf, G: 0x5f, B: 0xff, A: 0xff}, // "#af5fff" + 136: {R: 0xaf, G: 0x87, B: 0x00, A: 0xff}, // "#af8700" + 137: {R: 0xaf, G: 0x87, B: 0x5f, A: 0xff}, // "#af875f" + 138: {R: 0xaf, G: 0x87, B: 0x87, A: 0xff}, // "#af8787" + 139: {R: 0xaf, G: 0x87, B: 0xaf, A: 0xff}, // "#af87af" + 140: {R: 0xaf, G: 0x87, B: 0xd7, A: 0xff}, // "#af87d7" + 141: {R: 0xaf, G: 0x87, B: 0xff, A: 0xff}, // "#af87ff" + 142: {R: 0xaf, G: 0xaf, B: 0x00, A: 0xff}, // "#afaf00" + 143: {R: 0xaf, G: 0xaf, B: 0x5f, A: 0xff}, // "#afaf5f" + 144: {R: 0xaf, G: 0xaf, B: 0x87, A: 0xff}, // "#afaf87" + 145: {R: 0xaf, G: 0xaf, B: 0xaf, A: 0xff}, // "#afafaf" + 146: {R: 0xaf, G: 0xaf, B: 0xd7, A: 0xff}, // "#afafd7" + 147: {R: 0xaf, G: 0xaf, B: 0xff, A: 0xff}, // "#afafff" + 148: {R: 0xaf, G: 0xd7, B: 0x00, A: 0xff}, // "#afd700" + 149: {R: 0xaf, G: 0xd7, B: 0x5f, A: 0xff}, // "#afd75f" + 150: {R: 0xaf, G: 0xd7, B: 0x87, A: 0xff}, // "#afd787" + 151: {R: 0xaf, G: 0xd7, B: 0xaf, A: 0xff}, // "#afd7af" + 152: {R: 0xaf, G: 0xd7, B: 0xd7, A: 0xff}, // "#afd7d7" + 153: {R: 0xaf, G: 0xd7, B: 0xff, A: 0xff}, // "#afd7ff" + 154: {R: 0xaf, G: 0xff, B: 0x00, A: 0xff}, // "#afff00" + 155: {R: 0xaf, G: 0xff, B: 0x5f, A: 0xff}, // "#afff5f" + 156: {R: 0xaf, G: 0xff, B: 0x87, A: 0xff}, // "#afff87" + 157: {R: 0xaf, G: 0xff, B: 0xaf, A: 0xff}, // "#afffaf" + 158: {R: 0xaf, G: 0xff, B: 0xd7, A: 0xff}, // "#afffd7" + 159: {R: 0xaf, G: 0xff, B: 0xff, A: 0xff}, // "#afffff" + 160: {R: 0xd7, G: 0x00, B: 0x00, A: 0xff}, // "#d70000" + 161: {R: 0xd7, G: 0x00, B: 0x5f, A: 0xff}, // "#d7005f" + 162: {R: 0xd7, G: 0x00, B: 0x87, A: 0xff}, // "#d70087" + 163: {R: 0xd7, G: 0x00, B: 0xaf, A: 0xff}, // "#d700af" + 164: {R: 0xd7, G: 0x00, B: 0xd7, A: 0xff}, // "#d700d7" + 165: {R: 0xd7, G: 0x00, B: 0xff, A: 0xff}, // "#d700ff" + 166: {R: 0xd7, G: 0x5f, B: 0x00, A: 0xff}, // "#d75f00" + 167: {R: 0xd7, G: 0x5f, B: 0x5f, A: 0xff}, // "#d75f5f" + 168: {R: 0xd7, G: 0x5f, B: 0x87, A: 0xff}, // "#d75f87" + 169: {R: 0xd7, G: 0x5f, B: 0xaf, A: 0xff}, // "#d75faf" + 170: {R: 0xd7, G: 0x5f, B: 0xd7, A: 0xff}, // "#d75fd7" + 171: {R: 0xd7, G: 0x5f, B: 0xff, A: 0xff}, // "#d75fff" + 172: {R: 0xd7, G: 0x87, B: 0x00, A: 0xff}, // "#d78700" + 173: {R: 0xd7, G: 0x87, B: 0x5f, A: 0xff}, // "#d7875f" + 174: {R: 0xd7, G: 0x87, B: 0x87, A: 0xff}, // "#d78787" + 175: {R: 0xd7, G: 0x87, B: 0xaf, A: 0xff}, // "#d787af" + 176: {R: 0xd7, G: 0x87, B: 0xd7, A: 0xff}, // "#d787d7" + 177: {R: 0xd7, G: 0x87, B: 0xff, A: 0xff}, // "#d787ff" + 178: {R: 0xd7, G: 0xaf, B: 0x00, A: 0xff}, // "#d7af00" + 179: {R: 0xd7, G: 0xaf, B: 0x5f, A: 0xff}, // "#d7af5f" + 180: {R: 0xd7, G: 0xaf, B: 0x87, A: 0xff}, // "#d7af87" + 181: {R: 0xd7, G: 0xaf, B: 0xaf, A: 0xff}, // "#d7afaf" + 182: {R: 0xd7, G: 0xaf, B: 0xd7, A: 0xff}, // "#d7afd7" + 183: {R: 0xd7, G: 0xaf, B: 0xff, A: 0xff}, // "#d7afff" + 184: {R: 0xd7, G: 0xd7, B: 0x00, A: 0xff}, // "#d7d700" + 185: {R: 0xd7, G: 0xd7, B: 0x5f, A: 0xff}, // "#d7d75f" + 186: {R: 0xd7, G: 0xd7, B: 0x87, A: 0xff}, // "#d7d787" + 187: {R: 0xd7, G: 0xd7, B: 0xaf, A: 0xff}, // "#d7d7af" + 188: {R: 0xd7, G: 0xd7, B: 0xd7, A: 0xff}, // "#d7d7d7" + 189: {R: 0xd7, G: 0xd7, B: 0xff, A: 0xff}, // "#d7d7ff" + 190: {R: 0xd7, G: 0xff, B: 0x00, A: 0xff}, // "#d7ff00" + 191: {R: 0xd7, G: 0xff, B: 0x5f, A: 0xff}, // "#d7ff5f" + 192: {R: 0xd7, G: 0xff, B: 0x87, A: 0xff}, // "#d7ff87" + 193: {R: 0xd7, G: 0xff, B: 0xaf, A: 0xff}, // "#d7ffaf" + 194: {R: 0xd7, G: 0xff, B: 0xd7, A: 0xff}, // "#d7ffd7" + 195: {R: 0xd7, G: 0xff, B: 0xff, A: 0xff}, // "#d7ffff" + 196: {R: 0xff, G: 0x00, B: 0x00, A: 0xff}, // "#ff0000" + 197: {R: 0xff, G: 0x00, B: 0x5f, A: 0xff}, // "#ff005f" + 198: {R: 0xff, G: 0x00, B: 0x87, A: 0xff}, // "#ff0087" + 199: {R: 0xff, G: 0x00, B: 0xaf, A: 0xff}, // "#ff00af" + 200: {R: 0xff, G: 0x00, B: 0xd7, A: 0xff}, // "#ff00d7" + 201: {R: 0xff, G: 0x00, B: 0xff, A: 0xff}, // "#ff00ff" + 202: {R: 0xff, G: 0x5f, B: 0x00, A: 0xff}, // "#ff5f00" + 203: {R: 0xff, G: 0x5f, B: 0x5f, A: 0xff}, // "#ff5f5f" + 204: {R: 0xff, G: 0x5f, B: 0x87, A: 0xff}, // "#ff5f87" + 205: {R: 0xff, G: 0x5f, B: 0xaf, A: 0xff}, // "#ff5faf" + 206: {R: 0xff, G: 0x5f, B: 0xd7, A: 0xff}, // "#ff5fd7" + 207: {R: 0xff, G: 0x5f, B: 0xff, A: 0xff}, // "#ff5fff" + 208: {R: 0xff, G: 0x87, B: 0x00, A: 0xff}, // "#ff8700" + 209: {R: 0xff, G: 0x87, B: 0x5f, A: 0xff}, // "#ff875f" + 210: {R: 0xff, G: 0x87, B: 0x87, A: 0xff}, // "#ff8787" + 211: {R: 0xff, G: 0x87, B: 0xaf, A: 0xff}, // "#ff87af" + 212: {R: 0xff, G: 0x87, B: 0xd7, A: 0xff}, // "#ff87d7" + 213: {R: 0xff, G: 0x87, B: 0xff, A: 0xff}, // "#ff87ff" + 214: {R: 0xff, G: 0xaf, B: 0x00, A: 0xff}, // "#ffaf00" + 215: {R: 0xff, G: 0xaf, B: 0x5f, A: 0xff}, // "#ffaf5f" + 216: {R: 0xff, G: 0xaf, B: 0x87, A: 0xff}, // "#ffaf87" + 217: {R: 0xff, G: 0xaf, B: 0xaf, A: 0xff}, // "#ffafaf" + 218: {R: 0xff, G: 0xaf, B: 0xd7, A: 0xff}, // "#ffafd7" + 219: {R: 0xff, G: 0xaf, B: 0xff, A: 0xff}, // "#ffafff" + 220: {R: 0xff, G: 0xd7, B: 0x00, A: 0xff}, // "#ffd700" + 221: {R: 0xff, G: 0xd7, B: 0x5f, A: 0xff}, // "#ffd75f" + 222: {R: 0xff, G: 0xd7, B: 0x87, A: 0xff}, // "#ffd787" + 223: {R: 0xff, G: 0xd7, B: 0xaf, A: 0xff}, // "#ffd7af" + 224: {R: 0xff, G: 0xd7, B: 0xd7, A: 0xff}, // "#ffd7d7" + 225: {R: 0xff, G: 0xd7, B: 0xff, A: 0xff}, // "#ffd7ff" + 226: {R: 0xff, G: 0xff, B: 0x00, A: 0xff}, // "#ffff00" + 227: {R: 0xff, G: 0xff, B: 0x5f, A: 0xff}, // "#ffff5f" + 228: {R: 0xff, G: 0xff, B: 0x87, A: 0xff}, // "#ffff87" + 229: {R: 0xff, G: 0xff, B: 0xaf, A: 0xff}, // "#ffffaf" + 230: {R: 0xff, G: 0xff, B: 0xd7, A: 0xff}, // "#ffffd7" + 231: {R: 0xff, G: 0xff, B: 0xff, A: 0xff}, // "#ffffff" + 232: {R: 0x08, G: 0x08, B: 0x08, A: 0xff}, // "#080808" + 233: {R: 0x12, G: 0x12, B: 0x12, A: 0xff}, // "#121212" + 234: {R: 0x1c, G: 0x1c, B: 0x1c, A: 0xff}, // "#1c1c1c" + 235: {R: 0x26, G: 0x26, B: 0x26, A: 0xff}, // "#262626" + 236: {R: 0x30, G: 0x30, B: 0x30, A: 0xff}, // "#303030" + 237: {R: 0x3a, G: 0x3a, B: 0x3a, A: 0xff}, // "#3a3a3a" + 238: {R: 0x44, G: 0x44, B: 0x44, A: 0xff}, // "#444444" + 239: {R: 0x4e, G: 0x4e, B: 0x4e, A: 0xff}, // "#4e4e4e" + 240: {R: 0x58, G: 0x58, B: 0x58, A: 0xff}, // "#585858" + 241: {R: 0x62, G: 0x62, B: 0x62, A: 0xff}, // "#626262" + 242: {R: 0x6c, G: 0x6c, B: 0x6c, A: 0xff}, // "#6c6c6c" + 243: {R: 0x76, G: 0x76, B: 0x76, A: 0xff}, // "#767676" + 244: {R: 0x80, G: 0x80, B: 0x80, A: 0xff}, // "#808080" + 245: {R: 0x8a, G: 0x8a, B: 0x8a, A: 0xff}, // "#8a8a8a" + 246: {R: 0x94, G: 0x94, B: 0x94, A: 0xff}, // "#949494" + 247: {R: 0x9e, G: 0x9e, B: 0x9e, A: 0xff}, // "#9e9e9e" + 248: {R: 0xa8, G: 0xa8, B: 0xa8, A: 0xff}, // "#a8a8a8" + 249: {R: 0xb2, G: 0xb2, B: 0xb2, A: 0xff}, // "#b2b2b2" + 250: {R: 0xbc, G: 0xbc, B: 0xbc, A: 0xff}, // "#bcbcbc" + 251: {R: 0xc6, G: 0xc6, B: 0xc6, A: 0xff}, // "#c6c6c6" + 252: {R: 0xd0, G: 0xd0, B: 0xd0, A: 0xff}, // "#d0d0d0" + 253: {R: 0xda, G: 0xda, B: 0xda, A: 0xff}, // "#dadada" + 254: {R: 0xe4, G: 0xe4, B: 0xe4, A: 0xff}, // "#e4e4e4" + 255: {R: 0xee, G: 0xee, B: 0xee, A: 0xff}, // "#eeeeee" +} + +var ansi256To16 = [...]BasicColor{ + 0: 0, + 1: 1, + 2: 2, + 3: 3, + 4: 4, + 5: 5, + 6: 6, + 7: 7, + 8: 8, + 9: 9, + 10: 10, + 11: 11, + 12: 12, + 13: 13, + 14: 14, + 15: 15, + 16: 0, + 17: 4, + 18: 4, + 19: 4, + 20: 12, + 21: 12, + 22: 2, + 23: 6, + 24: 4, + 25: 4, + 26: 12, + 27: 12, + 28: 2, + 29: 2, + 30: 6, + 31: 4, + 32: 12, + 33: 12, + 34: 2, + 35: 2, + 36: 2, + 37: 6, + 38: 12, + 39: 12, + 40: 10, + 41: 10, + 42: 10, + 43: 10, + 44: 14, + 45: 12, + 46: 10, + 47: 10, + 48: 10, + 49: 10, + 50: 10, + 51: 14, + 52: 1, + 53: 5, + 54: 4, + 55: 4, + 56: 12, + 57: 12, + 58: 3, + 59: 8, + 60: 4, + 61: 4, + 62: 12, + 63: 12, + 64: 2, + 65: 2, + 66: 6, + 67: 4, + 68: 12, + 69: 12, + 70: 2, + 71: 2, + 72: 2, + 73: 6, + 74: 12, + 75: 12, + 76: 10, + 77: 10, + 78: 10, + 79: 10, + 80: 14, + 81: 12, + 82: 10, + 83: 10, + 84: 10, + 85: 10, + 86: 10, + 87: 14, + 88: 1, + 89: 1, + 90: 5, + 91: 4, + 92: 12, + 93: 12, + 94: 1, + 95: 1, + 96: 5, + 97: 4, + 98: 12, + 99: 12, + 100: 3, + 101: 3, + 102: 8, + 103: 4, + 104: 12, + 105: 12, + 106: 2, + 107: 2, + 108: 2, + 109: 6, + 110: 12, + 111: 12, + 112: 10, + 113: 10, + 114: 10, + 115: 10, + 116: 14, + 117: 12, + 118: 10, + 119: 10, + 120: 10, + 121: 10, + 122: 10, + 123: 14, + 124: 1, + 125: 1, + 126: 1, + 127: 5, + 128: 12, + 129: 12, + 130: 1, + 131: 1, + 132: 1, + 133: 5, + 134: 12, + 135: 12, + 136: 1, + 137: 1, + 138: 1, + 139: 5, + 140: 12, + 141: 12, + 142: 3, + 143: 3, + 144: 3, + 145: 7, + 146: 12, + 147: 12, + 148: 10, + 149: 10, + 150: 10, + 151: 10, + 152: 14, + 153: 12, + 154: 10, + 155: 10, + 156: 10, + 157: 10, + 158: 10, + 159: 14, + 160: 9, + 161: 9, + 162: 9, + 163: 9, + 164: 13, + 165: 12, + 166: 9, + 167: 9, + 168: 9, + 169: 9, + 170: 13, + 171: 12, + 172: 9, + 173: 9, + 174: 9, + 175: 9, + 176: 13, + 177: 12, + 178: 9, + 179: 9, + 180: 9, + 181: 9, + 182: 13, + 183: 12, + 184: 11, + 185: 11, + 186: 11, + 187: 11, + 188: 7, + 189: 12, + 190: 10, + 191: 10, + 192: 10, + 193: 10, + 194: 10, + 195: 14, + 196: 9, + 197: 9, + 198: 9, + 199: 9, + 200: 9, + 201: 13, + 202: 9, + 203: 9, + 204: 9, + 205: 9, + 206: 9, + 207: 13, + 208: 9, + 209: 9, + 210: 9, + 211: 9, + 212: 9, + 213: 13, + 214: 9, + 215: 9, + 216: 9, + 217: 9, + 218: 9, + 219: 13, + 220: 9, + 221: 9, + 222: 9, + 223: 9, + 224: 9, + 225: 13, + 226: 11, + 227: 11, + 228: 11, + 229: 11, + 230: 11, + 231: 15, + 232: 0, + 233: 0, + 234: 0, + 235: 0, + 236: 0, + 237: 0, + 238: 8, + 239: 8, + 240: 8, + 241: 8, + 242: 8, + 243: 8, + 244: 7, + 245: 7, + 246: 7, + 247: 7, + 248: 7, + 249: 7, + 250: 15, + 251: 15, + 252: 15, + 253: 15, + 254: 15, + 255: 15, +} diff --git a/vendor/github.com/charmbracelet/x/ansi/ctrl.go b/vendor/github.com/charmbracelet/x/ansi/ctrl.go new file mode 100644 index 00000000..64bcf113 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/ctrl.go @@ -0,0 +1,156 @@ +package ansi + +import ( + "strconv" + "strings" +) + +// RequestNameVersion (XTVERSION) is a control sequence that requests the +// terminal's name and version. It responds with a DSR sequence identifying the +// terminal. +// +// CSI > 0 q +// DCS > | text ST +// +// See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-PC-Style-Function-Keys +const ( + RequestNameVersion = "\x1b[>q" + XTVERSION = RequestNameVersion +) + +// RequestXTVersion is a control sequence that requests the terminal's XTVERSION. It responds with a DSR sequence identifying the version. +// +// CSI > Ps q +// DCS > | text ST +// +// See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-PC-Style-Function-Keys +// +// Deprecated: use [RequestNameVersion] instead. +const RequestXTVersion = RequestNameVersion + +// PrimaryDeviceAttributes (DA1) is a control sequence that reports the +// terminal's primary device attributes. +// +// CSI c +// CSI 0 c +// CSI ? Ps ; ... c +// +// If no attributes are given, or if the attribute is 0, this function returns +// the request sequence. Otherwise, it returns the response sequence. +// +// Common attributes include: +// - 1 132 columns +// - 2 Printer port +// - 4 Sixel +// - 6 Selective erase +// - 7 Soft character set (DRCS) +// - 8 User-defined keys (UDKs) +// - 9 National replacement character sets (NRCS) (International terminal only) +// - 12 Yugoslavian (SCS) +// - 15 Technical character set +// - 18 Windowing capability +// - 21 Horizontal scrolling +// - 23 Greek +// - 24 Turkish +// - 42 ISO Latin-2 character set +// - 44 PCTerm +// - 45 Soft key map +// - 46 ASCII emulation +// +// See https://vt100.net/docs/vt510-rm/DA1.html +func PrimaryDeviceAttributes(attrs ...int) string { + if len(attrs) == 0 { + return RequestPrimaryDeviceAttributes + } else if len(attrs) == 1 && attrs[0] == 0 { + return "\x1b[0c" + } + + as := make([]string, len(attrs)) + for i, a := range attrs { + as[i] = strconv.Itoa(a) + } + return "\x1b[?" + strings.Join(as, ";") + "c" +} + +// DA1 is an alias for [PrimaryDeviceAttributes]. +func DA1(attrs ...int) string { + return PrimaryDeviceAttributes(attrs...) +} + +// RequestPrimaryDeviceAttributes is a control sequence that requests the +// terminal's primary device attributes (DA1). +// +// CSI c +// +// See https://vt100.net/docs/vt510-rm/DA1.html +const RequestPrimaryDeviceAttributes = "\x1b[c" + +// SecondaryDeviceAttributes (DA2) is a control sequence that reports the +// terminal's secondary device attributes. +// +// CSI > c +// CSI > 0 c +// CSI > Ps ; ... c +// +// See https://vt100.net/docs/vt510-rm/DA2.html +func SecondaryDeviceAttributes(attrs ...int) string { + if len(attrs) == 0 { + return RequestSecondaryDeviceAttributes + } + + as := make([]string, len(attrs)) + for i, a := range attrs { + as[i] = strconv.Itoa(a) + } + return "\x1b[>" + strings.Join(as, ";") + "c" +} + +// DA2 is an alias for [SecondaryDeviceAttributes]. +func DA2(attrs ...int) string { + return SecondaryDeviceAttributes(attrs...) +} + +// RequestSecondaryDeviceAttributes is a control sequence that requests the +// terminal's secondary device attributes (DA2). +// +// CSI > c +// +// See https://vt100.net/docs/vt510-rm/DA2.html +const RequestSecondaryDeviceAttributes = "\x1b[>c" + +// TertiaryDeviceAttributes (DA3) is a control sequence that reports the +// terminal's tertiary device attributes. +// +// CSI = c +// CSI = 0 c +// DCS ! | Text ST +// +// Where Text is the unit ID for the terminal. +// +// If no unit ID is given, or if the unit ID is 0, this function returns the +// request sequence. Otherwise, it returns the response sequence. +// +// See https://vt100.net/docs/vt510-rm/DA3.html +func TertiaryDeviceAttributes(unitID string) string { + switch unitID { + case "": + return RequestTertiaryDeviceAttributes + case "0": + return "\x1b[=0c" + } + + return "\x1bP!|" + unitID + "\x1b\\" +} + +// DA3 is an alias for [TertiaryDeviceAttributes]. +func DA3(unitID string) string { + return TertiaryDeviceAttributes(unitID) +} + +// RequestTertiaryDeviceAttributes is a control sequence that requests the +// terminal's tertiary device attributes (DA3). +// +// CSI = c +// +// See https://vt100.net/docs/vt510-rm/DA3.html +const RequestTertiaryDeviceAttributes = "\x1b[=c" diff --git a/vendor/github.com/charmbracelet/x/ansi/cursor.go b/vendor/github.com/charmbracelet/x/ansi/cursor.go new file mode 100644 index 00000000..785e31f8 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/cursor.go @@ -0,0 +1,635 @@ +package ansi + +import ( + "strconv" +) + +// SaveCursor (DECSC) is an escape sequence that saves the current cursor +// position. +// +// ESC 7 +// +// See: https://vt100.net/docs/vt510-rm/DECSC.html +const ( + SaveCursor = "\x1b7" + DECSC = SaveCursor +) + +// RestoreCursor (DECRC) is an escape sequence that restores the cursor +// position. +// +// ESC 8 +// +// See: https://vt100.net/docs/vt510-rm/DECRC.html +const ( + RestoreCursor = "\x1b8" + DECRC = RestoreCursor +) + +// RequestCursorPosition is an escape sequence that requests the current cursor +// position. +// +// CSI 6 n +// +// The terminal will report the cursor position as a CSI sequence in the +// following format: +// +// CSI Pl ; Pc R +// +// Where Pl is the line number and Pc is the column number. +// See: https://vt100.net/docs/vt510-rm/CPR.html +// +// Deprecated: use [RequestCursorPositionReport] instead. +const RequestCursorPosition = "\x1b[6n" + +// RequestExtendedCursorPosition (DECXCPR) is a sequence for requesting the +// cursor position report including the current page number. +// +// CSI ? 6 n +// +// The terminal will report the cursor position as a CSI sequence in the +// following format: +// +// CSI ? Pl ; Pc ; Pp R +// +// Where Pl is the line number, Pc is the column number, and Pp is the page +// number. +// See: https://vt100.net/docs/vt510-rm/DECXCPR.html +// +// Deprecated: use [RequestExtendedCursorPositionReport] instead. +const RequestExtendedCursorPosition = "\x1b[?6n" + +// CursorUp (CUU) returns a sequence for moving the cursor up n cells. +// +// CSI n A +// +// See: https://vt100.net/docs/vt510-rm/CUU.html +func CursorUp(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "A" +} + +// CUU is an alias for [CursorUp]. +func CUU(n int) string { + return CursorUp(n) +} + +// CUU1 is a sequence for moving the cursor up one cell. +const CUU1 = "\x1b[A" + +// CursorUp1 is a sequence for moving the cursor up one cell. +// +// This is equivalent to CursorUp(1). +// +// Deprecated: use [CUU1] instead. +const CursorUp1 = "\x1b[A" + +// CursorDown (CUD) returns a sequence for moving the cursor down n cells. +// +// CSI n B +// +// See: https://vt100.net/docs/vt510-rm/CUD.html +func CursorDown(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "B" +} + +// CUD is an alias for [CursorDown]. +func CUD(n int) string { + return CursorDown(n) +} + +// CUD1 is a sequence for moving the cursor down one cell. +const CUD1 = "\x1b[B" + +// CursorDown1 is a sequence for moving the cursor down one cell. +// +// This is equivalent to CursorDown(1). +// +// Deprecated: use [CUD1] instead. +const CursorDown1 = "\x1b[B" + +// CursorForward (CUF) returns a sequence for moving the cursor right n cells. +// +// # CSI n C +// +// See: https://vt100.net/docs/vt510-rm/CUF.html +func CursorForward(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "C" +} + +// CUF is an alias for [CursorForward]. +func CUF(n int) string { + return CursorForward(n) +} + +// CUF1 is a sequence for moving the cursor right one cell. +const CUF1 = "\x1b[C" + +// CursorRight (CUF) returns a sequence for moving the cursor right n cells. +// +// CSI n C +// +// See: https://vt100.net/docs/vt510-rm/CUF.html +// +// Deprecated: use [CursorForward] instead. +func CursorRight(n int) string { + return CursorForward(n) +} + +// CursorRight1 is a sequence for moving the cursor right one cell. +// +// This is equivalent to CursorRight(1). +// +// Deprecated: use [CUF1] instead. +const CursorRight1 = CUF1 + +// CursorBackward (CUB) returns a sequence for moving the cursor left n cells. +// +// # CSI n D +// +// See: https://vt100.net/docs/vt510-rm/CUB.html +func CursorBackward(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "D" +} + +// CUB is an alias for [CursorBackward]. +func CUB(n int) string { + return CursorBackward(n) +} + +// CUB1 is a sequence for moving the cursor left one cell. +const CUB1 = "\x1b[D" + +// CursorLeft (CUB) returns a sequence for moving the cursor left n cells. +// +// CSI n D +// +// See: https://vt100.net/docs/vt510-rm/CUB.html +// +// Deprecated: use [CursorBackward] instead. +func CursorLeft(n int) string { + return CursorBackward(n) +} + +// CursorLeft1 is a sequence for moving the cursor left one cell. +// +// This is equivalent to CursorLeft(1). +// +// Deprecated: use [CUB1] instead. +const CursorLeft1 = CUB1 + +// CursorNextLine (CNL) returns a sequence for moving the cursor to the +// beginning of the next line n times. +// +// CSI n E +// +// See: https://vt100.net/docs/vt510-rm/CNL.html +func CursorNextLine(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "E" +} + +// CNL is an alias for [CursorNextLine]. +func CNL(n int) string { + return CursorNextLine(n) +} + +// CursorPreviousLine (CPL) returns a sequence for moving the cursor to the +// beginning of the previous line n times. +// +// CSI n F +// +// See: https://vt100.net/docs/vt510-rm/CPL.html +func CursorPreviousLine(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "F" +} + +// CPL is an alias for [CursorPreviousLine]. +func CPL(n int) string { + return CursorPreviousLine(n) +} + +// CursorHorizontalAbsolute (CHA) returns a sequence for moving the cursor to +// the given column. +// +// Default is 1. +// +// CSI n G +// +// See: https://vt100.net/docs/vt510-rm/CHA.html +func CursorHorizontalAbsolute(col int) string { + var s string + if col > 0 { + s = strconv.Itoa(col) + } + return "\x1b[" + s + "G" +} + +// CHA is an alias for [CursorHorizontalAbsolute]. +func CHA(col int) string { + return CursorHorizontalAbsolute(col) +} + +// CursorPosition (CUP) returns a sequence for setting the cursor to the +// given row and column. +// +// Default is 1,1. +// +// CSI n ; m H +// +// See: https://vt100.net/docs/vt510-rm/CUP.html +func CursorPosition(col, row int) string { + if row <= 0 && col <= 0 { + return CursorHomePosition + } + + var r, c string + if row > 0 { + r = strconv.Itoa(row) + } + if col > 0 { + c = strconv.Itoa(col) + } + return "\x1b[" + r + ";" + c + "H" +} + +// CUP is an alias for [CursorPosition]. +func CUP(col, row int) string { + return CursorPosition(col, row) +} + +// CursorHomePosition is a sequence for moving the cursor to the upper left +// corner of the scrolling region. This is equivalent to `CursorPosition(1, 1)`. +const CursorHomePosition = "\x1b[H" + +// SetCursorPosition (CUP) returns a sequence for setting the cursor to the +// given row and column. +// +// CSI n ; m H +// +// See: https://vt100.net/docs/vt510-rm/CUP.html +// +// Deprecated: use [CursorPosition] instead. +func SetCursorPosition(col, row int) string { + if row <= 0 && col <= 0 { + return HomeCursorPosition + } + + var r, c string + if row > 0 { + r = strconv.Itoa(row) + } + if col > 0 { + c = strconv.Itoa(col) + } + return "\x1b[" + r + ";" + c + "H" +} + +// HomeCursorPosition is a sequence for moving the cursor to the upper left +// corner of the scrolling region. This is equivalent to `SetCursorPosition(1, 1)`. +// +// Deprecated: use [CursorHomePosition] instead. +const HomeCursorPosition = CursorHomePosition + +// MoveCursor (CUP) returns a sequence for setting the cursor to the +// given row and column. +// +// CSI n ; m H +// +// See: https://vt100.net/docs/vt510-rm/CUP.html +// +// Deprecated: use [CursorPosition] instead. +func MoveCursor(col, row int) string { + return SetCursorPosition(col, row) +} + +// CursorOrigin is a sequence for moving the cursor to the upper left corner of +// the display. This is equivalent to `SetCursorPosition(1, 1)`. +// +// Deprecated: use [CursorHomePosition] instead. +const CursorOrigin = "\x1b[1;1H" + +// MoveCursorOrigin is a sequence for moving the cursor to the upper left +// corner of the display. This is equivalent to `SetCursorPosition(1, 1)`. +// +// Deprecated: use [CursorHomePosition] instead. +const MoveCursorOrigin = CursorOrigin + +// CursorHorizontalForwardTab (CHT) returns a sequence for moving the cursor to +// the next tab stop n times. +// +// Default is 1. +// +// CSI n I +// +// See: https://vt100.net/docs/vt510-rm/CHT.html +func CursorHorizontalForwardTab(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "I" +} + +// CHT is an alias for [CursorHorizontalForwardTab]. +func CHT(n int) string { + return CursorHorizontalForwardTab(n) +} + +// EraseCharacter (ECH) returns a sequence for erasing n characters from the +// screen. This doesn't affect other cell attributes. +// +// Default is 1. +// +// CSI n X +// +// See: https://vt100.net/docs/vt510-rm/ECH.html +func EraseCharacter(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "X" +} + +// ECH is an alias for [EraseCharacter]. +func ECH(n int) string { + return EraseCharacter(n) +} + +// CursorBackwardTab (CBT) returns a sequence for moving the cursor to the +// previous tab stop n times. +// +// Default is 1. +// +// CSI n Z +// +// See: https://vt100.net/docs/vt510-rm/CBT.html +func CursorBackwardTab(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "Z" +} + +// CBT is an alias for [CursorBackwardTab]. +func CBT(n int) string { + return CursorBackwardTab(n) +} + +// VerticalPositionAbsolute (VPA) returns a sequence for moving the cursor to +// the given row. +// +// Default is 1. +// +// CSI n d +// +// See: https://vt100.net/docs/vt510-rm/VPA.html +func VerticalPositionAbsolute(row int) string { + var s string + if row > 0 { + s = strconv.Itoa(row) + } + return "\x1b[" + s + "d" +} + +// VPA is an alias for [VerticalPositionAbsolute]. +func VPA(row int) string { + return VerticalPositionAbsolute(row) +} + +// VerticalPositionRelative (VPR) returns a sequence for moving the cursor down +// n rows relative to the current position. +// +// Default is 1. +// +// CSI n e +// +// See: https://vt100.net/docs/vt510-rm/VPR.html +func VerticalPositionRelative(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "e" +} + +// VPR is an alias for [VerticalPositionRelative]. +func VPR(n int) string { + return VerticalPositionRelative(n) +} + +// HorizontalVerticalPosition (HVP) returns a sequence for moving the cursor to +// the given row and column. +// +// Default is 1,1. +// +// CSI n ; m f +// +// This has the same effect as [CursorPosition]. +// +// See: https://vt100.net/docs/vt510-rm/HVP.html +func HorizontalVerticalPosition(col, row int) string { + var r, c string + if row > 0 { + r = strconv.Itoa(row) + } + if col > 0 { + c = strconv.Itoa(col) + } + return "\x1b[" + r + ";" + c + "f" +} + +// HVP is an alias for [HorizontalVerticalPosition]. +func HVP(col, row int) string { + return HorizontalVerticalPosition(col, row) +} + +// HorizontalVerticalHomePosition is a sequence for moving the cursor to the +// upper left corner of the scrolling region. This is equivalent to +// `HorizontalVerticalPosition(1, 1)`. +const HorizontalVerticalHomePosition = "\x1b[f" + +// SaveCurrentCursorPosition (SCOSC) is a sequence for saving the current cursor +// position for SCO console mode. +// +// CSI s +// +// This acts like [DECSC], except the page number where the cursor is located +// is not saved. +// +// See: https://vt100.net/docs/vt510-rm/SCOSC.html +const ( + SaveCurrentCursorPosition = "\x1b[s" + SCOSC = SaveCurrentCursorPosition +) + +// SaveCursorPosition (SCP or SCOSC) is a sequence for saving the cursor +// position. +// +// CSI s +// +// This acts like Save, except the page number where the cursor is located is +// not saved. +// +// See: https://vt100.net/docs/vt510-rm/SCOSC.html +// +// Deprecated: use [SaveCurrentCursorPosition] instead. +const SaveCursorPosition = "\x1b[s" + +// RestoreCurrentCursorPosition (SCORC) is a sequence for restoring the current +// cursor position for SCO console mode. +// +// CSI u +// +// This acts like [DECRC], except the page number where the cursor was saved is +// not restored. +// +// See: https://vt100.net/docs/vt510-rm/SCORC.html +const ( + RestoreCurrentCursorPosition = "\x1b[u" + SCORC = RestoreCurrentCursorPosition +) + +// RestoreCursorPosition (RCP or SCORC) is a sequence for restoring the cursor +// position. +// +// CSI u +// +// This acts like Restore, except the cursor stays on the same page where the +// cursor was saved. +// +// See: https://vt100.net/docs/vt510-rm/SCORC.html +// +// Deprecated: use [RestoreCurrentCursorPosition] instead. +const RestoreCursorPosition = "\x1b[u" + +// SetCursorStyle (DECSCUSR) returns a sequence for changing the cursor style. +// +// Default is 1. +// +// CSI Ps SP q +// +// Where Ps is the cursor style: +// +// 0: Blinking block +// 1: Blinking block (default) +// 2: Steady block +// 3: Blinking underline +// 4: Steady underline +// 5: Blinking bar (xterm) +// 6: Steady bar (xterm) +// +// See: https://vt100.net/docs/vt510-rm/DECSCUSR.html +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-SP-q.1D81 +func SetCursorStyle(style int) string { + if style < 0 { + style = 0 + } + return "\x1b[" + strconv.Itoa(style) + " q" +} + +// DECSCUSR is an alias for [SetCursorStyle]. +func DECSCUSR(style int) string { + return SetCursorStyle(style) +} + +// SetPointerShape returns a sequence for changing the mouse pointer cursor +// shape. Use "default" for the default pointer shape. +// +// OSC 22 ; Pt ST +// OSC 22 ; Pt BEL +// +// Where Pt is the pointer shape name. The name can be anything that the +// operating system can understand. Some common names are: +// +// - copy +// - crosshair +// - default +// - ew-resize +// - n-resize +// - text +// - wait +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands +func SetPointerShape(shape string) string { + return "\x1b]22;" + shape + "\x07" +} + +// ReverseIndex (RI) is an escape sequence for moving the cursor up one line in +// the same column. If the cursor is at the top margin, the screen scrolls +// down. +// +// This has the same effect as [RI]. +const ReverseIndex = "\x1bM" + +// HorizontalPositionAbsolute (HPA) returns a sequence for moving the cursor to +// the given column. This has the same effect as [CUP]. +// +// Default is 1. +// +// CSI n ` +// +// See: https://vt100.net/docs/vt510-rm/HPA.html +func HorizontalPositionAbsolute(col int) string { + var s string + if col > 0 { + s = strconv.Itoa(col) + } + return "\x1b[" + s + "`" +} + +// HPA is an alias for [HorizontalPositionAbsolute]. +func HPA(col int) string { + return HorizontalPositionAbsolute(col) +} + +// HorizontalPositionRelative (HPR) returns a sequence for moving the cursor +// right n columns relative to the current position. This has the same effect +// as [CUP]. +// +// Default is 1. +// +// CSI n a +// +// See: https://vt100.net/docs/vt510-rm/HPR.html +func HorizontalPositionRelative(n int) string { + var s string + if n > 0 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "a" +} + +// HPR is an alias for [HorizontalPositionRelative]. +func HPR(n int) string { + return HorizontalPositionRelative(n) +} + +// Index (IND) is an escape sequence for moving the cursor down one line in the +// same column. If the cursor is at the bottom margin, the screen scrolls up. +// This has the same effect as [IND]. +const Index = "\x1bD" diff --git a/vendor/github.com/charmbracelet/x/ansi/cwd.go b/vendor/github.com/charmbracelet/x/ansi/cwd.go new file mode 100644 index 00000000..b03ac1bb --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/cwd.go @@ -0,0 +1,26 @@ +package ansi + +import ( + "net/url" + "path" +) + +// NotifyWorkingDirectory returns a sequence that notifies the terminal +// of the current working directory. +// +// OSC 7 ; Pt BEL +// +// Where Pt is a URL in the format "file://[host]/[path]". +// Set host to "localhost" if this is a path on the local computer. +// +// See: https://wezfurlong.org/wezterm/shell-integration.html#osc-7-escape-sequence-to-set-the-working-directory +// See: https://iterm2.com/documentation-escape-codes.html#:~:text=RemoteHost%20and%20CurrentDir%3A-,OSC%207,-%3B%20%5BPs%5D%20ST +func NotifyWorkingDirectory(host string, paths ...string) string { + path := path.Join(paths...) + u := &url.URL{ + Scheme: "file", + Host: host, + Path: path, + } + return "\x1b]7;" + u.String() + "\x07" +} diff --git a/vendor/github.com/charmbracelet/x/ansi/doc.go b/vendor/github.com/charmbracelet/x/ansi/doc.go new file mode 100644 index 00000000..e955e9f1 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/doc.go @@ -0,0 +1,7 @@ +// Package ansi defines common ANSI escape sequences based on the ECMA-48 +// specs. +// +// All sequences use 7-bit C1 control codes, which are supported by most +// terminal emulators. OSC sequences are terminated by a BEL for wider +// compatibility with terminals. +package ansi diff --git a/vendor/github.com/charmbracelet/x/ansi/finalterm.go b/vendor/github.com/charmbracelet/x/ansi/finalterm.go new file mode 100644 index 00000000..2c283472 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/finalterm.go @@ -0,0 +1,67 @@ +package ansi + +import "strings" + +// FinalTerm returns an escape sequence that is used for shell integrations. +// Originally, FinalTerm designed the protocol hence the name. +// +// OSC 133 ; Ps ; Pm ST +// OSC 133 ; Ps ; Pm BEL +// +// See: https://iterm2.com/documentation-shell-integration.html +func FinalTerm(pm ...string) string { + return "\x1b]133;" + strings.Join(pm, ";") + "\x07" +} + +// FinalTermPrompt returns an escape sequence that is used for shell +// integrations prompt marks. This is sent just before the start of the shell +// prompt. +// +// This is an alias for FinalTerm("A"). +func FinalTermPrompt(pm ...string) string { + if len(pm) == 0 { + return FinalTerm("A") + } + return FinalTerm(append([]string{"A"}, pm...)...) +} + +// FinalTermCmdStart returns an escape sequence that is used for shell +// integrations command start marks. This is sent just after the end of the +// shell prompt, before the user enters a command. +// +// This is an alias for FinalTerm("B"). +func FinalTermCmdStart(pm ...string) string { + if len(pm) == 0 { + return FinalTerm("B") + } + return FinalTerm(append([]string{"B"}, pm...)...) +} + +// FinalTermCmdExecuted returns an escape sequence that is used for shell +// integrations command executed marks. This is sent just before the start of +// the command output. +// +// This is an alias for FinalTerm("C"). +func FinalTermCmdExecuted(pm ...string) string { + if len(pm) == 0 { + return FinalTerm("C") + } + return FinalTerm(append([]string{"C"}, pm...)...) +} + +// FinalTermCmdFinished returns an escape sequence that is used for shell +// integrations command finished marks. +// +// If the command was sent after +// [FinalTermCmdStart], it indicates that the command was aborted. If the +// command was sent after [FinalTermCmdExecuted], it indicates the end of the +// command output. If neither was sent, [FinalTermCmdFinished] should be +// ignored. +// +// This is an alias for FinalTerm("D"). +func FinalTermCmdFinished(pm ...string) string { + if len(pm) == 0 { + return FinalTerm("D") + } + return FinalTerm(append([]string{"D"}, pm...)...) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/focus.go b/vendor/github.com/charmbracelet/x/ansi/focus.go new file mode 100644 index 00000000..4e0207ce --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/focus.go @@ -0,0 +1,9 @@ +package ansi + +// Focus is an escape sequence to notify the terminal that it has focus. +// This is used with [FocusEventMode]. +const Focus = "\x1b[I" + +// Blur is an escape sequence to notify the terminal that it has lost focus. +// This is used with [FocusEventMode]. +const Blur = "\x1b[O" diff --git a/vendor/github.com/charmbracelet/x/ansi/graphics.go b/vendor/github.com/charmbracelet/x/ansi/graphics.go new file mode 100644 index 00000000..b5b1dc82 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/graphics.go @@ -0,0 +1,237 @@ +package ansi + +import ( + "bytes" + "encoding/base64" + "errors" + "fmt" + "image" + "io" + "os" + "strconv" + "strings" + + "github.com/charmbracelet/x/ansi/kitty" +) + +// SixelGraphics returns a sequence that encodes the given sixel image payload to +// a DCS sixel sequence. +// +// DCS p1; p2; p3; q [sixel payload] ST +// +// p1 = pixel aspect ratio, deprecated and replaced by pixel metrics in the payload +// +// p2 = This is supposed to be 0 for transparency, but terminals don't seem to +// to use it properly. Value 0 leaves an unsightly black bar on all terminals +// I've tried and looks correct with value 1. +// +// p3 = Horizontal grid size parameter. Everyone ignores this and uses a fixed grid +// size, as far as I can tell. +// +// See https://shuford.invisible-island.net/all_about_sixels.txt +func SixelGraphics(p1, p2, p3 int, payload []byte) string { + var buf bytes.Buffer + + buf.WriteString("\x1bP") + if p1 >= 0 { + buf.WriteString(strconv.Itoa(p1)) + } + buf.WriteByte(';') + if p2 >= 0 { + buf.WriteString(strconv.Itoa(p2)) + } + if p3 > 0 { + buf.WriteByte(';') + buf.WriteString(strconv.Itoa(p3)) + } + buf.WriteByte('q') + buf.Write(payload) + buf.WriteString("\x1b\\") + + return buf.String() +} + +// KittyGraphics returns a sequence that encodes the given image in the Kitty +// graphics protocol. +// +// APC G [comma separated options] ; [base64 encoded payload] ST +// +// See https://sw.kovidgoyal.net/kitty/graphics-protocol/ +func KittyGraphics(payload []byte, opts ...string) string { + var buf bytes.Buffer + buf.WriteString("\x1b_G") + buf.WriteString(strings.Join(opts, ",")) + if len(payload) > 0 { + buf.WriteString(";") + buf.Write(payload) + } + buf.WriteString("\x1b\\") + return buf.String() +} + +var ( + // KittyGraphicsTempDir is the directory where temporary files are stored. + // This is used in [WriteKittyGraphics] along with [os.CreateTemp]. + KittyGraphicsTempDir = "" + + // KittyGraphicsTempPattern is the pattern used to create temporary files. + // This is used in [WriteKittyGraphics] along with [os.CreateTemp]. + // The Kitty Graphics protocol requires the file path to contain the + // substring "tty-graphics-protocol". + KittyGraphicsTempPattern = "tty-graphics-protocol-*" +) + +// EncodeKittyGraphics writes an image using the Kitty Graphics protocol with +// the given options to w. It chunks the written data if o.Chunk is true. +// +// You can omit m and use nil when rendering an image from a file. In this +// case, you must provide a file path in o.File and use o.Transmission = +// [kitty.File]. You can also use o.Transmission = [kitty.TempFile] to write +// the image to a temporary file. In that case, the file path is ignored, and +// the image is written to a temporary file that is automatically deleted by +// the terminal. +// +// See https://sw.kovidgoyal.net/kitty/graphics-protocol/ +func EncodeKittyGraphics(w io.Writer, m image.Image, o *kitty.Options) error { + if o == nil { + o = &kitty.Options{} + } + + if o.Transmission == 0 && len(o.File) != 0 { + o.Transmission = kitty.File + } + + var data bytes.Buffer // the data to be encoded into base64 + e := &kitty.Encoder{ + Compress: o.Compression == kitty.Zlib, + Format: o.Format, + } + + switch o.Transmission { + case kitty.Direct: + if err := e.Encode(&data, m); err != nil { + return fmt.Errorf("failed to encode direct image: %w", err) + } + + case kitty.SharedMemory: + // TODO: Implement shared memory + return fmt.Errorf("shared memory transmission is not yet implemented") + + case kitty.File: + if len(o.File) == 0 { + return kitty.ErrMissingFile + } + + f, err := os.Open(o.File) + if err != nil { + return fmt.Errorf("failed to open file: %w", err) + } + + defer f.Close() //nolint:errcheck + + stat, err := f.Stat() + if err != nil { + return fmt.Errorf("failed to get file info: %w", err) + } + + mode := stat.Mode() + if !mode.IsRegular() { + return fmt.Errorf("file is not a regular file") + } + + // Write the file path to the buffer + if _, err := data.WriteString(f.Name()); err != nil { + return fmt.Errorf("failed to write file path to buffer: %w", err) + } + + case kitty.TempFile: + f, err := os.CreateTemp(KittyGraphicsTempDir, KittyGraphicsTempPattern) + if err != nil { + return fmt.Errorf("failed to create file: %w", err) + } + + defer f.Close() //nolint:errcheck + + if err := e.Encode(f, m); err != nil { + return fmt.Errorf("failed to encode image to file: %w", err) + } + + // Write the file path to the buffer + if _, err := data.WriteString(f.Name()); err != nil { + return fmt.Errorf("failed to write file path to buffer: %w", err) + } + } + + // Encode image to base64 + var payload bytes.Buffer // the base64 encoded image to be written to w + b64 := base64.NewEncoder(base64.StdEncoding, &payload) + if _, err := data.WriteTo(b64); err != nil { + return fmt.Errorf("failed to write base64 encoded image to payload: %w", err) + } + if err := b64.Close(); err != nil { + return err + } + + // If not chunking, write all at once + if !o.Chunk { + _, err := io.WriteString(w, KittyGraphics(payload.Bytes(), o.Options()...)) + return err + } + + // Write in chunks + var ( + err error + n int + ) + chunk := make([]byte, kitty.MaxChunkSize) + isFirstChunk := true + + for { + // Stop if we read less than the chunk size [kitty.MaxChunkSize]. + n, err = io.ReadFull(&payload, chunk) + if errors.Is(err, io.ErrUnexpectedEOF) || errors.Is(err, io.EOF) { + break + } + if err != nil { + return fmt.Errorf("failed to read chunk: %w", err) + } + + opts := buildChunkOptions(o, isFirstChunk, false) + if _, err := io.WriteString(w, KittyGraphics(chunk[:n], opts...)); err != nil { + return err + } + + isFirstChunk = false + } + + // Write the last chunk + opts := buildChunkOptions(o, isFirstChunk, true) + _, err = io.WriteString(w, KittyGraphics(chunk[:n], opts...)) + return err +} + +// buildChunkOptions creates the options slice for a chunk +func buildChunkOptions(o *kitty.Options, isFirstChunk, isLastChunk bool) []string { + var opts []string + if isFirstChunk { + opts = o.Options() + } else { + // These options are allowed in subsequent chunks + if o.Quite > 0 { + opts = append(opts, fmt.Sprintf("q=%d", o.Quite)) + } + if o.Action == kitty.Frame { + opts = append(opts, "a=f") + } + } + + if !isFirstChunk || !isLastChunk { + // We don't need to encode the (m=) option when we only have one chunk. + if isLastChunk { + opts = append(opts, "m=0") + } else { + opts = append(opts, "m=1") + } + } + return opts +} diff --git a/vendor/github.com/charmbracelet/x/ansi/hyperlink.go b/vendor/github.com/charmbracelet/x/ansi/hyperlink.go new file mode 100644 index 00000000..323bfe93 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/hyperlink.go @@ -0,0 +1,28 @@ +package ansi + +import "strings" + +// SetHyperlink returns a sequence for starting a hyperlink. +// +// OSC 8 ; Params ; Uri ST +// OSC 8 ; Params ; Uri BEL +// +// To reset the hyperlink, omit the URI. +// +// See: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda +func SetHyperlink(uri string, params ...string) string { + var p string + if len(params) > 0 { + p = strings.Join(params, ":") + } + return "\x1b]8;" + p + ";" + uri + "\x07" +} + +// ResetHyperlink returns a sequence for resetting the hyperlink. +// +// This is equivalent to SetHyperlink("", params...). +// +// See: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda +func ResetHyperlink(params ...string) string { + return SetHyperlink("", params...) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/iterm2.go b/vendor/github.com/charmbracelet/x/ansi/iterm2.go new file mode 100644 index 00000000..0ecb336d --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/iterm2.go @@ -0,0 +1,18 @@ +package ansi + +import "fmt" + +// ITerm2 returns a sequence that uses the iTerm2 proprietary protocol. Use the +// iterm2 package for a more convenient API. +// +// OSC 1337 ; key = value ST +// +// Example: +// +// ITerm2(iterm2.File{...}) +// +// See https://iterm2.com/documentation-escape-codes.html +// See https://iterm2.com/documentation-images.html +func ITerm2(data any) string { + return "\x1b]1337;" + fmt.Sprint(data) + "\x07" +} diff --git a/vendor/github.com/charmbracelet/x/ansi/keypad.go b/vendor/github.com/charmbracelet/x/ansi/keypad.go new file mode 100644 index 00000000..9183c6a7 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/keypad.go @@ -0,0 +1,28 @@ +package ansi + +// Keypad Application Mode (DECKPAM) is a mode that determines whether the +// keypad sends application sequences or ANSI sequences. +// +// This works like enabling [DECNKM]. +// Use [NumericKeypadMode] to set the numeric keypad mode. +// +// ESC = +// +// See: https://vt100.net/docs/vt510-rm/DECKPAM.html +const ( + KeypadApplicationMode = "\x1b=" + DECKPAM = KeypadApplicationMode +) + +// Keypad Numeric Mode (DECKPNM) is a mode that determines whether the keypad +// sends application sequences or ANSI sequences. +// +// This works the same as disabling [DECNKM]. +// +// ESC > +// +// See: https://vt100.net/docs/vt510-rm/DECKPNM.html +const ( + KeypadNumericMode = "\x1b>" + DECKPNM = KeypadNumericMode +) diff --git a/vendor/github.com/charmbracelet/x/ansi/kitty.go b/vendor/github.com/charmbracelet/x/ansi/kitty.go new file mode 100644 index 00000000..124ab839 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/kitty.go @@ -0,0 +1,90 @@ +package ansi + +import "strconv" + +// Kitty keyboard protocol progressive enhancement flags. +// See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement +const ( + KittyDisambiguateEscapeCodes = 1 << iota + KittyReportEventTypes + KittyReportAlternateKeys + KittyReportAllKeysAsEscapeCodes + KittyReportAssociatedKeys + + KittyAllFlags = KittyDisambiguateEscapeCodes | KittyReportEventTypes | + KittyReportAlternateKeys | KittyReportAllKeysAsEscapeCodes | KittyReportAssociatedKeys +) + +// RequestKittyKeyboard is a sequence to request the terminal Kitty keyboard +// protocol enabled flags. +// +// See: https://sw.kovidgoyal.net/kitty/keyboard-protocol/ +const RequestKittyKeyboard = "\x1b[?u" + +// KittyKeyboard returns a sequence to request keyboard enhancements from the terminal. +// The flags argument is a bitmask of the Kitty keyboard protocol flags. While +// mode specifies how the flags should be interpreted. +// +// Possible values for flags mask: +// +// 1: Disambiguate escape codes +// 2: Report event types +// 4: Report alternate keys +// 8: Report all keys as escape codes +// 16: Report associated text +// +// Possible values for mode: +// +// 1: Set given flags and unset all others +// 2: Set given flags and keep existing flags unchanged +// 3: Unset given flags and keep existing flags unchanged +// +// See https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement +func KittyKeyboard(flags, mode int) string { + return "\x1b[=" + strconv.Itoa(flags) + ";" + strconv.Itoa(mode) + "u" +} + +// PushKittyKeyboard returns a sequence to push the given flags to the terminal +// Kitty Keyboard stack. +// +// Possible values for flags mask: +// +// 0: Disable all features +// 1: Disambiguate escape codes +// 2: Report event types +// 4: Report alternate keys +// 8: Report all keys as escape codes +// 16: Report associated text +// +// CSI > flags u +// +// See https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement +func PushKittyKeyboard(flags int) string { + var f string + if flags > 0 { + f = strconv.Itoa(flags) + } + + return "\x1b[>" + f + "u" +} + +// DisableKittyKeyboard is a sequence to push zero into the terminal Kitty +// Keyboard stack to disable the protocol. +// +// This is equivalent to PushKittyKeyboard(0). +const DisableKittyKeyboard = "\x1b[>u" + +// PopKittyKeyboard returns a sequence to pop n number of flags from the +// terminal Kitty Keyboard stack. +// +// CSI < flags u +// +// See https://sw.kovidgoyal.net/kitty/keyboard-protocol/#progressive-enhancement +func PopKittyKeyboard(n int) string { + var num string + if n > 0 { + num = strconv.Itoa(n) + } + + return "\x1b[<" + num + "u" +} diff --git a/vendor/github.com/charmbracelet/x/ansi/kitty/decoder.go b/vendor/github.com/charmbracelet/x/ansi/kitty/decoder.go new file mode 100644 index 00000000..1559c69e --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/kitty/decoder.go @@ -0,0 +1,85 @@ +package kitty + +import ( + "compress/zlib" + "fmt" + "image" + "image/color" + "image/png" + "io" +) + +// Decoder is a decoder for the Kitty graphics protocol. It supports decoding +// images in the 24-bit [RGB], 32-bit [RGBA], and [PNG] formats. It can also +// decompress data using zlib. +// The default format is 32-bit [RGBA]. +type Decoder struct { + // Uses zlib decompression. + Decompress bool + + // Can be one of [RGB], [RGBA], or [PNG]. + Format int + + // Width of the image in pixels. This can be omitted if the image is [PNG] + // formatted. + Width int + + // Height of the image in pixels. This can be omitted if the image is [PNG] + // formatted. + Height int +} + +// Decode decodes the image data from r in the specified format. +func (d *Decoder) Decode(r io.Reader) (image.Image, error) { + if d.Decompress { + zr, err := zlib.NewReader(r) + if err != nil { + return nil, fmt.Errorf("failed to create zlib reader: %w", err) + } + + defer zr.Close() //nolint:errcheck + r = zr + } + + if d.Format == 0 { + d.Format = RGBA + } + + switch d.Format { + case RGBA, RGB: + return d.decodeRGBA(r, d.Format == RGBA) + + case PNG: + return png.Decode(r) + + default: + return nil, fmt.Errorf("unsupported format: %d", d.Format) + } +} + +// decodeRGBA decodes the image data in 32-bit RGBA or 24-bit RGB formats. +func (d *Decoder) decodeRGBA(r io.Reader, alpha bool) (image.Image, error) { + m := image.NewRGBA(image.Rect(0, 0, d.Width, d.Height)) + + var buf []byte + if alpha { + buf = make([]byte, 4) + } else { + buf = make([]byte, 3) + } + + for y := range d.Height { + for x := range d.Width { + if _, err := io.ReadFull(r, buf[:]); err != nil { + return nil, fmt.Errorf("failed to read pixel data: %w", err) + } + if alpha { + m.SetRGBA(x, y, color.RGBA{buf[0], buf[1], buf[2], buf[3]}) + } else { + m.SetRGBA(x, y, color.RGBA{buf[0], buf[1], buf[2], 0xff}) + } + } + } + + return m, nil +} diff --git a/vendor/github.com/charmbracelet/x/ansi/kitty/encoder.go b/vendor/github.com/charmbracelet/x/ansi/kitty/encoder.go new file mode 100644 index 00000000..f668b9e3 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/kitty/encoder.go @@ -0,0 +1,64 @@ +package kitty + +import ( + "compress/zlib" + "fmt" + "image" + "image/png" + "io" +) + +// Encoder is an encoder for the Kitty graphics protocol. It supports encoding +// images in the 24-bit [RGB], 32-bit [RGBA], and [PNG] formats, and +// compressing the data using zlib. +// The default format is 32-bit [RGBA]. +type Encoder struct { + // Uses zlib compression. + Compress bool + + // Can be one of [RGBA], [RGB], or [PNG]. + Format int +} + +// Encode encodes the image data in the specified format and writes it to w. +func (e *Encoder) Encode(w io.Writer, m image.Image) error { + if m == nil { + return nil + } + + if e.Compress { + zw := zlib.NewWriter(w) + defer zw.Close() //nolint:errcheck + w = zw + } + + if e.Format == 0 { + e.Format = RGBA + } + + switch e.Format { + case RGBA, RGB: + bounds := m.Bounds() + for y := bounds.Min.Y; y < bounds.Max.Y; y++ { + for x := bounds.Min.X; x < bounds.Max.X; x++ { + r, g, b, a := m.At(x, y).RGBA() + switch e.Format { + case RGBA: + w.Write([]byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)}) //nolint:errcheck + case RGB: + w.Write([]byte{byte(r >> 8), byte(g >> 8), byte(b >> 8)}) //nolint:errcheck + } + } + } + + case PNG: + if err := png.Encode(w, m); err != nil { + return fmt.Errorf("failed to encode PNG: %w", err) + } + + default: + return fmt.Errorf("unsupported format: %d", e.Format) + } + + return nil +} diff --git a/vendor/github.com/charmbracelet/x/ansi/kitty/graphics.go b/vendor/github.com/charmbracelet/x/ansi/kitty/graphics.go new file mode 100644 index 00000000..490e7a8a --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/kitty/graphics.go @@ -0,0 +1,414 @@ +package kitty + +import "errors" + +// ErrMissingFile is returned when the file path is missing. +var ErrMissingFile = errors.New("missing file path") + +// MaxChunkSize is the maximum chunk size for the image data. +const MaxChunkSize = 1024 * 4 + +// Placeholder is a special Unicode character that can be used as a placeholder +// for an image. +const Placeholder = '\U0010EEEE' + +// Graphics image format. +const ( + // 32-bit RGBA format. + RGBA = 32 + + // 24-bit RGB format. + RGB = 24 + + // PNG format. + PNG = 100 +) + +// Compression types. +const ( + Zlib = 'z' +) + +// Transmission types. +const ( + // The data transmitted directly in the escape sequence. + Direct = 'd' + + // The data transmitted in a regular file. + File = 'f' + + // A temporary file is used and deleted after transmission. + TempFile = 't' + + // A shared memory object. + // For POSIX see https://pubs.opengroup.org/onlinepubs/9699919799/functions/shm_open.html + // For Windows see https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory + SharedMemory = 's' +) + +// Action types. +const ( + // Transmit image data. + Transmit = 't' + // TransmitAndPut transmit image data and display (put) it. + TransmitAndPut = 'T' + // Query terminal for image info. + Query = 'q' + // Put (display) previously transmitted image. + Put = 'p' + // Delete image. + Delete = 'd' + // Frame transmits data for animation frames. + Frame = 'f' + // Animate controls animation. + Animate = 'a' + // Compose composes animation frames. + Compose = 'c' +) + +// Delete types. +const ( + // Delete all placements visible on screen + DeleteAll = 'a' + // Delete all images with the specified id, specified using the i key. If + // you specify a p key for the placement id as well, then only the + // placement with the specified image id and placement id will be deleted. + DeleteID = 'i' + // Delete newest image with the specified number, specified using the I + // key. If you specify a p key for the placement id as well, then only the + // placement with the specified number and placement id will be deleted. + DeleteNumber = 'n' + // Delete all placements that intersect with the current cursor position. + DeleteCursor = 'c' + // Delete animation frames. + DeleteFrames = 'f' + // Delete all placements that intersect a specific cell, the cell is + // specified using the x and y keys + DeleteCell = 'p' + // Delete all placements that intersect a specific cell having a specific + // z-index. The cell and z-index is specified using the x, y and z keys. + DeleteCellZ = 'q' + // Delete all images whose id is greater than or equal to the value of the x + // key and less than or equal to the value of the y. + DeleteRange = 'r' + // Delete all placements that intersect the specified column, specified using + // the x key. + DeleteColumn = 'x' + // Delete all placements that intersect the specified row, specified using + // the y key. + DeleteRow = 'y' + // Delete all placements that have the specified z-index, specified using the + // z key. + DeleteZ = 'z' +) + +// Diacritic returns the diacritic rune at the specified index. If the index is +// out of bounds, the first diacritic rune is returned. +func Diacritic(i int) rune { + if i < 0 || i >= len(diacritics) { + return diacritics[0] + } + return diacritics[i] +} + +// From https://sw.kovidgoyal.net/kitty/_downloads/f0a0de9ec8d9ff4456206db8e0814937/rowcolumn-diacritics.txt +// See https://sw.kovidgoyal.net/kitty/graphics-protocol/#unicode-placeholders for further explanation. +var diacritics = []rune{ + '\u0305', + '\u030D', + '\u030E', + '\u0310', + '\u0312', + '\u033D', + '\u033E', + '\u033F', + '\u0346', + '\u034A', + '\u034B', + '\u034C', + '\u0350', + '\u0351', + '\u0352', + '\u0357', + '\u035B', + '\u0363', + '\u0364', + '\u0365', + '\u0366', + '\u0367', + '\u0368', + '\u0369', + '\u036A', + '\u036B', + '\u036C', + '\u036D', + '\u036E', + '\u036F', + '\u0483', + '\u0484', + '\u0485', + '\u0486', + '\u0487', + '\u0592', + '\u0593', + '\u0594', + '\u0595', + '\u0597', + '\u0598', + '\u0599', + '\u059C', + '\u059D', + '\u059E', + '\u059F', + '\u05A0', + '\u05A1', + '\u05A8', + '\u05A9', + '\u05AB', + '\u05AC', + '\u05AF', + '\u05C4', + '\u0610', + '\u0611', + '\u0612', + '\u0613', + '\u0614', + '\u0615', + '\u0616', + '\u0617', + '\u0657', + '\u0658', + '\u0659', + '\u065A', + '\u065B', + '\u065D', + '\u065E', + '\u06D6', + '\u06D7', + '\u06D8', + '\u06D9', + '\u06DA', + '\u06DB', + '\u06DC', + '\u06DF', + '\u06E0', + '\u06E1', + '\u06E2', + '\u06E4', + '\u06E7', + '\u06E8', + '\u06EB', + '\u06EC', + '\u0730', + '\u0732', + '\u0733', + '\u0735', + '\u0736', + '\u073A', + '\u073D', + '\u073F', + '\u0740', + '\u0741', + '\u0743', + '\u0745', + '\u0747', + '\u0749', + '\u074A', + '\u07EB', + '\u07EC', + '\u07ED', + '\u07EE', + '\u07EF', + '\u07F0', + '\u07F1', + '\u07F3', + '\u0816', + '\u0817', + '\u0818', + '\u0819', + '\u081B', + '\u081C', + '\u081D', + '\u081E', + '\u081F', + '\u0820', + '\u0821', + '\u0822', + '\u0823', + '\u0825', + '\u0826', + '\u0827', + '\u0829', + '\u082A', + '\u082B', + '\u082C', + '\u082D', + '\u0951', + '\u0953', + '\u0954', + '\u0F82', + '\u0F83', + '\u0F86', + '\u0F87', + '\u135D', + '\u135E', + '\u135F', + '\u17DD', + '\u193A', + '\u1A17', + '\u1A75', + '\u1A76', + '\u1A77', + '\u1A78', + '\u1A79', + '\u1A7A', + '\u1A7B', + '\u1A7C', + '\u1B6B', + '\u1B6D', + '\u1B6E', + '\u1B6F', + '\u1B70', + '\u1B71', + '\u1B72', + '\u1B73', + '\u1CD0', + '\u1CD1', + '\u1CD2', + '\u1CDA', + '\u1CDB', + '\u1CE0', + '\u1DC0', + '\u1DC1', + '\u1DC3', + '\u1DC4', + '\u1DC5', + '\u1DC6', + '\u1DC7', + '\u1DC8', + '\u1DC9', + '\u1DCB', + '\u1DCC', + '\u1DD1', + '\u1DD2', + '\u1DD3', + '\u1DD4', + '\u1DD5', + '\u1DD6', + '\u1DD7', + '\u1DD8', + '\u1DD9', + '\u1DDA', + '\u1DDB', + '\u1DDC', + '\u1DDD', + '\u1DDE', + '\u1DDF', + '\u1DE0', + '\u1DE1', + '\u1DE2', + '\u1DE3', + '\u1DE4', + '\u1DE5', + '\u1DE6', + '\u1DFE', + '\u20D0', + '\u20D1', + '\u20D4', + '\u20D5', + '\u20D6', + '\u20D7', + '\u20DB', + '\u20DC', + '\u20E1', + '\u20E7', + '\u20E9', + '\u20F0', + '\u2CEF', + '\u2CF0', + '\u2CF1', + '\u2DE0', + '\u2DE1', + '\u2DE2', + '\u2DE3', + '\u2DE4', + '\u2DE5', + '\u2DE6', + '\u2DE7', + '\u2DE8', + '\u2DE9', + '\u2DEA', + '\u2DEB', + '\u2DEC', + '\u2DED', + '\u2DEE', + '\u2DEF', + '\u2DF0', + '\u2DF1', + '\u2DF2', + '\u2DF3', + '\u2DF4', + '\u2DF5', + '\u2DF6', + '\u2DF7', + '\u2DF8', + '\u2DF9', + '\u2DFA', + '\u2DFB', + '\u2DFC', + '\u2DFD', + '\u2DFE', + '\u2DFF', + '\uA66F', + '\uA67C', + '\uA67D', + '\uA6F0', + '\uA6F1', + '\uA8E0', + '\uA8E1', + '\uA8E2', + '\uA8E3', + '\uA8E4', + '\uA8E5', + '\uA8E6', + '\uA8E7', + '\uA8E8', + '\uA8E9', + '\uA8EA', + '\uA8EB', + '\uA8EC', + '\uA8ED', + '\uA8EE', + '\uA8EF', + '\uA8F0', + '\uA8F1', + '\uAAB0', + '\uAAB2', + '\uAAB3', + '\uAAB7', + '\uAAB8', + '\uAABE', + '\uAABF', + '\uAAC1', + '\uFE20', + '\uFE21', + '\uFE22', + '\uFE23', + '\uFE24', + '\uFE25', + '\uFE26', + '\U00010A0F', + '\U00010A38', + '\U0001D185', + '\U0001D186', + '\U0001D187', + '\U0001D188', + '\U0001D189', + '\U0001D1AA', + '\U0001D1AB', + '\U0001D1AC', + '\U0001D1AD', + '\U0001D242', + '\U0001D243', + '\U0001D244', +} diff --git a/vendor/github.com/charmbracelet/x/ansi/kitty/options.go b/vendor/github.com/charmbracelet/x/ansi/kitty/options.go new file mode 100644 index 00000000..a8d907bd --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/kitty/options.go @@ -0,0 +1,367 @@ +package kitty + +import ( + "encoding" + "fmt" + "strconv" + "strings" +) + +var ( + _ encoding.TextMarshaler = Options{} + _ encoding.TextUnmarshaler = &Options{} +) + +// Options represents a Kitty Graphics Protocol options. +type Options struct { + // Common options. + + // Action (a=t) is the action to be performed on the image. Can be one of + // [Transmit], [TransmitDisplay], [Query], [Put], [Delete], [Frame], + // [Animate], [Compose]. + Action byte + + // Quite mode (q=0) is the quiet mode. Can be either zero, one, or two + // where zero is the default, 1 suppresses OK responses, and 2 suppresses + // both OK and error responses. + Quite byte + + // Transmission options. + + // ID (i=) is the image ID. The ID is a unique identifier for the image. + // Must be a positive integer up to [math.MaxUint32]. + ID int + + // PlacementID (p=) is the placement ID. The placement ID is a unique + // identifier for the placement of the image. Must be a positive integer up + // to [math.MaxUint32]. + PlacementID int + + // Number (I=0) is the number of images to be transmitted. + Number int + + // Format (f=32) is the image format. One of [RGBA], [RGB], [PNG]. + Format int + + // ImageWidth (s=0) is the transmitted image width. + ImageWidth int + + // ImageHeight (v=0) is the transmitted image height. + ImageHeight int + + // Compression (o=) is the image compression type. Can be [Zlib] or zero. + Compression byte + + // Transmission (t=d) is the image transmission type. Can be [Direct], [File], + // [TempFile], or[SharedMemory]. + Transmission byte + + // File is the file path to be used when the transmission type is [File]. + // If [Options.Transmission] is omitted i.e. zero and this is non-empty, + // the transmission type is set to [File]. + File string + + // Size (S=0) is the size to be read from the transmission medium. + Size int + + // Offset (O=0) is the offset byte to start reading from the transmission + // medium. + Offset int + + // Chunk (m=) whether the image is transmitted in chunks. Can be either + // zero or one. When true, the image is transmitted in chunks. Each chunk + // must be a multiple of 4, and up to [MaxChunkSize] bytes. Each chunk must + // have the m=1 option except for the last chunk which must have m=0. + Chunk bool + + // Display options. + + // X (x=0) is the pixel X coordinate of the image to start displaying. + X int + + // Y (y=0) is the pixel Y coordinate of the image to start displaying. + Y int + + // Z (z=0) is the Z coordinate of the image to display. + Z int + + // Width (w=0) is the width of the image to display. + Width int + + // Height (h=0) is the height of the image to display. + Height int + + // OffsetX (X=0) is the OffsetX coordinate of the cursor cell to start + // displaying the image. OffsetX=0 is the leftmost cell. This must be + // smaller than the terminal cell width. + OffsetX int + + // OffsetY (Y=0) is the OffsetY coordinate of the cursor cell to start + // displaying the image. OffsetY=0 is the topmost cell. This must be + // smaller than the terminal cell height. + OffsetY int + + // Columns (c=0) is the number of columns to display the image. The image + // will be scaled to fit the number of columns. + Columns int + + // Rows (r=0) is the number of rows to display the image. The image will be + // scaled to fit the number of rows. + Rows int + + // VirtualPlacement (U=0) whether to use virtual placement. This is used + // with Unicode [Placeholder] to display images. + VirtualPlacement bool + + // DoNotMoveCursor (C=0) whether to move the cursor after displaying the + // image. + DoNotMoveCursor bool + + // ParentID (P=0) is the parent image ID. The parent ID is the ID of the + // image that is the parent of the current image. This is used with Unicode + // [Placeholder] to display images relative to the parent image. + ParentID int + + // ParentPlacementID (Q=0) is the parent placement ID. The parent placement + // ID is the ID of the placement of the parent image. This is used with + // Unicode [Placeholder] to display images relative to the parent image. + ParentPlacementID int + + // Delete options. + + // Delete (d=a) is the delete action. Can be one of [DeleteAll], + // [DeleteID], [DeleteNumber], [DeleteCursor], [DeleteFrames], + // [DeleteCell], [DeleteCellZ], [DeleteRange], [DeleteColumn], [DeleteRow], + // [DeleteZ]. + Delete byte + + // DeleteResources indicates whether to delete the resources associated + // with the image. + DeleteResources bool +} + +// Options returns the options as a slice of a key-value pairs. +func (o *Options) Options() (opts []string) { + opts = []string{} + if o.Format == 0 { + o.Format = RGBA + } + + if o.Action == 0 { + o.Action = Transmit + } + + if o.Delete == 0 { + o.Delete = DeleteAll + } + + if o.Transmission == 0 { + if len(o.File) > 0 { + o.Transmission = File + } else { + o.Transmission = Direct + } + } + + if o.Format != RGBA { + opts = append(opts, fmt.Sprintf("f=%d", o.Format)) + } + + if o.Quite > 0 { + opts = append(opts, fmt.Sprintf("q=%d", o.Quite)) + } + + if o.ID > 0 { + opts = append(opts, fmt.Sprintf("i=%d", o.ID)) + } + + if o.PlacementID > 0 { + opts = append(opts, fmt.Sprintf("p=%d", o.PlacementID)) + } + + if o.Number > 0 { + opts = append(opts, fmt.Sprintf("I=%d", o.Number)) + } + + if o.ImageWidth > 0 { + opts = append(opts, fmt.Sprintf("s=%d", o.ImageWidth)) + } + + if o.ImageHeight > 0 { + opts = append(opts, fmt.Sprintf("v=%d", o.ImageHeight)) + } + + if o.Transmission != Direct { + opts = append(opts, fmt.Sprintf("t=%c", o.Transmission)) + } + + if o.Size > 0 { + opts = append(opts, fmt.Sprintf("S=%d", o.Size)) + } + + if o.Offset > 0 { + opts = append(opts, fmt.Sprintf("O=%d", o.Offset)) + } + + if o.Compression == Zlib { + opts = append(opts, fmt.Sprintf("o=%c", o.Compression)) + } + + if o.VirtualPlacement { + opts = append(opts, "U=1") + } + + if o.DoNotMoveCursor { + opts = append(opts, "C=1") + } + + if o.ParentID > 0 { + opts = append(opts, fmt.Sprintf("P=%d", o.ParentID)) + } + + if o.ParentPlacementID > 0 { + opts = append(opts, fmt.Sprintf("Q=%d", o.ParentPlacementID)) + } + + if o.X > 0 { + opts = append(opts, fmt.Sprintf("x=%d", o.X)) + } + + if o.Y > 0 { + opts = append(opts, fmt.Sprintf("y=%d", o.Y)) + } + + if o.Z > 0 { + opts = append(opts, fmt.Sprintf("z=%d", o.Z)) + } + + if o.Width > 0 { + opts = append(opts, fmt.Sprintf("w=%d", o.Width)) + } + + if o.Height > 0 { + opts = append(opts, fmt.Sprintf("h=%d", o.Height)) + } + + if o.OffsetX > 0 { + opts = append(opts, fmt.Sprintf("X=%d", o.OffsetX)) + } + + if o.OffsetY > 0 { + opts = append(opts, fmt.Sprintf("Y=%d", o.OffsetY)) + } + + if o.Columns > 0 { + opts = append(opts, fmt.Sprintf("c=%d", o.Columns)) + } + + if o.Rows > 0 { + opts = append(opts, fmt.Sprintf("r=%d", o.Rows)) + } + + if o.Delete != DeleteAll || o.DeleteResources { + da := o.Delete + if o.DeleteResources { + da = da - ' ' // to uppercase + } + + opts = append(opts, fmt.Sprintf("d=%c", da)) + } + + if o.Action != Transmit { + opts = append(opts, fmt.Sprintf("a=%c", o.Action)) + } + + return +} + +// String returns the string representation of the options. +func (o Options) String() string { + return strings.Join(o.Options(), ",") +} + +// MarshalText returns the string representation of the options. +func (o Options) MarshalText() ([]byte, error) { + return []byte(o.String()), nil +} + +// UnmarshalText parses the options from the given string. +func (o *Options) UnmarshalText(text []byte) error { + opts := strings.Split(string(text), ",") + for _, opt := range opts { + ps := strings.SplitN(opt, "=", 2) + if len(ps) != 2 || len(ps[1]) == 0 { + continue + } + + switch ps[0] { + case "a": + o.Action = ps[1][0] + case "o": + o.Compression = ps[1][0] + case "t": + o.Transmission = ps[1][0] + case "d": + d := ps[1][0] + if d >= 'A' && d <= 'Z' { + o.DeleteResources = true + d = d + ' ' // to lowercase + } + o.Delete = d + case "i", "q", "p", "I", "f", "s", "v", "S", "O", "m", "x", "y", "z", "w", "h", "X", "Y", "c", "r", "U", "P", "Q": + v, err := strconv.Atoi(ps[1]) + if err != nil { + continue + } + + switch ps[0] { + case "i": + o.ID = v + case "q": + o.Quite = byte(v) + case "p": + o.PlacementID = v + case "I": + o.Number = v + case "f": + o.Format = v + case "s": + o.ImageWidth = v + case "v": + o.ImageHeight = v + case "S": + o.Size = v + case "O": + o.Offset = v + case "m": + o.Chunk = v == 0 || v == 1 + case "x": + o.X = v + case "y": + o.Y = v + case "z": + o.Z = v + case "w": + o.Width = v + case "h": + o.Height = v + case "X": + o.OffsetX = v + case "Y": + o.OffsetY = v + case "c": + o.Columns = v + case "r": + o.Rows = v + case "U": + o.VirtualPlacement = v == 1 + case "P": + o.ParentID = v + case "Q": + o.ParentPlacementID = v + } + } + } + + return nil +} diff --git a/vendor/github.com/charmbracelet/x/ansi/method.go b/vendor/github.com/charmbracelet/x/ansi/method.go new file mode 100644 index 00000000..0218809c --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/method.go @@ -0,0 +1,172 @@ +package ansi + +// Method is a type that represents the how the renderer should calculate the +// display width of cells. +type Method uint8 + +// Display width modes. +const ( + WcWidth Method = iota + GraphemeWidth +) + +// StringWidth returns the width of a string in cells. This is the number of +// cells that the string will occupy when printed in a terminal. ANSI escape +// codes are ignored and wide characters (such as East Asians and emojis) are +// accounted for. +func (m Method) StringWidth(s string) int { + return stringWidth(m, s) +} + +// Truncate truncates a string to a given length, adding a tail to the end if +// the string is longer than the given length. This function is aware of ANSI +// escape codes and will not break them, and accounts for wide-characters (such +// as East-Asian characters and emojis). +func (m Method) Truncate(s string, length int, tail string) string { + return truncate(m, s, length, tail) +} + +// TruncateLeft truncates a string to a given length, adding a prefix to the +// beginning if the string is longer than the given length. This function is +// aware of ANSI escape codes and will not break them, and accounts for +// wide-characters (such as East-Asian characters and emojis). +func (m Method) TruncateLeft(s string, length int, prefix string) string { + return truncateLeft(m, s, length, prefix) +} + +// Cut the string, without adding any prefix or tail strings. This function is +// aware of ANSI escape codes and will not break them, and accounts for +// wide-characters (such as East-Asian characters and emojis). Note that the +// [left] parameter is inclusive, while [right] isn't. +func (m Method) Cut(s string, left, right int) string { + return cut(m, s, left, right) +} + +// Hardwrap wraps a string or a block of text to a given line length, breaking +// word boundaries. This will preserve ANSI escape codes and will account for +// wide-characters in the string. +// When preserveSpace is true, spaces at the beginning of a line will be +// preserved. +// This treats the text as a sequence of graphemes. +func (m Method) Hardwrap(s string, length int, preserveSpace bool) string { + return hardwrap(m, s, length, preserveSpace) +} + +// Wordwrap wraps a string or a block of text to a given line length, not +// breaking word boundaries. This will preserve ANSI escape codes and will +// account for wide-characters in the string. +// The breakpoints string is a list of characters that are considered +// breakpoints for word wrapping. A hyphen (-) is always considered a +// breakpoint. +// +// Note: breakpoints must be a string of 1-cell wide rune characters. +func (m Method) Wordwrap(s string, length int, breakpoints string) string { + return wordwrap(m, s, length, breakpoints) +} + +// Wrap wraps a string or a block of text to a given line length, breaking word +// boundaries if necessary. This will preserve ANSI escape codes and will +// account for wide-characters in the string. The breakpoints string is a list +// of characters that are considered breakpoints for word wrapping. A hyphen +// (-) is always considered a breakpoint. +// +// Note: breakpoints must be a string of 1-cell wide rune characters. +func (m Method) Wrap(s string, length int, breakpoints string) string { + return wrap(m, s, length, breakpoints) +} + +// DecodeSequence decodes the first ANSI escape sequence or a printable +// grapheme from the given data. It returns the sequence slice, the number of +// bytes read, the cell width for each sequence, and the new state. +// +// The cell width will always be 0 for control and escape sequences, 1 for +// ASCII printable characters, and the number of cells other Unicode characters +// occupy. It uses the uniseg package to calculate the width of Unicode +// graphemes and characters. This means it will always do grapheme clustering +// (mode 2027). +// +// Passing a non-nil [*Parser] as the last argument will allow the decoder to +// collect sequence parameters, data, and commands. The parser cmd will have +// the packed command value that contains intermediate and prefix characters. +// In the case of a OSC sequence, the cmd will be the OSC command number. Use +// [Cmd] and [Param] types to unpack command intermediates and prefixes as well +// as parameters. +// +// Zero [Cmd] means the CSI, DCS, or ESC sequence is invalid. Moreover, checking the +// validity of other data sequences, OSC, DCS, etc, will require checking for +// the returned sequence terminator bytes such as ST (ESC \\) and BEL). +// +// We store the command byte in [Cmd] in the most significant byte, the +// prefix byte in the next byte, and the intermediate byte in the least +// significant byte. This is done to avoid using a struct to store the command +// and its intermediates and prefixes. The command byte is always the least +// significant byte i.e. [Cmd & 0xff]. Use the [Cmd] type to unpack the +// command, intermediate, and prefix bytes. Note that we only collect the last +// prefix character and intermediate byte. +// +// The [p.Params] slice will contain the parameters of the sequence. Any +// sub-parameter will have the [parser.HasMoreFlag] set. Use the [Param] type +// to unpack the parameters. +// +// Example: +// +// var state byte // the initial state is always zero [NormalState] +// p := NewParser(32, 1024) // create a new parser with a 32 params buffer and 1024 data buffer (optional) +// input := []byte("\x1b[31mHello, World!\x1b[0m") +// for len(input) > 0 { +// seq, width, n, newState := DecodeSequence(input, state, p) +// log.Printf("seq: %q, width: %d", seq, width) +// state = newState +// input = input[n:] +// } +func (m Method) DecodeSequence(data []byte, state byte, p *Parser) (seq []byte, width, n int, newState byte) { + return decodeSequence(m, data, state, p) +} + +// DecodeSequenceInString decodes the first ANSI escape sequence or a printable +// grapheme from the given data. It returns the sequence slice, the number of +// bytes read, the cell width for each sequence, and the new state. +// +// The cell width will always be 0 for control and escape sequences, 1 for +// ASCII printable characters, and the number of cells other Unicode characters +// occupy. It uses the uniseg package to calculate the width of Unicode +// graphemes and characters. This means it will always do grapheme clustering +// (mode 2027). +// +// Passing a non-nil [*Parser] as the last argument will allow the decoder to +// collect sequence parameters, data, and commands. The parser cmd will have +// the packed command value that contains intermediate and prefix characters. +// In the case of a OSC sequence, the cmd will be the OSC command number. Use +// [Cmd] and [Param] types to unpack command intermediates and prefixes as well +// as parameters. +// +// Zero [Cmd] means the CSI, DCS, or ESC sequence is invalid. Moreover, checking the +// validity of other data sequences, OSC, DCS, etc, will require checking for +// the returned sequence terminator bytes such as ST (ESC \\) and BEL). +// +// We store the command byte in [Cmd] in the most significant byte, the +// prefix byte in the next byte, and the intermediate byte in the least +// significant byte. This is done to avoid using a struct to store the command +// and its intermediates and prefixes. The command byte is always the least +// significant byte i.e. [Cmd & 0xff]. Use the [Cmd] type to unpack the +// command, intermediate, and prefix bytes. Note that we only collect the last +// prefix character and intermediate byte. +// +// The [p.Params] slice will contain the parameters of the sequence. Any +// sub-parameter will have the [parser.HasMoreFlag] set. Use the [Param] type +// to unpack the parameters. +// +// Example: +// +// var state byte // the initial state is always zero [NormalState] +// p := NewParser(32, 1024) // create a new parser with a 32 params buffer and 1024 data buffer (optional) +// input := []byte("\x1b[31mHello, World!\x1b[0m") +// for len(input) > 0 { +// seq, width, n, newState := DecodeSequenceInString(input, state, p) +// log.Printf("seq: %q, width: %d", seq, width) +// state = newState +// input = input[n:] +// } +func (m Method) DecodeSequenceInString(data string, state byte, p *Parser) (seq string, width, n int, newState byte) { + return decodeSequence(m, data, state, p) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/mode.go b/vendor/github.com/charmbracelet/x/ansi/mode.go new file mode 100644 index 00000000..b57b09cc --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/mode.go @@ -0,0 +1,778 @@ +package ansi + +import ( + "strconv" + "strings" +) + +// ModeSetting represents a mode setting. +type ModeSetting byte + +// ModeSetting constants. +const ( + ModeNotRecognized ModeSetting = iota + ModeSet + ModeReset + ModePermanentlySet + ModePermanentlyReset +) + +// IsNotRecognized returns true if the mode is not recognized. +func (m ModeSetting) IsNotRecognized() bool { + return m == ModeNotRecognized +} + +// IsSet returns true if the mode is set or permanently set. +func (m ModeSetting) IsSet() bool { + return m == ModeSet || m == ModePermanentlySet +} + +// IsReset returns true if the mode is reset or permanently reset. +func (m ModeSetting) IsReset() bool { + return m == ModeReset || m == ModePermanentlyReset +} + +// IsPermanentlySet returns true if the mode is permanently set. +func (m ModeSetting) IsPermanentlySet() bool { + return m == ModePermanentlySet +} + +// IsPermanentlyReset returns true if the mode is permanently reset. +func (m ModeSetting) IsPermanentlyReset() bool { + return m == ModePermanentlyReset +} + +// Mode represents an interface for terminal modes. +// Modes can be set, reset, and requested. +type Mode interface { + Mode() int +} + +// SetMode (SM) returns a sequence to set a mode. +// The mode arguments are a list of modes to set. +// +// If one of the modes is a [DECMode], the function will returns two escape +// sequences. +// +// ANSI format: +// +// CSI Pd ; ... ; Pd h +// +// DEC format: +// +// CSI ? Pd ; ... ; Pd h +// +// See: https://vt100.net/docs/vt510-rm/SM.html +func SetMode(modes ...Mode) string { + return setMode(false, modes...) +} + +// SM is an alias for [SetMode]. +func SM(modes ...Mode) string { + return SetMode(modes...) +} + +// ResetMode (RM) returns a sequence to reset a mode. +// The mode arguments are a list of modes to reset. +// +// If one of the modes is a [DECMode], the function will returns two escape +// sequences. +// +// ANSI format: +// +// CSI Pd ; ... ; Pd l +// +// DEC format: +// +// CSI ? Pd ; ... ; Pd l +// +// See: https://vt100.net/docs/vt510-rm/RM.html +func ResetMode(modes ...Mode) string { + return setMode(true, modes...) +} + +// RM is an alias for [ResetMode]. +func RM(modes ...Mode) string { + return ResetMode(modes...) +} + +func setMode(reset bool, modes ...Mode) (s string) { + if len(modes) == 0 { + return + } + + cmd := "h" + if reset { + cmd = "l" + } + + seq := "\x1b[" + if len(modes) == 1 { + switch modes[0].(type) { + case DECMode: + seq += "?" + } + return seq + strconv.Itoa(modes[0].Mode()) + cmd + } + + dec := make([]string, 0, len(modes)/2) + ansi := make([]string, 0, len(modes)/2) + for _, m := range modes { + switch m.(type) { + case DECMode: + dec = append(dec, strconv.Itoa(m.Mode())) + case ANSIMode: + ansi = append(ansi, strconv.Itoa(m.Mode())) + } + } + + if len(ansi) > 0 { + s += seq + strings.Join(ansi, ";") + cmd + } + if len(dec) > 0 { + s += seq + "?" + strings.Join(dec, ";") + cmd + } + return +} + +// RequestMode (DECRQM) returns a sequence to request a mode from the terminal. +// The terminal responds with a report mode function [DECRPM]. +// +// ANSI format: +// +// CSI Pa $ p +// +// DEC format: +// +// CSI ? Pa $ p +// +// See: https://vt100.net/docs/vt510-rm/DECRQM.html +func RequestMode(m Mode) string { + seq := "\x1b[" + switch m.(type) { + case DECMode: + seq += "?" + } + return seq + strconv.Itoa(m.Mode()) + "$p" +} + +// DECRQM is an alias for [RequestMode]. +func DECRQM(m Mode) string { + return RequestMode(m) +} + +// ReportMode (DECRPM) returns a sequence that the terminal sends to the host +// in response to a mode request [DECRQM]. +// +// ANSI format: +// +// CSI Pa ; Ps ; $ y +// +// DEC format: +// +// CSI ? Pa ; Ps $ y +// +// Where Pa is the mode number, and Ps is the mode value. +// +// 0: Not recognized +// 1: Set +// 2: Reset +// 3: Permanent set +// 4: Permanent reset +// +// See: https://vt100.net/docs/vt510-rm/DECRPM.html +func ReportMode(mode Mode, value ModeSetting) string { + if value > 4 { + value = 0 + } + switch mode.(type) { + case DECMode: + return "\x1b[?" + strconv.Itoa(mode.Mode()) + ";" + strconv.Itoa(int(value)) + "$y" + } + return "\x1b[" + strconv.Itoa(mode.Mode()) + ";" + strconv.Itoa(int(value)) + "$y" +} + +// DECRPM is an alias for [ReportMode]. +func DECRPM(mode Mode, value ModeSetting) string { + return ReportMode(mode, value) +} + +// ANSIMode represents an ANSI terminal mode. +type ANSIMode int //nolint:revive + +// Mode returns the ANSI mode as an integer. +func (m ANSIMode) Mode() int { + return int(m) +} + +// DECMode represents a private DEC terminal mode. +type DECMode int + +// Mode returns the DEC mode as an integer. +func (m DECMode) Mode() int { + return int(m) +} + +// Keyboard Action Mode (KAM) is a mode that controls locking of the keyboard. +// When the keyboard is locked, it cannot send data to the terminal. +// +// See: https://vt100.net/docs/vt510-rm/KAM.html +const ( + KeyboardActionMode = ANSIMode(2) + KAM = KeyboardActionMode + + SetKeyboardActionMode = "\x1b[2h" + ResetKeyboardActionMode = "\x1b[2l" + RequestKeyboardActionMode = "\x1b[2$p" +) + +// Insert/Replace Mode (IRM) is a mode that determines whether characters are +// inserted or replaced when typed. +// +// When enabled, characters are inserted at the cursor position pushing the +// characters to the right. When disabled, characters replace the character at +// the cursor position. +// +// See: https://vt100.net/docs/vt510-rm/IRM.html +const ( + InsertReplaceMode = ANSIMode(4) + IRM = InsertReplaceMode + + SetInsertReplaceMode = "\x1b[4h" + ResetInsertReplaceMode = "\x1b[4l" + RequestInsertReplaceMode = "\x1b[4$p" +) + +// BiDirectional Support Mode (BDSM) is a mode that determines whether the +// terminal supports bidirectional text. When enabled, the terminal supports +// bidirectional text and is set to implicit bidirectional mode. When disabled, +// the terminal does not support bidirectional text. +// +// See ECMA-48 7.2.1. +const ( + BiDirectionalSupportMode = ANSIMode(8) + BDSM = BiDirectionalSupportMode + + SetBiDirectionalSupportMode = "\x1b[8h" + ResetBiDirectionalSupportMode = "\x1b[8l" + RequestBiDirectionalSupportMode = "\x1b[8$p" +) + +// Send Receive Mode (SRM) or Local Echo Mode is a mode that determines whether +// the terminal echoes characters back to the host. When enabled, the terminal +// sends characters to the host as they are typed. +// +// See: https://vt100.net/docs/vt510-rm/SRM.html +const ( + SendReceiveMode = ANSIMode(12) + LocalEchoMode = SendReceiveMode + SRM = SendReceiveMode + + SetSendReceiveMode = "\x1b[12h" + ResetSendReceiveMode = "\x1b[12l" + RequestSendReceiveMode = "\x1b[12$p" + + SetLocalEchoMode = "\x1b[12h" + ResetLocalEchoMode = "\x1b[12l" + RequestLocalEchoMode = "\x1b[12$p" +) + +// Line Feed/New Line Mode (LNM) is a mode that determines whether the terminal +// interprets the line feed character as a new line. +// +// When enabled, the terminal interprets the line feed character as a new line. +// When disabled, the terminal interprets the line feed character as a line feed. +// +// A new line moves the cursor to the first position of the next line. +// A line feed moves the cursor down one line without changing the column +// scrolling the screen if necessary. +// +// See: https://vt100.net/docs/vt510-rm/LNM.html +const ( + LineFeedNewLineMode = ANSIMode(20) + LNM = LineFeedNewLineMode + + SetLineFeedNewLineMode = "\x1b[20h" + ResetLineFeedNewLineMode = "\x1b[20l" + RequestLineFeedNewLineMode = "\x1b[20$p" +) + +// Cursor Keys Mode (DECCKM) is a mode that determines whether the cursor keys +// send ANSI cursor sequences or application sequences. +// +// See: https://vt100.net/docs/vt510-rm/DECCKM.html +const ( + CursorKeysMode = DECMode(1) + DECCKM = CursorKeysMode + + SetCursorKeysMode = "\x1b[?1h" + ResetCursorKeysMode = "\x1b[?1l" + RequestCursorKeysMode = "\x1b[?1$p" +) + +// Deprecated: use [SetCursorKeysMode] and [ResetCursorKeysMode] instead. +const ( + EnableCursorKeys = "\x1b[?1h" + DisableCursorKeys = "\x1b[?1l" +) + +// Origin Mode (DECOM) is a mode that determines whether the cursor moves to the +// home position or the margin position. +// +// See: https://vt100.net/docs/vt510-rm/DECOM.html +const ( + OriginMode = DECMode(6) + DECOM = OriginMode + + SetOriginMode = "\x1b[?6h" + ResetOriginMode = "\x1b[?6l" + RequestOriginMode = "\x1b[?6$p" +) + +// Auto Wrap Mode (DECAWM) is a mode that determines whether the cursor wraps +// to the next line when it reaches the right margin. +// +// See: https://vt100.net/docs/vt510-rm/DECAWM.html +const ( + AutoWrapMode = DECMode(7) + DECAWM = AutoWrapMode + + SetAutoWrapMode = "\x1b[?7h" + ResetAutoWrapMode = "\x1b[?7l" + RequestAutoWrapMode = "\x1b[?7$p" +) + +// X10 Mouse Mode is a mode that determines whether the mouse reports on button +// presses. +// +// The terminal responds with the following encoding: +// +// CSI M CbCxCy +// +// Where Cb is the button-1, where it can be 1, 2, or 3. +// Cx and Cy are the x and y coordinates of the mouse event. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +const ( + X10MouseMode = DECMode(9) + + SetX10MouseMode = "\x1b[?9h" + ResetX10MouseMode = "\x1b[?9l" + RequestX10MouseMode = "\x1b[?9$p" +) + +// Text Cursor Enable Mode (DECTCEM) is a mode that shows/hides the cursor. +// +// See: https://vt100.net/docs/vt510-rm/DECTCEM.html +const ( + TextCursorEnableMode = DECMode(25) + DECTCEM = TextCursorEnableMode + + SetTextCursorEnableMode = "\x1b[?25h" + ResetTextCursorEnableMode = "\x1b[?25l" + RequestTextCursorEnableMode = "\x1b[?25$p" +) + +// These are aliases for [SetTextCursorEnableMode] and [ResetTextCursorEnableMode]. +const ( + ShowCursor = SetTextCursorEnableMode + HideCursor = ResetTextCursorEnableMode +) + +// Text Cursor Enable Mode (DECTCEM) is a mode that shows/hides the cursor. +// +// See: https://vt100.net/docs/vt510-rm/DECTCEM.html +// +// Deprecated: use [SetTextCursorEnableMode] and [ResetTextCursorEnableMode] instead. +const ( + CursorEnableMode = DECMode(25) + RequestCursorVisibility = "\x1b[?25$p" +) + +// Numeric Keypad Mode (DECNKM) is a mode that determines whether the keypad +// sends application sequences or numeric sequences. +// +// This works like [DECKPAM] and [DECKPNM], but uses different sequences. +// +// See: https://vt100.net/docs/vt510-rm/DECNKM.html +const ( + NumericKeypadMode = DECMode(66) + DECNKM = NumericKeypadMode + + SetNumericKeypadMode = "\x1b[?66h" + ResetNumericKeypadMode = "\x1b[?66l" + RequestNumericKeypadMode = "\x1b[?66$p" +) + +// Backarrow Key Mode (DECBKM) is a mode that determines whether the backspace +// key sends a backspace or delete character. Disabled by default. +// +// See: https://vt100.net/docs/vt510-rm/DECBKM.html +const ( + BackarrowKeyMode = DECMode(67) + DECBKM = BackarrowKeyMode + + SetBackarrowKeyMode = "\x1b[?67h" + ResetBackarrowKeyMode = "\x1b[?67l" + RequestBackarrowKeyMode = "\x1b[?67$p" +) + +// Left Right Margin Mode (DECLRMM) is a mode that determines whether the left +// and right margins can be set with [DECSLRM]. +// +// See: https://vt100.net/docs/vt510-rm/DECLRMM.html +const ( + LeftRightMarginMode = DECMode(69) + DECLRMM = LeftRightMarginMode + + SetLeftRightMarginMode = "\x1b[?69h" + ResetLeftRightMarginMode = "\x1b[?69l" + RequestLeftRightMarginMode = "\x1b[?69$p" +) + +// Normal Mouse Mode is a mode that determines whether the mouse reports on +// button presses and releases. It will also report modifier keys, wheel +// events, and extra buttons. +// +// It uses the same encoding as [X10MouseMode] with a few differences: +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +const ( + NormalMouseMode = DECMode(1000) + + SetNormalMouseMode = "\x1b[?1000h" + ResetNormalMouseMode = "\x1b[?1000l" + RequestNormalMouseMode = "\x1b[?1000$p" +) + +// VT Mouse Tracking is a mode that determines whether the mouse reports on +// button press and release. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +// +// Deprecated: use [NormalMouseMode] instead. +const ( + MouseMode = DECMode(1000) + + EnableMouse = "\x1b[?1000h" + DisableMouse = "\x1b[?1000l" + RequestMouse = "\x1b[?1000$p" +) + +// Highlight Mouse Tracking is a mode that determines whether the mouse reports +// on button presses, releases, and highlighted cells. +// +// It uses the same encoding as [NormalMouseMode] with a few differences: +// +// On highlight events, the terminal responds with the following encoding: +// +// CSI t CxCy +// CSI T CxCyCxCyCxCy +// +// Where the parameters are startx, starty, endx, endy, mousex, and mousey. +const ( + HighlightMouseMode = DECMode(1001) + + SetHighlightMouseMode = "\x1b[?1001h" + ResetHighlightMouseMode = "\x1b[?1001l" + RequestHighlightMouseMode = "\x1b[?1001$p" +) + +// VT Hilite Mouse Tracking is a mode that determines whether the mouse reports on +// button presses, releases, and highlighted cells. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +// +// Deprecated: use [HighlightMouseMode] instead. +const ( + MouseHiliteMode = DECMode(1001) + + EnableMouseHilite = "\x1b[?1001h" + DisableMouseHilite = "\x1b[?1001l" + RequestMouseHilite = "\x1b[?1001$p" +) + +// Button Event Mouse Tracking is essentially the same as [NormalMouseMode], +// but it also reports button-motion events when a button is pressed. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +const ( + ButtonEventMouseMode = DECMode(1002) + + SetButtonEventMouseMode = "\x1b[?1002h" + ResetButtonEventMouseMode = "\x1b[?1002l" + RequestButtonEventMouseMode = "\x1b[?1002$p" +) + +// Cell Motion Mouse Tracking is a mode that determines whether the mouse +// reports on button press, release, and motion events. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +// +// Deprecated: use [ButtonEventMouseMode] instead. +const ( + MouseCellMotionMode = DECMode(1002) + + EnableMouseCellMotion = "\x1b[?1002h" + DisableMouseCellMotion = "\x1b[?1002l" + RequestMouseCellMotion = "\x1b[?1002$p" +) + +// Any Event Mouse Tracking is the same as [ButtonEventMouseMode], except that +// all motion events are reported even if no mouse buttons are pressed. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +const ( + AnyEventMouseMode = DECMode(1003) + + SetAnyEventMouseMode = "\x1b[?1003h" + ResetAnyEventMouseMode = "\x1b[?1003l" + RequestAnyEventMouseMode = "\x1b[?1003$p" +) + +// All Mouse Tracking is a mode that determines whether the mouse reports on +// button press, release, motion, and highlight events. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +// +// Deprecated: use [AnyEventMouseMode] instead. +const ( + MouseAllMotionMode = DECMode(1003) + + EnableMouseAllMotion = "\x1b[?1003h" + DisableMouseAllMotion = "\x1b[?1003l" + RequestMouseAllMotion = "\x1b[?1003$p" +) + +// Focus Event Mode is a mode that determines whether the terminal reports focus +// and blur events. +// +// The terminal sends the following encoding: +// +// CSI I // Focus In +// CSI O // Focus Out +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Focus-Tracking +const ( + FocusEventMode = DECMode(1004) + + SetFocusEventMode = "\x1b[?1004h" + ResetFocusEventMode = "\x1b[?1004l" + RequestFocusEventMode = "\x1b[?1004$p" +) + +// Deprecated: use [SetFocusEventMode], [ResetFocusEventMode], and +// [RequestFocusEventMode] instead. +const ( + ReportFocusMode = DECMode(1004) + + EnableReportFocus = "\x1b[?1004h" + DisableReportFocus = "\x1b[?1004l" + RequestReportFocus = "\x1b[?1004$p" +) + +// SGR Extended Mouse Mode is a mode that changes the mouse tracking encoding +// to use SGR parameters. +// +// The terminal responds with the following encoding: +// +// CSI < Cb ; Cx ; Cy M +// +// Where Cb is the same as [NormalMouseMode], and Cx and Cy are the x and y. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +const ( + SgrExtMouseMode = DECMode(1006) + + SetSgrExtMouseMode = "\x1b[?1006h" + ResetSgrExtMouseMode = "\x1b[?1006l" + RequestSgrExtMouseMode = "\x1b[?1006$p" +) + +// Deprecated: use [SgrExtMouseMode] [SetSgrExtMouseMode], +// [ResetSgrExtMouseMode], and [RequestSgrExtMouseMode] instead. +const ( + MouseSgrExtMode = DECMode(1006) + EnableMouseSgrExt = "\x1b[?1006h" + DisableMouseSgrExt = "\x1b[?1006l" + RequestMouseSgrExt = "\x1b[?1006$p" +) + +// UTF-8 Extended Mouse Mode is a mode that changes the mouse tracking encoding +// to use UTF-8 parameters. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +const ( + Utf8ExtMouseMode = DECMode(1005) + + SetUtf8ExtMouseMode = "\x1b[?1005h" + ResetUtf8ExtMouseMode = "\x1b[?1005l" + RequestUtf8ExtMouseMode = "\x1b[?1005$p" +) + +// URXVT Extended Mouse Mode is a mode that changes the mouse tracking encoding +// to use an alternate encoding. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +const ( + UrxvtExtMouseMode = DECMode(1015) + + SetUrxvtExtMouseMode = "\x1b[?1015h" + ResetUrxvtExtMouseMode = "\x1b[?1015l" + RequestUrxvtExtMouseMode = "\x1b[?1015$p" +) + +// SGR Pixel Extended Mouse Mode is a mode that changes the mouse tracking +// encoding to use SGR parameters with pixel coordinates. +// +// This is similar to [SgrExtMouseMode], but also reports pixel coordinates. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Mouse-Tracking +const ( + SgrPixelExtMouseMode = DECMode(1016) + + SetSgrPixelExtMouseMode = "\x1b[?1016h" + ResetSgrPixelExtMouseMode = "\x1b[?1016l" + RequestSgrPixelExtMouseMode = "\x1b[?1016$p" +) + +// Alternate Screen Mode is a mode that determines whether the alternate screen +// buffer is active. When this mode is enabled, the alternate screen buffer is +// cleared. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer +const ( + AltScreenMode = DECMode(1047) + + SetAltScreenMode = "\x1b[?1047h" + ResetAltScreenMode = "\x1b[?1047l" + RequestAltScreenMode = "\x1b[?1047$p" +) + +// Save Cursor Mode is a mode that saves the cursor position. +// This is equivalent to [SaveCursor] and [RestoreCursor]. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer +const ( + SaveCursorMode = DECMode(1048) + + SetSaveCursorMode = "\x1b[?1048h" + ResetSaveCursorMode = "\x1b[?1048l" + RequestSaveCursorMode = "\x1b[?1048$p" +) + +// Alternate Screen Save Cursor Mode is a mode that saves the cursor position as in +// [SaveCursorMode], switches to the alternate screen buffer as in [AltScreenMode], +// and clears the screen on switch. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer +const ( + AltScreenSaveCursorMode = DECMode(1049) + + SetAltScreenSaveCursorMode = "\x1b[?1049h" + ResetAltScreenSaveCursorMode = "\x1b[?1049l" + RequestAltScreenSaveCursorMode = "\x1b[?1049$p" +) + +// Alternate Screen Buffer is a mode that determines whether the alternate screen +// buffer is active. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-The-Alternate-Screen-Buffer +// +// Deprecated: use [AltScreenSaveCursorMode] instead. +const ( + AltScreenBufferMode = DECMode(1049) + + SetAltScreenBufferMode = "\x1b[?1049h" + ResetAltScreenBufferMode = "\x1b[?1049l" + RequestAltScreenBufferMode = "\x1b[?1049$p" + + EnableAltScreenBuffer = "\x1b[?1049h" + DisableAltScreenBuffer = "\x1b[?1049l" + RequestAltScreenBuffer = "\x1b[?1049$p" +) + +// Bracketed Paste Mode is a mode that determines whether pasted text is +// bracketed with escape sequences. +// +// See: https://cirw.in/blog/bracketed-paste +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Bracketed-Paste-Mode +const ( + BracketedPasteMode = DECMode(2004) + + SetBracketedPasteMode = "\x1b[?2004h" + ResetBracketedPasteMode = "\x1b[?2004l" + RequestBracketedPasteMode = "\x1b[?2004$p" +) + +// Deprecated: use [SetBracketedPasteMode], [ResetBracketedPasteMode], and +// [RequestBracketedPasteMode] instead. +const ( + EnableBracketedPaste = "\x1b[?2004h" + DisableBracketedPaste = "\x1b[?2004l" + RequestBracketedPaste = "\x1b[?2004$p" +) + +// Synchronized Output Mode is a mode that determines whether output is +// synchronized with the terminal. +// +// See: https://gist.github.com/christianparpart/d8a62cc1ab659194337d73e399004036 +const ( + SynchronizedOutputMode = DECMode(2026) + + SetSynchronizedOutputMode = "\x1b[?2026h" + ResetSynchronizedOutputMode = "\x1b[?2026l" + RequestSynchronizedOutputMode = "\x1b[?2026$p" +) + +// Deprecated: use [SynchronizedOutputMode], [SetSynchronizedOutputMode], and +// [ResetSynchronizedOutputMode], and [RequestSynchronizedOutputMode] instead. +const ( + SyncdOutputMode = DECMode(2026) + + EnableSyncdOutput = "\x1b[?2026h" + DisableSyncdOutput = "\x1b[?2026l" + RequestSyncdOutput = "\x1b[?2026$p" +) + +// Grapheme Clustering Mode is a mode that determines whether the terminal +// should look for grapheme clusters instead of single runes in the rendered +// text. This makes the terminal properly render combining characters such as +// emojis. +// +// See: https://github.com/contour-terminal/terminal-unicode-core +const ( + GraphemeClusteringMode = DECMode(2027) + + SetGraphemeClusteringMode = "\x1b[?2027h" + ResetGraphemeClusteringMode = "\x1b[?2027l" + RequestGraphemeClusteringMode = "\x1b[?2027$p" +) + +// Deprecated: use [SetGraphemeClusteringMode], [ResetGraphemeClusteringMode], and +// [RequestGraphemeClusteringMode] instead. +const ( + EnableGraphemeClustering = "\x1b[?2027h" + DisableGraphemeClustering = "\x1b[?2027l" + RequestGraphemeClustering = "\x1b[?2027$p" +) + +// Win32Input is a mode that determines whether input is processed by the +// Win32 console and Conpty. +// +// See: https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md +const ( + Win32InputMode = DECMode(9001) + + SetWin32InputMode = "\x1b[?9001h" + ResetWin32InputMode = "\x1b[?9001l" + RequestWin32InputMode = "\x1b[?9001$p" +) + +// Deprecated: use [SetWin32InputMode], [ResetWin32InputMode], and +// [RequestWin32InputMode] instead. +const ( + EnableWin32Input = "\x1b[?9001h" + DisableWin32Input = "\x1b[?9001l" + RequestWin32Input = "\x1b[?9001$p" +) diff --git a/vendor/github.com/charmbracelet/x/ansi/modes.go b/vendor/github.com/charmbracelet/x/ansi/modes.go new file mode 100644 index 00000000..6856d35e --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/modes.go @@ -0,0 +1,65 @@ +package ansi + +// Modes represents the terminal modes that can be set or reset. By default, +// all modes are [ModeNotRecognized]. +type Modes map[Mode]ModeSetting + +// Get returns the setting of a terminal mode. If the mode is not set, it +// returns [ModeNotRecognized]. +func (m Modes) Get(mode Mode) ModeSetting { + return m[mode] +} + +// Delete deletes a terminal mode. This has the same effect as setting the mode +// to [ModeNotRecognized]. +func (m Modes) Delete(mode Mode) { + delete(m, mode) +} + +// Set sets a terminal mode to [ModeSet]. +func (m Modes) Set(modes ...Mode) { + for _, mode := range modes { + m[mode] = ModeSet + } +} + +// PermanentlySet sets a terminal mode to [ModePermanentlySet]. +func (m Modes) PermanentlySet(modes ...Mode) { + for _, mode := range modes { + m[mode] = ModePermanentlySet + } +} + +// Reset sets a terminal mode to [ModeReset]. +func (m Modes) Reset(modes ...Mode) { + for _, mode := range modes { + m[mode] = ModeReset + } +} + +// PermanentlyReset sets a terminal mode to [ModePermanentlyReset]. +func (m Modes) PermanentlyReset(modes ...Mode) { + for _, mode := range modes { + m[mode] = ModePermanentlyReset + } +} + +// IsSet returns true if the mode is set to [ModeSet] or [ModePermanentlySet]. +func (m Modes) IsSet(mode Mode) bool { + return m[mode].IsSet() +} + +// IsPermanentlySet returns true if the mode is set to [ModePermanentlySet]. +func (m Modes) IsPermanentlySet(mode Mode) bool { + return m[mode].IsPermanentlySet() +} + +// IsReset returns true if the mode is set to [ModeReset] or [ModePermanentlyReset]. +func (m Modes) IsReset(mode Mode) bool { + return m[mode].IsReset() +} + +// IsPermanentlyReset returns true if the mode is set to [ModePermanentlyReset]. +func (m Modes) IsPermanentlyReset(mode Mode) bool { + return m[mode].IsPermanentlyReset() +} diff --git a/vendor/github.com/charmbracelet/x/ansi/mouse.go b/vendor/github.com/charmbracelet/x/ansi/mouse.go new file mode 100644 index 00000000..95b0127f --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/mouse.go @@ -0,0 +1,172 @@ +package ansi + +import ( + "fmt" +) + +// MouseButton represents the button that was pressed during a mouse message. +type MouseButton byte + +// Mouse event buttons +// +// This is based on X11 mouse button codes. +// +// 1 = left button +// 2 = middle button (pressing the scroll wheel) +// 3 = right button +// 4 = turn scroll wheel up +// 5 = turn scroll wheel down +// 6 = push scroll wheel left +// 7 = push scroll wheel right +// 8 = 4th button (aka browser backward button) +// 9 = 5th button (aka browser forward button) +// 10 +// 11 +// +// Other buttons are not supported. +const ( + MouseNone MouseButton = iota + MouseButton1 + MouseButton2 + MouseButton3 + MouseButton4 + MouseButton5 + MouseButton6 + MouseButton7 + MouseButton8 + MouseButton9 + MouseButton10 + MouseButton11 + + MouseLeft = MouseButton1 + MouseMiddle = MouseButton2 + MouseRight = MouseButton3 + MouseWheelUp = MouseButton4 + MouseWheelDown = MouseButton5 + MouseWheelLeft = MouseButton6 + MouseWheelRight = MouseButton7 + MouseBackward = MouseButton8 + MouseForward = MouseButton9 + MouseRelease = MouseNone +) + +var mouseButtons = map[MouseButton]string{ + MouseNone: "none", + MouseLeft: "left", + MouseMiddle: "middle", + MouseRight: "right", + MouseWheelUp: "wheelup", + MouseWheelDown: "wheeldown", + MouseWheelLeft: "wheelleft", + MouseWheelRight: "wheelright", + MouseBackward: "backward", + MouseForward: "forward", + MouseButton10: "button10", + MouseButton11: "button11", +} + +// String returns a string representation of the mouse button. +func (b MouseButton) String() string { + return mouseButtons[b] +} + +// EncodeMouseButton returns a byte representing a mouse button. +// The button is a bitmask of the following leftmost values: +// +// - The first two bits are the button number: +// 0 = left button, wheel up, or button no. 8 aka (backwards) +// 1 = middle button, wheel down, or button no. 9 aka (forwards) +// 2 = right button, wheel left, or button no. 10 +// 3 = release event, wheel right, or button no. 11 +// +// - The third bit indicates whether the shift key was pressed. +// +// - The fourth bit indicates the alt key was pressed. +// +// - The fifth bit indicates the control key was pressed. +// +// - The sixth bit indicates motion events. Combined with button number 3, i.e. +// release event, it represents a drag event. +// +// - The seventh bit indicates a wheel event. +// +// - The eighth bit indicates additional buttons. +// +// If button is [MouseNone], and motion is false, this returns a release event. +// If button is undefined, this function returns 0xff. +func EncodeMouseButton(b MouseButton, motion, shift, alt, ctrl bool) (m byte) { + // mouse bit shifts + const ( + bitShift = 0b0000_0100 + bitAlt = 0b0000_1000 + bitCtrl = 0b0001_0000 + bitMotion = 0b0010_0000 + bitWheel = 0b0100_0000 + bitAdd = 0b1000_0000 // additional buttons 8-11 + + bitsMask = 0b0000_0011 + ) + + if b == MouseNone { + m = bitsMask + } else if b >= MouseLeft && b <= MouseRight { + m = byte(b - MouseLeft) + } else if b >= MouseWheelUp && b <= MouseWheelRight { + m = byte(b - MouseWheelUp) + m |= bitWheel + } else if b >= MouseBackward && b <= MouseButton11 { + m = byte(b - MouseBackward) + m |= bitAdd + } else { + m = 0xff // invalid button + } + + if shift { + m |= bitShift + } + if alt { + m |= bitAlt + } + if ctrl { + m |= bitCtrl + } + if motion { + m |= bitMotion + } + + return +} + +// x10Offset is the offset for X10 mouse events. +// See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking +const x10Offset = 32 + +// MouseX10 returns an escape sequence representing a mouse event in X10 mode. +// Note that this requires the terminal support X10 mouse modes. +// +// CSI M Cb Cx Cy +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking +func MouseX10(b byte, x, y int) string { + return "\x1b[M" + string(b+x10Offset) + string(byte(x)+x10Offset+1) + string(byte(y)+x10Offset+1) +} + +// MouseSgr returns an escape sequence representing a mouse event in SGR mode. +// +// CSI < Cb ; Cx ; Cy M +// CSI < Cb ; Cx ; Cy m (release) +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#Mouse%20Tracking +func MouseSgr(b byte, x, y int, release bool) string { + s := 'M' + if release { + s = 'm' + } + if x < 0 { + x = -x + } + if y < 0 { + y = -y + } + return fmt.Sprintf("\x1b[<%d;%d;%d%c", b, x+1, y+1, s) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/notification.go b/vendor/github.com/charmbracelet/x/ansi/notification.go new file mode 100644 index 00000000..c712f340 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/notification.go @@ -0,0 +1,13 @@ +package ansi + +// Notify sends a desktop notification using iTerm's OSC 9. +// +// OSC 9 ; Mc ST +// OSC 9 ; Mc BEL +// +// Where Mc is the notification body. +// +// See: https://iterm2.com/documentation-escape-codes.html +func Notify(s string) string { + return "\x1b]9;" + s + "\x07" +} diff --git a/vendor/github.com/charmbracelet/x/ansi/parser.go b/vendor/github.com/charmbracelet/x/ansi/parser.go new file mode 100644 index 00000000..e770c15f --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/parser.go @@ -0,0 +1,417 @@ +package ansi + +import ( + "unicode/utf8" + "unsafe" + + "github.com/charmbracelet/x/ansi/parser" +) + +// Parser represents a DEC ANSI compatible sequence parser. +// +// It uses a state machine to parse ANSI escape sequences and control +// characters. The parser is designed to be used with a terminal emulator or +// similar application that needs to parse ANSI escape sequences and control +// characters. +// See package [parser] for more information. +// +//go:generate go run ./gen.go +type Parser struct { + handler Handler + + // params contains the raw parameters of the sequence. + // These parameters used when constructing CSI and DCS sequences. + params []int + + // data contains the raw data of the sequence. + // These data used when constructing OSC, DCS, SOS, PM, and APC sequences. + data []byte + + // dataLen keeps track of the length of the data buffer. + // If dataLen is -1, the data buffer is unlimited and will grow as needed. + // Otherwise, dataLen is limited by the size of the data buffer. + dataLen int + + // paramsLen keeps track of the number of parameters. + // This is limited by the size of the params buffer. + // + // This is also used when collecting UTF-8 runes to keep track of the + // number of rune bytes collected. + paramsLen int + + // cmd contains the raw command along with the private prefix and + // intermediate bytes of the sequence. + // The first lower byte contains the command byte, the next byte contains + // the private prefix, and the next byte contains the intermediate byte. + // + // This is also used when collecting UTF-8 runes treating it as a slice of + // 4 bytes. + cmd int + + // state is the current state of the parser. + state byte +} + +// NewParser returns a new parser with the default settings. +// The [Parser] uses a default size of 32 for the parameters and 64KB for the +// data buffer. Use [Parser.SetParamsSize] and [Parser.SetDataSize] to set the +// size of the parameters and data buffer respectively. +func NewParser() *Parser { + p := new(Parser) + p.SetParamsSize(parser.MaxParamsSize) + p.SetDataSize(1024 * 64) // 64KB data buffer + return p +} + +// SetParamsSize sets the size of the parameters buffer. +// This is used when constructing CSI and DCS sequences. +func (p *Parser) SetParamsSize(size int) { + p.params = make([]int, size) +} + +// SetDataSize sets the size of the data buffer. +// This is used when constructing OSC, DCS, SOS, PM, and APC sequences. +// If size is less than or equal to 0, the data buffer is unlimited and will +// grow as needed. +func (p *Parser) SetDataSize(size int) { + if size <= 0 { + size = 0 + p.dataLen = -1 + } + p.data = make([]byte, size) +} + +// Params returns the list of parsed packed parameters. +func (p *Parser) Params() Params { + return unsafe.Slice((*Param)(unsafe.Pointer(&p.params[0])), p.paramsLen) +} + +// Param returns the parameter at the given index and falls back to the default +// value if the parameter is missing. If the index is out of bounds, it returns +// the default value and false. +func (p *Parser) Param(i, def int) (int, bool) { + if i < 0 || i >= p.paramsLen { + return def, false + } + return Param(p.params[i]).Param(def), true +} + +// Command returns the packed command of the last dispatched sequence. Use +// [Cmd] to unpack the command. +func (p *Parser) Command() int { + return p.cmd +} + +// Rune returns the last dispatched sequence as a rune. +func (p *Parser) Rune() rune { + rw := utf8ByteLen(byte(p.cmd & 0xff)) + if rw == -1 { + return utf8.RuneError + } + r, _ := utf8.DecodeRune((*[utf8.UTFMax]byte)(unsafe.Pointer(&p.cmd))[:rw]) + return r +} + +// Control returns the last dispatched sequence as a control code. +func (p *Parser) Control() byte { + return byte(p.cmd & 0xff) +} + +// Data returns the raw data of the last dispatched sequence. +func (p *Parser) Data() []byte { + return p.data[:p.dataLen] +} + +// Reset resets the parser to its initial state. +func (p *Parser) Reset() { + p.clear() + p.state = parser.GroundState +} + +// clear clears the parser parameters and command. +func (p *Parser) clear() { + if len(p.params) > 0 { + p.params[0] = parser.MissingParam + } + p.paramsLen = 0 + p.cmd = 0 +} + +// State returns the current state of the parser. +func (p *Parser) State() parser.State { + return p.state +} + +// StateName returns the name of the current state. +func (p *Parser) StateName() string { + return parser.StateNames[p.state] +} + +// Parse parses the given dispatcher and byte buffer. +// Deprecated: Loop over the buffer and call [Parser.Advance] instead. +func (p *Parser) Parse(b []byte) { + for i := range b { + p.Advance(b[i]) + } +} + +// Advance advances the parser using the given byte. It returns the action +// performed by the parser. +func (p *Parser) Advance(b byte) parser.Action { + switch p.state { + case parser.Utf8State: + // We handle UTF-8 here. + return p.advanceUtf8(b) + default: + return p.advance(b) + } +} + +func (p *Parser) collectRune(b byte) { + if p.paramsLen >= utf8.UTFMax { + return + } + + shift := p.paramsLen * 8 + p.cmd &^= 0xff << shift + p.cmd |= int(b) << shift + p.paramsLen++ +} + +func (p *Parser) advanceUtf8(b byte) parser.Action { + // Collect UTF-8 rune bytes. + p.collectRune(b) + rw := utf8ByteLen(byte(p.cmd & 0xff)) + if rw == -1 { + // We panic here because the first byte comes from the state machine, + // if this panics, it means there is a bug in the state machine! + panic("invalid rune") // unreachable + } + + if p.paramsLen < rw { + return parser.CollectAction + } + + // We have enough bytes to decode the rune using unsafe + if p.handler.Print != nil { + p.handler.Print(p.Rune()) + } + + p.state = parser.GroundState + p.paramsLen = 0 + + return parser.PrintAction +} + +func (p *Parser) advance(b byte) parser.Action { + state, action := parser.Table.Transition(p.state, b) + + // We need to clear the parser state if the state changes from EscapeState. + // This is because when we enter the EscapeState, we don't get a chance to + // clear the parser state. For example, when a sequence terminates with a + // ST (\x1b\\ or \x9c), we dispatch the current sequence and transition to + // EscapeState. However, the parser state is not cleared in this case and + // we need to clear it here before dispatching the esc sequence. + if p.state != state { + if p.state == parser.EscapeState { + p.performAction(parser.ClearAction, state, b) + } + if action == parser.PutAction && + p.state == parser.DcsEntryState && state == parser.DcsStringState { + // XXX: This is a special case where we need to start collecting + // non-string parameterized data i.e. doesn't follow the ECMA-48 § + // 5.4.1 string parameters format. + p.performAction(parser.StartAction, state, 0) + } + } + + // Handle special cases + switch { + case b == ESC && p.state == parser.EscapeState: + // Two ESCs in a row + p.performAction(parser.ExecuteAction, state, b) + default: + p.performAction(action, state, b) + } + + p.state = state + + return action +} + +func (p *Parser) parseStringCmd() { + // Try to parse the command + datalen := len(p.data) + if p.dataLen >= 0 { + datalen = p.dataLen + } + for i := range datalen { + d := p.data[i] + if d < '0' || d > '9' { + break + } + if p.cmd == parser.MissingCommand { + p.cmd = 0 + } + p.cmd *= 10 + p.cmd += int(d - '0') + } +} + +func (p *Parser) performAction(action parser.Action, state parser.State, b byte) { + switch action { + case parser.IgnoreAction: + break + + case parser.ClearAction: + p.clear() + + case parser.PrintAction: + p.cmd = int(b) + if p.handler.Print != nil { + p.handler.Print(rune(b)) + } + + case parser.ExecuteAction: + p.cmd = int(b) + if p.handler.Execute != nil { + p.handler.Execute(b) + } + + case parser.PrefixAction: + // Collect private prefix + // we only store the last prefix + p.cmd &^= 0xff << parser.PrefixShift + p.cmd |= int(b) << parser.PrefixShift + + case parser.CollectAction: + if state == parser.Utf8State { + // Reset the UTF-8 counter + p.paramsLen = 0 + p.collectRune(b) + } else { + // Collect intermediate bytes + // we only store the last intermediate byte + p.cmd &^= 0xff << parser.IntermedShift + p.cmd |= int(b) << parser.IntermedShift + } + + case parser.ParamAction: + // Collect parameters + if p.paramsLen >= len(p.params) { + break + } + + if b >= '0' && b <= '9' { + if p.params[p.paramsLen] == parser.MissingParam { + p.params[p.paramsLen] = 0 + } + + p.params[p.paramsLen] *= 10 + p.params[p.paramsLen] += int(b - '0') + } + + if b == ':' { + p.params[p.paramsLen] |= parser.HasMoreFlag + } + + if b == ';' || b == ':' { + p.paramsLen++ + if p.paramsLen < len(p.params) { + p.params[p.paramsLen] = parser.MissingParam + } + } + + case parser.StartAction: + if p.dataLen < 0 && p.data != nil { + p.data = p.data[:0] + } else { + p.dataLen = 0 + } + if p.state >= parser.DcsEntryState && p.state <= parser.DcsStringState { + // Collect the command byte for DCS + p.cmd |= int(b) + } else { + p.cmd = parser.MissingCommand + } + + case parser.PutAction: + switch p.state { + case parser.OscStringState: + if b == ';' && p.cmd == parser.MissingCommand { + p.parseStringCmd() + } + } + + if p.dataLen < 0 { + p.data = append(p.data, b) + } else { + if p.dataLen < len(p.data) { + p.data[p.dataLen] = b + p.dataLen++ + } + } + + case parser.DispatchAction: + // Increment the last parameter + if p.paramsLen > 0 && p.paramsLen < len(p.params)-1 || + p.paramsLen == 0 && len(p.params) > 0 && p.params[0] != parser.MissingParam { + p.paramsLen++ + } + + if p.state == parser.OscStringState && p.cmd == parser.MissingCommand { + // Ensure we have a command for OSC + p.parseStringCmd() + } + + data := p.data + if p.dataLen >= 0 { + data = data[:p.dataLen] + } + switch p.state { + case parser.CsiEntryState, parser.CsiParamState, parser.CsiIntermediateState: + p.cmd |= int(b) + if p.handler.HandleCsi != nil { + p.handler.HandleCsi(Cmd(p.cmd), p.Params()) + } + case parser.EscapeState, parser.EscapeIntermediateState: + p.cmd |= int(b) + if p.handler.HandleEsc != nil { + p.handler.HandleEsc(Cmd(p.cmd)) + } + case parser.DcsEntryState, parser.DcsParamState, parser.DcsIntermediateState, parser.DcsStringState: + if p.handler.HandleDcs != nil { + p.handler.HandleDcs(Cmd(p.cmd), p.Params(), data) + } + case parser.OscStringState: + if p.handler.HandleOsc != nil { + p.handler.HandleOsc(p.cmd, data) + } + case parser.SosStringState: + if p.handler.HandleSos != nil { + p.handler.HandleSos(data) + } + case parser.PmStringState: + if p.handler.HandlePm != nil { + p.handler.HandlePm(data) + } + case parser.ApcStringState: + if p.handler.HandleApc != nil { + p.handler.HandleApc(data) + } + } + } +} + +func utf8ByteLen(b byte) int { + if b <= 0b0111_1111 { // 0x00-0x7F + return 1 + } else if b >= 0b1100_0000 && b <= 0b1101_1111 { // 0xC0-0xDF + return 2 + } else if b >= 0b1110_0000 && b <= 0b1110_1111 { // 0xE0-0xEF + return 3 + } else if b >= 0b1111_0000 && b <= 0b1111_0111 { // 0xF0-0xF7 + return 4 + } + return -1 +} diff --git a/vendor/github.com/charmbracelet/x/ansi/parser/const.go b/vendor/github.com/charmbracelet/x/ansi/parser/const.go new file mode 100644 index 00000000..d62dbf37 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/parser/const.go @@ -0,0 +1,78 @@ +package parser + +// Action is a DEC ANSI parser action. +type Action = byte + +// These are the actions that the parser can take. +const ( + NoneAction Action = iota + ClearAction + CollectAction + PrefixAction + DispatchAction + ExecuteAction + StartAction // Start of a data string + PutAction // Put into the data string + ParamAction + PrintAction + + IgnoreAction = NoneAction +) + +// nolint: unused +var ActionNames = []string{ + "NoneAction", + "ClearAction", + "CollectAction", + "PrefixAction", + "DispatchAction", + "ExecuteAction", + "StartAction", + "PutAction", + "ParamAction", + "PrintAction", +} + +// State is a DEC ANSI parser state. +type State = byte + +// These are the states that the parser can be in. +const ( + GroundState State = iota + CsiEntryState + CsiIntermediateState + CsiParamState + DcsEntryState + DcsIntermediateState + DcsParamState + DcsStringState + EscapeState + EscapeIntermediateState + OscStringState + SosStringState + PmStringState + ApcStringState + + // Utf8State is not part of the DEC ANSI standard. It is used to handle + // UTF-8 sequences. + Utf8State +) + +// nolint: unused +var StateNames = []string{ + "GroundState", + "CsiEntryState", + "CsiIntermediateState", + "CsiParamState", + "DcsEntryState", + "DcsIntermediateState", + "DcsParamState", + "DcsStringState", + "EscapeState", + "EscapeIntermediateState", + "OscStringState", + "SosStringState", + "PmStringState", + "ApcStringState", + "Utf8State", +} diff --git a/vendor/github.com/charmbracelet/x/ansi/parser/seq.go b/vendor/github.com/charmbracelet/x/ansi/parser/seq.go new file mode 100644 index 00000000..de7e15e6 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/parser/seq.go @@ -0,0 +1,136 @@ +package parser + +import "math" + +// Shift and masks for sequence parameters and intermediates. +const ( + PrefixShift = 8 + IntermedShift = 16 + FinalMask = 0xff + HasMoreFlag = math.MinInt32 + ParamMask = ^HasMoreFlag + MissingParam = ParamMask + MissingCommand = MissingParam + MaxParam = math.MaxUint16 // the maximum value a parameter can have +) + +const ( + // MaxParamsSize is the maximum number of parameters a sequence can have. + MaxParamsSize = 32 + + // DefaultParamValue is the default value used for missing parameters. + DefaultParamValue = 0 +) + +// Prefix returns the prefix byte of the sequence. +// This is always gonna be one of the following '<' '=' '>' '?' and in the +// range of 0x3C-0x3F. +// Zero is returned if the sequence does not have a prefix. +func Prefix(cmd int) int { + return (cmd >> PrefixShift) & FinalMask +} + +// Intermediate returns the intermediate byte of the sequence. +// An intermediate byte is in the range of 0x20-0x2F. This includes these +// characters from ' ', '!', '"', '#', '$', '%', '&', ”', '(', ')', '*', '+', +// ',', '-', '.', '/'. +// Zero is returned if the sequence does not have an intermediate byte. +func Intermediate(cmd int) int { + return (cmd >> IntermedShift) & FinalMask +} + +// Command returns the command byte of the CSI sequence. +func Command(cmd int) int { + return cmd & FinalMask +} + +// Param returns the parameter at the given index. +// It returns -1 if the parameter does not exist. +func Param(params []int, i int) int { + if len(params) == 0 || i < 0 || i >= len(params) { + return -1 + } + + p := params[i] & ParamMask + if p == MissingParam { + return -1 + } + + return p +} + +// HasMore returns true if the parameter has more sub-parameters. +func HasMore(params []int, i int) bool { + if len(params) == 0 || i >= len(params) { + return false + } + + return params[i]&HasMoreFlag != 0 +} + +// Subparams returns the sub-parameters of the given parameter. +// It returns nil if the parameter does not exist. +func Subparams(params []int, i int) []int { + if len(params) == 0 || i < 0 || i >= len(params) { + return nil + } + + // Count the number of parameters before the given parameter index. + var count int + var j int + for j = range params { + if count == i { + break + } + if !HasMore(params, j) { + count++ + } + } + + if count > i || j >= len(params) { + return nil + } + + var subs []int + for ; j < len(params); j++ { + if !HasMore(params, j) { + break + } + p := Param(params, j) + if p == -1 { + p = DefaultParamValue + } + subs = append(subs, p) + } + + p := Param(params, j) + if p == -1 { + p = DefaultParamValue + } + + return append(subs, p) +} + +// Len returns the number of parameters in the sequence. +// This will return the number of parameters in the sequence, excluding any +// sub-parameters. +func Len(params []int) int { + var n int + for i := range params { + if !HasMore(params, i) { + n++ + } + } + return n +} + +// Range iterates over the parameters of the sequence and calls the given +// function for each parameter. +// The function should return false to stop the iteration. +func Range(params []int, fn func(i int, param int, hasMore bool) bool) { + for i := range params { + if !fn(i, Param(params, i), HasMore(params, i)) { + break + } + } +} diff --git a/vendor/github.com/charmbracelet/x/ansi/parser/transition_table.go b/vendor/github.com/charmbracelet/x/ansi/parser/transition_table.go new file mode 100644 index 00000000..7c41ba2c --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/parser/transition_table.go @@ -0,0 +1,273 @@ +package parser + +// Table values are generated like this: +// +// index: currentState << IndexStateShift | charCode +// value: action << TransitionActionShift | nextState +const ( + TransitionActionShift = 4 + TransitionStateMask = 15 + IndexStateShift = 8 + + // DefaultTableSize is the default size of the transition table. + DefaultTableSize = 4096 +) + +// Table is a DEC ANSI transition table. +var Table = GenerateTransitionTable() + +// TransitionTable is a DEC ANSI transition table. +// https://vt100.net/emu/dec_ansi_parser +type TransitionTable []byte + +// NewTransitionTable returns a new DEC ANSI transition table. +func NewTransitionTable(size int) TransitionTable { + if size <= 0 { + size = DefaultTableSize + } + return TransitionTable(make([]byte, size)) +} + +// SetDefault sets default transition. +func (t TransitionTable) SetDefault(action Action, state State) { + for i := range t { + t[i] = action<> TransitionActionShift +} + +// byte range macro +func r(start, end byte) []byte { + var a []byte + for i := int(start); i <= int(end); i++ { + a = append(a, byte(i)) + } + return a +} + +// GenerateTransitionTable generates a DEC ANSI transition table compatible +// with the VT500-series of terminals. This implementation includes a few +// modifications that include: +// - A new Utf8State is introduced to handle UTF8 sequences. +// - Osc and Dcs data accept UTF8 sequences by extending the printable range +// to 0xFF and 0xFE respectively. +// - We don't ignore 0x3A (':') when building Csi and Dcs parameters and +// instead use it to denote sub-parameters. +// - Support dispatching SosPmApc sequences. +// - The DEL (0x7F) character is executed in the Ground state. +// - The DEL (0x7F) character is collected in the DcsPassthrough string state. +// - The ST C1 control character (0x9C) is executed and not ignored. +func GenerateTransitionTable() TransitionTable { + table := NewTransitionTable(DefaultTableSize) + table.SetDefault(NoneAction, GroundState) + + // Anywhere + for _, state := range r(GroundState, Utf8State) { + // Anywhere -> Ground + table.AddMany([]byte{0x18, 0x1a, 0x99, 0x9a}, state, ExecuteAction, GroundState) + table.AddRange(0x80, 0x8F, state, ExecuteAction, GroundState) + table.AddRange(0x90, 0x97, state, ExecuteAction, GroundState) + table.AddOne(0x9C, state, ExecuteAction, GroundState) + // Anywhere -> Escape + table.AddOne(0x1B, state, ClearAction, EscapeState) + // Anywhere -> SosStringState + table.AddOne(0x98, state, StartAction, SosStringState) + // Anywhere -> PmStringState + table.AddOne(0x9E, state, StartAction, PmStringState) + // Anywhere -> ApcStringState + table.AddOne(0x9F, state, StartAction, ApcStringState) + // Anywhere -> CsiEntry + table.AddOne(0x9B, state, ClearAction, CsiEntryState) + // Anywhere -> DcsEntry + table.AddOne(0x90, state, ClearAction, DcsEntryState) + // Anywhere -> OscString + table.AddOne(0x9D, state, StartAction, OscStringState) + // Anywhere -> Utf8 + table.AddRange(0xC2, 0xDF, state, CollectAction, Utf8State) // UTF8 2 byte sequence + table.AddRange(0xE0, 0xEF, state, CollectAction, Utf8State) // UTF8 3 byte sequence + table.AddRange(0xF0, 0xF4, state, CollectAction, Utf8State) // UTF8 4 byte sequence + } + + // Ground + table.AddRange(0x00, 0x17, GroundState, ExecuteAction, GroundState) + table.AddOne(0x19, GroundState, ExecuteAction, GroundState) + table.AddRange(0x1C, 0x1F, GroundState, ExecuteAction, GroundState) + table.AddRange(0x20, 0x7E, GroundState, PrintAction, GroundState) + table.AddOne(0x7F, GroundState, ExecuteAction, GroundState) + + // EscapeIntermediate + table.AddRange(0x00, 0x17, EscapeIntermediateState, ExecuteAction, EscapeIntermediateState) + table.AddOne(0x19, EscapeIntermediateState, ExecuteAction, EscapeIntermediateState) + table.AddRange(0x1C, 0x1F, EscapeIntermediateState, ExecuteAction, EscapeIntermediateState) + table.AddRange(0x20, 0x2F, EscapeIntermediateState, CollectAction, EscapeIntermediateState) + table.AddOne(0x7F, EscapeIntermediateState, IgnoreAction, EscapeIntermediateState) + // EscapeIntermediate -> Ground + table.AddRange(0x30, 0x7E, EscapeIntermediateState, DispatchAction, GroundState) + + // Escape + table.AddRange(0x00, 0x17, EscapeState, ExecuteAction, EscapeState) + table.AddOne(0x19, EscapeState, ExecuteAction, EscapeState) + table.AddRange(0x1C, 0x1F, EscapeState, ExecuteAction, EscapeState) + table.AddOne(0x7F, EscapeState, IgnoreAction, EscapeState) + // Escape -> Ground + table.AddRange(0x30, 0x4F, EscapeState, DispatchAction, GroundState) + table.AddRange(0x51, 0x57, EscapeState, DispatchAction, GroundState) + table.AddOne(0x59, EscapeState, DispatchAction, GroundState) + table.AddOne(0x5A, EscapeState, DispatchAction, GroundState) + table.AddOne(0x5C, EscapeState, DispatchAction, GroundState) + table.AddRange(0x60, 0x7E, EscapeState, DispatchAction, GroundState) + // Escape -> Escape_intermediate + table.AddRange(0x20, 0x2F, EscapeState, CollectAction, EscapeIntermediateState) + // Escape -> Sos_pm_apc_string + table.AddOne('X', EscapeState, StartAction, SosStringState) // SOS + table.AddOne('^', EscapeState, StartAction, PmStringState) // PM + table.AddOne('_', EscapeState, StartAction, ApcStringState) // APC + // Escape -> Dcs_entry + table.AddOne('P', EscapeState, ClearAction, DcsEntryState) + // Escape -> Csi_entry + table.AddOne('[', EscapeState, ClearAction, CsiEntryState) + // Escape -> Osc_string + table.AddOne(']', EscapeState, StartAction, OscStringState) + + // Sos_pm_apc_string + for _, state := range r(SosStringState, ApcStringState) { + table.AddRange(0x00, 0x17, state, PutAction, state) + table.AddOne(0x19, state, PutAction, state) + table.AddRange(0x1C, 0x1F, state, PutAction, state) + table.AddRange(0x20, 0x7F, state, PutAction, state) + // ESC, ST, CAN, and SUB terminate the sequence + table.AddOne(0x1B, state, DispatchAction, EscapeState) + table.AddOne(0x9C, state, DispatchAction, GroundState) + table.AddMany([]byte{0x18, 0x1A}, state, IgnoreAction, GroundState) + } + + // Dcs_entry + table.AddRange(0x00, 0x07, DcsEntryState, IgnoreAction, DcsEntryState) + table.AddRange(0x0E, 0x17, DcsEntryState, IgnoreAction, DcsEntryState) + table.AddOne(0x19, DcsEntryState, IgnoreAction, DcsEntryState) + table.AddRange(0x1C, 0x1F, DcsEntryState, IgnoreAction, DcsEntryState) + table.AddOne(0x7F, DcsEntryState, IgnoreAction, DcsEntryState) + // Dcs_entry -> Dcs_intermediate + table.AddRange(0x20, 0x2F, DcsEntryState, CollectAction, DcsIntermediateState) + // Dcs_entry -> Dcs_param + table.AddRange(0x30, 0x3B, DcsEntryState, ParamAction, DcsParamState) + table.AddRange(0x3C, 0x3F, DcsEntryState, PrefixAction, DcsParamState) + // Dcs_entry -> Dcs_passthrough + table.AddRange(0x08, 0x0D, DcsEntryState, PutAction, DcsStringState) // Follows ECMA-48 § 8.3.27 + // XXX: allows passing ESC (not a ECMA-48 standard) this to allow for + // passthrough of ANSI sequences like in Screen or Tmux passthrough mode. + table.AddOne(0x1B, DcsEntryState, PutAction, DcsStringState) + table.AddRange(0x40, 0x7E, DcsEntryState, StartAction, DcsStringState) + + // Dcs_intermediate + table.AddRange(0x00, 0x17, DcsIntermediateState, IgnoreAction, DcsIntermediateState) + table.AddOne(0x19, DcsIntermediateState, IgnoreAction, DcsIntermediateState) + table.AddRange(0x1C, 0x1F, DcsIntermediateState, IgnoreAction, DcsIntermediateState) + table.AddRange(0x20, 0x2F, DcsIntermediateState, CollectAction, DcsIntermediateState) + table.AddOne(0x7F, DcsIntermediateState, IgnoreAction, DcsIntermediateState) + // Dcs_intermediate -> Dcs_passthrough + table.AddRange(0x30, 0x3F, DcsIntermediateState, StartAction, DcsStringState) + table.AddRange(0x40, 0x7E, DcsIntermediateState, StartAction, DcsStringState) + + // Dcs_param + table.AddRange(0x00, 0x17, DcsParamState, IgnoreAction, DcsParamState) + table.AddOne(0x19, DcsParamState, IgnoreAction, DcsParamState) + table.AddRange(0x1C, 0x1F, DcsParamState, IgnoreAction, DcsParamState) + table.AddRange(0x30, 0x3B, DcsParamState, ParamAction, DcsParamState) + table.AddOne(0x7F, DcsParamState, IgnoreAction, DcsParamState) + table.AddRange(0x3C, 0x3F, DcsParamState, IgnoreAction, DcsParamState) + // Dcs_param -> Dcs_intermediate + table.AddRange(0x20, 0x2F, DcsParamState, CollectAction, DcsIntermediateState) + // Dcs_param -> Dcs_passthrough + table.AddRange(0x40, 0x7E, DcsParamState, StartAction, DcsStringState) + + // Dcs_passthrough + table.AddRange(0x00, 0x17, DcsStringState, PutAction, DcsStringState) + table.AddOne(0x19, DcsStringState, PutAction, DcsStringState) + table.AddRange(0x1C, 0x1F, DcsStringState, PutAction, DcsStringState) + table.AddRange(0x20, 0x7E, DcsStringState, PutAction, DcsStringState) + table.AddOne(0x7F, DcsStringState, PutAction, DcsStringState) + table.AddRange(0x80, 0xFF, DcsStringState, PutAction, DcsStringState) // Allow Utf8 characters by extending the printable range from 0x7F to 0xFF + // ST, CAN, SUB, and ESC terminate the sequence + table.AddOne(0x1B, DcsStringState, DispatchAction, EscapeState) + table.AddOne(0x9C, DcsStringState, DispatchAction, GroundState) + table.AddMany([]byte{0x18, 0x1A}, DcsStringState, IgnoreAction, GroundState) + + // Csi_param + table.AddRange(0x00, 0x17, CsiParamState, ExecuteAction, CsiParamState) + table.AddOne(0x19, CsiParamState, ExecuteAction, CsiParamState) + table.AddRange(0x1C, 0x1F, CsiParamState, ExecuteAction, CsiParamState) + table.AddRange(0x30, 0x3B, CsiParamState, ParamAction, CsiParamState) + table.AddOne(0x7F, CsiParamState, IgnoreAction, CsiParamState) + table.AddRange(0x3C, 0x3F, CsiParamState, IgnoreAction, CsiParamState) + // Csi_param -> Ground + table.AddRange(0x40, 0x7E, CsiParamState, DispatchAction, GroundState) + // Csi_param -> Csi_intermediate + table.AddRange(0x20, 0x2F, CsiParamState, CollectAction, CsiIntermediateState) + + // Csi_intermediate + table.AddRange(0x00, 0x17, CsiIntermediateState, ExecuteAction, CsiIntermediateState) + table.AddOne(0x19, CsiIntermediateState, ExecuteAction, CsiIntermediateState) + table.AddRange(0x1C, 0x1F, CsiIntermediateState, ExecuteAction, CsiIntermediateState) + table.AddRange(0x20, 0x2F, CsiIntermediateState, CollectAction, CsiIntermediateState) + table.AddOne(0x7F, CsiIntermediateState, IgnoreAction, CsiIntermediateState) + // Csi_intermediate -> Ground + table.AddRange(0x40, 0x7E, CsiIntermediateState, DispatchAction, GroundState) + // Csi_intermediate -> Csi_ignore + table.AddRange(0x30, 0x3F, CsiIntermediateState, IgnoreAction, GroundState) + + // Csi_entry + table.AddRange(0x00, 0x17, CsiEntryState, ExecuteAction, CsiEntryState) + table.AddOne(0x19, CsiEntryState, ExecuteAction, CsiEntryState) + table.AddRange(0x1C, 0x1F, CsiEntryState, ExecuteAction, CsiEntryState) + table.AddOne(0x7F, CsiEntryState, IgnoreAction, CsiEntryState) + // Csi_entry -> Ground + table.AddRange(0x40, 0x7E, CsiEntryState, DispatchAction, GroundState) + // Csi_entry -> Csi_intermediate + table.AddRange(0x20, 0x2F, CsiEntryState, CollectAction, CsiIntermediateState) + // Csi_entry -> Csi_param + table.AddRange(0x30, 0x3B, CsiEntryState, ParamAction, CsiParamState) + table.AddRange(0x3C, 0x3F, CsiEntryState, PrefixAction, CsiParamState) + + // Osc_string + table.AddRange(0x00, 0x06, OscStringState, IgnoreAction, OscStringState) + table.AddRange(0x08, 0x17, OscStringState, IgnoreAction, OscStringState) + table.AddOne(0x19, OscStringState, IgnoreAction, OscStringState) + table.AddRange(0x1C, 0x1F, OscStringState, IgnoreAction, OscStringState) + table.AddRange(0x20, 0xFF, OscStringState, PutAction, OscStringState) // Allow Utf8 characters by extending the printable range from 0x7F to 0xFF + + // ST, CAN, SUB, ESC, and BEL terminate the sequence + table.AddOne(0x1B, OscStringState, DispatchAction, EscapeState) + table.AddOne(0x07, OscStringState, DispatchAction, GroundState) + table.AddOne(0x9C, OscStringState, DispatchAction, GroundState) + table.AddMany([]byte{0x18, 0x1A}, OscStringState, IgnoreAction, GroundState) + + return table +} diff --git a/vendor/github.com/charmbracelet/x/ansi/parser_decode.go b/vendor/github.com/charmbracelet/x/ansi/parser_decode.go new file mode 100644 index 00000000..dfd2dc76 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/parser_decode.go @@ -0,0 +1,524 @@ +package ansi + +import ( + "unicode/utf8" + + "github.com/charmbracelet/x/ansi/parser" + "github.com/mattn/go-runewidth" + "github.com/rivo/uniseg" +) + +// State represents the state of the ANSI escape sequence parser used by +// [DecodeSequence]. +type State = byte + +// ANSI escape sequence states used by [DecodeSequence]. +const ( + NormalState State = iota + PrefixState + ParamsState + IntermedState + EscapeState + StringState +) + +// DecodeSequence decodes the first ANSI escape sequence or a printable +// grapheme from the given data. It returns the sequence slice, the number of +// bytes read, the cell width for each sequence, and the new state. +// +// The cell width will always be 0 for control and escape sequences, 1 for +// ASCII printable characters, and the number of cells other Unicode characters +// occupy. It uses the uniseg package to calculate the width of Unicode +// graphemes and characters. This means it will always do grapheme clustering +// (mode 2027). +// +// Passing a non-nil [*Parser] as the last argument will allow the decoder to +// collect sequence parameters, data, and commands. The parser cmd will have +// the packed command value that contains intermediate and prefix characters. +// In the case of a OSC sequence, the cmd will be the OSC command number. Use +// [Cmd] and [Param] types to unpack command intermediates and prefixes as well +// as parameters. +// +// Zero [Cmd] means the CSI, DCS, or ESC sequence is invalid. Moreover, checking the +// validity of other data sequences, OSC, DCS, etc, will require checking for +// the returned sequence terminator bytes such as ST (ESC \\) and BEL). +// +// We store the command byte in [Cmd] in the most significant byte, the +// prefix byte in the next byte, and the intermediate byte in the least +// significant byte. This is done to avoid using a struct to store the command +// and its intermediates and prefixes. The command byte is always the least +// significant byte i.e. [Cmd & 0xff]. Use the [Cmd] type to unpack the +// command, intermediate, and prefix bytes. Note that we only collect the last +// prefix character and intermediate byte. +// +// The [p.Params] slice will contain the parameters of the sequence. Any +// sub-parameter will have the [parser.HasMoreFlag] set. Use the [Param] type +// to unpack the parameters. +// +// Example: +// +// var state byte // the initial state is always zero [NormalState] +// p := NewParser(32, 1024) // create a new parser with a 32 params buffer and 1024 data buffer (optional) +// input := []byte("\x1b[31mHello, World!\x1b[0m") +// for len(input) > 0 { +// seq, width, n, newState := DecodeSequence(input, state, p) +// log.Printf("seq: %q, width: %d", seq, width) +// state = newState +// input = input[n:] +// } +// +// This function treats the text as a sequence of grapheme clusters. +func DecodeSequence[T string | []byte](b T, state byte, p *Parser) (seq T, width int, n int, newState byte) { + return decodeSequence(GraphemeWidth, b, state, p) +} + +// DecodeSequenceWc decodes the first ANSI escape sequence or a printable +// grapheme from the given data. It returns the sequence slice, the number of +// bytes read, the cell width for each sequence, and the new state. +// +// The cell width will always be 0 for control and escape sequences, 1 for +// ASCII printable characters, and the number of cells other Unicode characters +// occupy. It uses the uniseg package to calculate the width of Unicode +// graphemes and characters. This means it will always do grapheme clustering +// (mode 2027). +// +// Passing a non-nil [*Parser] as the last argument will allow the decoder to +// collect sequence parameters, data, and commands. The parser cmd will have +// the packed command value that contains intermediate and prefix characters. +// In the case of a OSC sequence, the cmd will be the OSC command number. Use +// [Cmd] and [Param] types to unpack command intermediates and prefixes as well +// as parameters. +// +// Zero [Cmd] means the CSI, DCS, or ESC sequence is invalid. Moreover, checking the +// validity of other data sequences, OSC, DCS, etc, will require checking for +// the returned sequence terminator bytes such as ST (ESC \\) and BEL). +// +// We store the command byte in [Cmd] in the most significant byte, the +// prefix byte in the next byte, and the intermediate byte in the least +// significant byte. This is done to avoid using a struct to store the command +// and its intermediates and prefixes. The command byte is always the least +// significant byte i.e. [Cmd & 0xff]. Use the [Cmd] type to unpack the +// command, intermediate, and prefix bytes. Note that we only collect the last +// prefix character and intermediate byte. +// +// The [p.Params] slice will contain the parameters of the sequence. Any +// sub-parameter will have the [parser.HasMoreFlag] set. Use the [Param] type +// to unpack the parameters. +// +// Example: +// +// var state byte // the initial state is always zero [NormalState] +// p := NewParser(32, 1024) // create a new parser with a 32 params buffer and 1024 data buffer (optional) +// input := []byte("\x1b[31mHello, World!\x1b[0m") +// for len(input) > 0 { +// seq, width, n, newState := DecodeSequenceWc(input, state, p) +// log.Printf("seq: %q, width: %d", seq, width) +// state = newState +// input = input[n:] +// } +// +// This function treats the text as a sequence of wide characters and runes. +func DecodeSequenceWc[T string | []byte](b T, state byte, p *Parser) (seq T, width int, n int, newState byte) { + return decodeSequence(WcWidth, b, state, p) +} + +func decodeSequence[T string | []byte](m Method, b T, state State, p *Parser) (seq T, width int, n int, newState byte) { + for i := 0; i < len(b); i++ { + c := b[i] + + switch state { + case NormalState: + switch c { + case ESC: + if p != nil { + if len(p.params) > 0 { + p.params[0] = parser.MissingParam + } + p.cmd = 0 + p.paramsLen = 0 + p.dataLen = 0 + } + state = EscapeState + continue + case CSI, DCS: + if p != nil { + if len(p.params) > 0 { + p.params[0] = parser.MissingParam + } + p.cmd = 0 + p.paramsLen = 0 + p.dataLen = 0 + } + state = PrefixState + continue + case OSC, APC, SOS, PM: + if p != nil { + p.cmd = parser.MissingCommand + p.dataLen = 0 + } + state = StringState + continue + } + + if p != nil { + p.dataLen = 0 + p.paramsLen = 0 + p.cmd = 0 + } + if c > US && c < DEL { + // ASCII printable characters + return b[i : i+1], 1, 1, NormalState + } + + if c <= US || c == DEL || c < 0xC0 { + // C0 & C1 control characters & DEL + return b[i : i+1], 0, 1, NormalState + } + + if utf8.RuneStart(c) { + seq, _, width, _ = FirstGraphemeCluster(b, -1) + if m == WcWidth { + width = runewidth.StringWidth(string(seq)) + } + i += len(seq) + return b[:i], width, i, NormalState + } + + // Invalid UTF-8 sequence + return b[:i], 0, i, NormalState + case PrefixState: + if c >= '<' && c <= '?' { + if p != nil { + // We only collect the last prefix character. + p.cmd &^= 0xff << parser.PrefixShift + p.cmd |= int(c) << parser.PrefixShift + } + break + } + + state = ParamsState + fallthrough + case ParamsState: + if c >= '0' && c <= '9' { + if p != nil { + if p.params[p.paramsLen] == parser.MissingParam { + p.params[p.paramsLen] = 0 + } + + p.params[p.paramsLen] *= 10 + p.params[p.paramsLen] += int(c - '0') + } + break + } + + if c == ':' { + if p != nil { + p.params[p.paramsLen] |= parser.HasMoreFlag + } + } + + if c == ';' || c == ':' { + if p != nil { + p.paramsLen++ + if p.paramsLen < len(p.params) { + p.params[p.paramsLen] = parser.MissingParam + } + } + break + } + + state = IntermedState + fallthrough + case IntermedState: + if c >= ' ' && c <= '/' { + if p != nil { + p.cmd &^= 0xff << parser.IntermedShift + p.cmd |= int(c) << parser.IntermedShift + } + break + } + + if p != nil { + // Increment the last parameter + if p.paramsLen > 0 && p.paramsLen < len(p.params)-1 || + p.paramsLen == 0 && len(p.params) > 0 && p.params[0] != parser.MissingParam { + p.paramsLen++ + } + } + + if c >= '@' && c <= '~' { + if p != nil { + p.cmd &^= 0xff + p.cmd |= int(c) + } + + if HasDcsPrefix(b) { + // Continue to collect DCS data + if p != nil { + p.dataLen = 0 + } + state = StringState + continue + } + + return b[:i+1], 0, i + 1, NormalState + } + + // Invalid CSI/DCS sequence + return b[:i], 0, i, NormalState + case EscapeState: + switch c { + case '[', 'P': + if p != nil { + if len(p.params) > 0 { + p.params[0] = parser.MissingParam + } + p.paramsLen = 0 + p.cmd = 0 + } + state = PrefixState + continue + case ']', 'X', '^', '_': + if p != nil { + p.cmd = parser.MissingCommand + p.dataLen = 0 + } + state = StringState + continue + } + + if c >= ' ' && c <= '/' { + if p != nil { + p.cmd &^= 0xff << parser.IntermedShift + p.cmd |= int(c) << parser.IntermedShift + } + continue + } else if c >= '0' && c <= '~' { + if p != nil { + p.cmd &^= 0xff + p.cmd |= int(c) + } + return b[:i+1], 0, i + 1, NormalState + } + + // Invalid escape sequence + return b[:i], 0, i, NormalState + case StringState: + switch c { + case BEL: + if HasOscPrefix(b) { + parseOscCmd(p) + return b[:i+1], 0, i + 1, NormalState + } + case CAN, SUB: + if HasOscPrefix(b) { + // Ensure we parse the OSC command number + parseOscCmd(p) + } + + // Cancel the sequence + return b[:i], 0, i, NormalState + case ST: + if HasOscPrefix(b) { + // Ensure we parse the OSC command number + parseOscCmd(p) + } + + return b[:i+1], 0, i + 1, NormalState + case ESC: + if HasStPrefix(b[i:]) { + if HasOscPrefix(b) { + // Ensure we parse the OSC command number + parseOscCmd(p) + } + + // End of string 7-bit (ST) + return b[:i+2], 0, i + 2, NormalState + } + + // Otherwise, cancel the sequence + return b[:i], 0, i, NormalState + } + + if p != nil && p.dataLen < len(p.data) { + p.data[p.dataLen] = c + p.dataLen++ + + // Parse the OSC command number + if c == ';' && HasOscPrefix(b) { + parseOscCmd(p) + } + } + } + } + + return b, 0, len(b), state +} + +func parseOscCmd(p *Parser) { + if p == nil || p.cmd != parser.MissingCommand { + return + } + for j := range p.dataLen { + d := p.data[j] + if d < '0' || d > '9' { + break + } + if p.cmd == parser.MissingCommand { + p.cmd = 0 + } + p.cmd *= 10 + p.cmd += int(d - '0') + } +} + +// Equal returns true if the given byte slices are equal. +func Equal[T string | []byte](a, b T) bool { + return string(a) == string(b) +} + +// HasPrefix returns true if the given byte slice has prefix. +func HasPrefix[T string | []byte](b, prefix T) bool { + return len(b) >= len(prefix) && Equal(b[0:len(prefix)], prefix) +} + +// HasSuffix returns true if the given byte slice has suffix. +func HasSuffix[T string | []byte](b, suffix T) bool { + return len(b) >= len(suffix) && Equal(b[len(b)-len(suffix):], suffix) +} + +// HasCsiPrefix returns true if the given byte slice has a CSI prefix. +func HasCsiPrefix[T string | []byte](b T) bool { + return (len(b) > 0 && b[0] == CSI) || + (len(b) > 1 && b[0] == ESC && b[1] == '[') +} + +// HasOscPrefix returns true if the given byte slice has an OSC prefix. +func HasOscPrefix[T string | []byte](b T) bool { + return (len(b) > 0 && b[0] == OSC) || + (len(b) > 1 && b[0] == ESC && b[1] == ']') +} + +// HasApcPrefix returns true if the given byte slice has an APC prefix. +func HasApcPrefix[T string | []byte](b T) bool { + return (len(b) > 0 && b[0] == APC) || + (len(b) > 1 && b[0] == ESC && b[1] == '_') +} + +// HasDcsPrefix returns true if the given byte slice has a DCS prefix. +func HasDcsPrefix[T string | []byte](b T) bool { + return (len(b) > 0 && b[0] == DCS) || + (len(b) > 1 && b[0] == ESC && b[1] == 'P') +} + +// HasSosPrefix returns true if the given byte slice has a SOS prefix. +func HasSosPrefix[T string | []byte](b T) bool { + return (len(b) > 0 && b[0] == SOS) || + (len(b) > 1 && b[0] == ESC && b[1] == 'X') +} + +// HasPmPrefix returns true if the given byte slice has a PM prefix. +func HasPmPrefix[T string | []byte](b T) bool { + return (len(b) > 0 && b[0] == PM) || + (len(b) > 1 && b[0] == ESC && b[1] == '^') +} + +// HasStPrefix returns true if the given byte slice has a ST prefix. +func HasStPrefix[T string | []byte](b T) bool { + return (len(b) > 0 && b[0] == ST) || + (len(b) > 1 && b[0] == ESC && b[1] == '\\') +} + +// HasEscPrefix returns true if the given byte slice has an ESC prefix. +func HasEscPrefix[T string | []byte](b T) bool { + return len(b) > 0 && b[0] == ESC +} + +// FirstGraphemeCluster returns the first grapheme cluster in the given string or byte slice. +// This is a syntactic sugar function that wraps +// uniseg.FirstGraphemeClusterInString and uniseg.FirstGraphemeCluster. +func FirstGraphemeCluster[T string | []byte](b T, state int) (T, T, int, int) { + switch b := any(b).(type) { + case string: + cluster, rest, width, newState := uniseg.FirstGraphemeClusterInString(b, state) + return T(cluster), T(rest), width, newState + case []byte: + cluster, rest, width, newState := uniseg.FirstGraphemeCluster(b, state) + return T(cluster), T(rest), width, newState + } + panic("unreachable") +} + +// Cmd represents a sequence command. This is used to pack/unpack a sequence +// command with its intermediate and prefix characters. Those are commonly +// found in CSI and DCS sequences. +type Cmd int + +// Prefix returns the unpacked prefix byte of the CSI sequence. +// This is always gonna be one of the following '<' '=' '>' '?' and in the +// range of 0x3C-0x3F. +// Zero is returned if the sequence does not have a prefix. +func (c Cmd) Prefix() byte { + return byte(parser.Prefix(int(c))) +} + +// Intermediate returns the unpacked intermediate byte of the CSI sequence. +// An intermediate byte is in the range of 0x20-0x2F. This includes these +// characters from ' ', '!', '"', '#', '$', '%', '&', ”', '(', ')', '*', '+', +// ',', '-', '.', '/'. +// Zero is returned if the sequence does not have an intermediate byte. +func (c Cmd) Intermediate() byte { + return byte(parser.Intermediate(int(c))) +} + +// Final returns the unpacked command byte of the CSI sequence. +func (c Cmd) Final() byte { + return byte(parser.Command(int(c))) +} + +// Command packs a command with the given prefix, intermediate, and final. A +// zero byte means the sequence does not have a prefix or intermediate. +// +// Prefixes are in the range of 0x3C-0x3F that is one of `<=>?`. +// +// Intermediates are in the range of 0x20-0x2F that is anything in +// `!"#$%&'()*+,-./`. +// +// Final bytes are in the range of 0x40-0x7E that is anything in the range +// `@A–Z[\]^_`a–z{|}~`. +func Command(prefix, inter, final byte) (c int) { + c = int(final) + c |= int(prefix) << parser.PrefixShift + c |= int(inter) << parser.IntermedShift + return +} + +// Param represents a sequence parameter. Sequence parameters with +// sub-parameters are packed with the HasMoreFlag set. This is used to unpack +// the parameters from a CSI and DCS sequences. +type Param int + +// Param returns the unpacked parameter at the given index. +// It returns the default value if the parameter is missing. +func (s Param) Param(def int) int { + p := int(s) & parser.ParamMask + if p == parser.MissingParam { + return def + } + return p +} + +// HasMore unpacks the HasMoreFlag from the parameter. +func (s Param) HasMore() bool { + return s&parser.HasMoreFlag != 0 +} + +// Parameter packs an escape code parameter with the given parameter and +// whether this parameter has following sub-parameters. +func Parameter(p int, hasMore bool) (s int) { + s = p & parser.ParamMask + if hasMore { + s |= parser.HasMoreFlag + } + return +} diff --git a/vendor/github.com/charmbracelet/x/ansi/parser_handler.go b/vendor/github.com/charmbracelet/x/ansi/parser_handler.go new file mode 100644 index 00000000..03f9ed4c --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/parser_handler.go @@ -0,0 +1,60 @@ +package ansi + +import "unsafe" + +// Params represents a list of packed parameters. +type Params []Param + +// Param returns the parameter at the given index and if it is part of a +// sub-parameters. It falls back to the default value if the parameter is +// missing. If the index is out of bounds, it returns the default value and +// false. +func (p Params) Param(i, def int) (int, bool, bool) { + if i < 0 || i >= len(p) { + return def, false, false + } + return p[i].Param(def), p[i].HasMore(), true +} + +// ForEach iterates over the parameters and calls the given function for each +// parameter. If a parameter is part of a sub-parameter, it will be called with +// hasMore set to true. +// Use def to set a default value for missing parameters. +func (p Params) ForEach(def int, f func(i, param int, hasMore bool)) { + for i := range p { + f(i, p[i].Param(def), p[i].HasMore()) + } +} + +// ToParams converts a list of integers to a list of parameters. +func ToParams(params []int) Params { + return unsafe.Slice((*Param)(unsafe.Pointer(¶ms[0])), len(params)) +} + +// Handler handles actions performed by the parser. +// It is used to handle ANSI escape sequences, control characters, and runes. +type Handler struct { + // Print is called when a printable rune is encountered. + Print func(r rune) + // Execute is called when a control character is encountered. + Execute func(b byte) + // HandleCsi is called when a CSI sequence is encountered. + HandleCsi func(cmd Cmd, params Params) + // HandleEsc is called when an ESC sequence is encountered. + HandleEsc func(cmd Cmd) + // HandleDcs is called when a DCS sequence is encountered. + HandleDcs func(cmd Cmd, params Params, data []byte) + // HandleOsc is called when an OSC sequence is encountered. + HandleOsc func(cmd int, data []byte) + // HandlePm is called when a PM sequence is encountered. + HandlePm func(data []byte) + // HandleApc is called when an APC sequence is encountered. + HandleApc func(data []byte) + // HandleSos is called when a SOS sequence is encountered. + HandleSos func(data []byte) +} + +// SetHandler sets the handler for the parser. +func (p *Parser) SetHandler(h Handler) { + p.handler = h +} diff --git a/vendor/github.com/charmbracelet/x/ansi/parser_sync.go b/vendor/github.com/charmbracelet/x/ansi/parser_sync.go new file mode 100644 index 00000000..65d25a9a --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/parser_sync.go @@ -0,0 +1,29 @@ +package ansi + +import ( + "sync" + + "github.com/charmbracelet/x/ansi/parser" +) + +var parserPool = sync.Pool{ + New: func() any { + p := NewParser() + p.SetParamsSize(parser.MaxParamsSize) + p.SetDataSize(1024 * 1024 * 4) // 4MB of data buffer + return p + }, +} + +// GetParser returns a parser from a sync pool. +func GetParser() *Parser { + return parserPool.Get().(*Parser) +} + +// PutParser returns a parser to a sync pool. The parser is reset +// automatically. +func PutParser(p *Parser) { + p.Reset() + p.dataLen = 0 + parserPool.Put(p) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/passthrough.go b/vendor/github.com/charmbracelet/x/ansi/passthrough.go new file mode 100644 index 00000000..7ac7cef1 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/passthrough.go @@ -0,0 +1,60 @@ +package ansi + +import ( + "bytes" +) + +// ScreenPassthrough wraps the given ANSI sequence in a DCS passthrough +// sequence to be sent to the outer terminal. This is used to send raw escape +// sequences to the outer terminal when running inside GNU Screen. +// +// DCS ST +// +// Note: Screen limits the length of string sequences to 768 bytes (since 2014). +// Use zero to indicate no limit, otherwise, this will chunk the returned +// string into limit sized chunks. +// +// See: https://www.gnu.org/software/screen/manual/screen.html#String-Escapes +// See: https://git.savannah.gnu.org/cgit/screen.git/tree/src/screen.h?id=c184c6ec27683ff1a860c45be5cf520d896fd2ef#n44 +func ScreenPassthrough(seq string, limit int) string { + var b bytes.Buffer + b.WriteString("\x1bP") + if limit > 0 { + for i := 0; i < len(seq); i += limit { + end := min(i+limit, len(seq)) + b.WriteString(seq[i:end]) + if end < len(seq) { + b.WriteString("\x1b\\\x1bP") + } + } + } else { + b.WriteString(seq) + } + b.WriteString("\x1b\\") + return b.String() +} + +// TmuxPassthrough wraps the given ANSI sequence in a special DCS passthrough +// sequence to be sent to the outer terminal. This is used to send raw escape +// sequences to the outer terminal when running inside Tmux. +// +// DCS tmux ; ST +// +// Where is the given sequence in which all occurrences of ESC +// (0x1b) are doubled i.e. replaced with ESC ESC (0x1b 0x1b). +// +// Note: this needs the `allow-passthrough` option to be set to `on`. +// +// See: https://github.com/tmux/tmux/wiki/FAQ#what-is-the-passthrough-escape-sequence-and-how-do-i-use-it +func TmuxPassthrough(seq string) string { + var b bytes.Buffer + b.WriteString("\x1bPtmux;") + for i := range len(seq) { + if seq[i] == ESC { + b.WriteByte(ESC) + } + b.WriteByte(seq[i]) + } + b.WriteString("\x1b\\") + return b.String() +} diff --git a/vendor/github.com/charmbracelet/x/ansi/paste.go b/vendor/github.com/charmbracelet/x/ansi/paste.go new file mode 100644 index 00000000..2f9ea6f7 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/paste.go @@ -0,0 +1,7 @@ +package ansi + +// BracketedPasteStart is the control sequence to enable bracketed paste mode. +const BracketedPasteStart = "\x1b[200~" + +// BracketedPasteEnd is the control sequence to disable bracketed paste mode. +const BracketedPasteEnd = "\x1b[201~" diff --git a/vendor/github.com/charmbracelet/x/ansi/reset.go b/vendor/github.com/charmbracelet/x/ansi/reset.go new file mode 100644 index 00000000..c1b89ea4 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/reset.go @@ -0,0 +1,11 @@ +package ansi + +// ResetInitialState (RIS) resets the terminal to its initial state. +// +// ESC c +// +// See: https://vt100.net/docs/vt510-rm/RIS.html +const ( + ResetInitialState = "\x1bc" + RIS = ResetInitialState +) diff --git a/vendor/github.com/charmbracelet/x/ansi/screen.go b/vendor/github.com/charmbracelet/x/ansi/screen.go new file mode 100644 index 00000000..c76e4f0d --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/screen.go @@ -0,0 +1,410 @@ +package ansi + +import ( + "strconv" + "strings" +) + +// EraseDisplay (ED) clears the display or parts of the display. A screen is +// the shown part of the terminal display excluding the scrollback buffer. +// Possible values: +// +// Default is 0. +// +// 0: Clear from cursor to end of screen. +// 1: Clear from cursor to beginning of the screen. +// 2: Clear entire screen (and moves cursor to upper left on DOS). +// 3: Clear entire display which delete all lines saved in the scrollback buffer (xterm). +// +// CSI J +// +// See: https://vt100.net/docs/vt510-rm/ED.html +func EraseDisplay(n int) string { + var s string + if n > 0 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "J" +} + +// ED is an alias for [EraseDisplay]. +func ED(n int) string { + return EraseDisplay(n) +} + +// EraseDisplay constants. +// These are the possible values for the EraseDisplay function. +const ( + EraseScreenBelow = "\x1b[J" + EraseScreenAbove = "\x1b[1J" + EraseEntireScreen = "\x1b[2J" + EraseEntireDisplay = "\x1b[3J" +) + +// EraseLine (EL) clears the current line or parts of the line. Possible values: +// +// 0: Clear from cursor to end of line. +// 1: Clear from cursor to beginning of the line. +// 2: Clear entire line. +// +// The cursor position is not affected. +// +// CSI K +// +// See: https://vt100.net/docs/vt510-rm/EL.html +func EraseLine(n int) string { + var s string + if n > 0 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "K" +} + +// EL is an alias for [EraseLine]. +func EL(n int) string { + return EraseLine(n) +} + +// EraseLine constants. +// These are the possible values for the EraseLine function. +const ( + EraseLineRight = "\x1b[K" + EraseLineLeft = "\x1b[1K" + EraseEntireLine = "\x1b[2K" +) + +// ScrollUp (SU) scrolls the screen up n lines. New lines are added at the +// bottom of the screen. +// +// CSI Pn S +// +// See: https://vt100.net/docs/vt510-rm/SU.html +func ScrollUp(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "S" +} + +// PanDown is an alias for [ScrollUp]. +func PanDown(n int) string { + return ScrollUp(n) +} + +// SU is an alias for [ScrollUp]. +func SU(n int) string { + return ScrollUp(n) +} + +// ScrollDown (SD) scrolls the screen down n lines. New lines are added at the +// top of the screen. +// +// CSI Pn T +// +// See: https://vt100.net/docs/vt510-rm/SD.html +func ScrollDown(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "T" +} + +// PanUp is an alias for [ScrollDown]. +func PanUp(n int) string { + return ScrollDown(n) +} + +// SD is an alias for [ScrollDown]. +func SD(n int) string { + return ScrollDown(n) +} + +// InsertLine (IL) inserts n blank lines at the current cursor position. +// Existing lines are moved down. +// +// CSI Pn L +// +// See: https://vt100.net/docs/vt510-rm/IL.html +func InsertLine(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "L" +} + +// IL is an alias for [InsertLine]. +func IL(n int) string { + return InsertLine(n) +} + +// DeleteLine (DL) deletes n lines at the current cursor position. Existing +// lines are moved up. +// +// CSI Pn M +// +// See: https://vt100.net/docs/vt510-rm/DL.html +func DeleteLine(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "M" +} + +// DL is an alias for [DeleteLine]. +func DL(n int) string { + return DeleteLine(n) +} + +// SetTopBottomMargins (DECSTBM) sets the top and bottom margins for the scrolling +// region. The default is the entire screen. +// +// Default is 1 and the bottom of the screen. +// +// CSI Pt ; Pb r +// +// See: https://vt100.net/docs/vt510-rm/DECSTBM.html +func SetTopBottomMargins(top, bot int) string { + var t, b string + if top > 0 { + t = strconv.Itoa(top) + } + if bot > 0 { + b = strconv.Itoa(bot) + } + return "\x1b[" + t + ";" + b + "r" +} + +// DECSTBM is an alias for [SetTopBottomMargins]. +func DECSTBM(top, bot int) string { + return SetTopBottomMargins(top, bot) +} + +// SetLeftRightMargins (DECSLRM) sets the left and right margins for the scrolling +// region. +// +// Default is 1 and the right of the screen. +// +// CSI Pl ; Pr s +// +// See: https://vt100.net/docs/vt510-rm/DECSLRM.html +func SetLeftRightMargins(left, right int) string { + var l, r string + if left > 0 { + l = strconv.Itoa(left) + } + if right > 0 { + r = strconv.Itoa(right) + } + return "\x1b[" + l + ";" + r + "s" +} + +// DECSLRM is an alias for [SetLeftRightMargins]. +func DECSLRM(left, right int) string { + return SetLeftRightMargins(left, right) +} + +// SetScrollingRegion (DECSTBM) sets the top and bottom margins for the scrolling +// region. The default is the entire screen. +// +// CSI ; r +// +// See: https://vt100.net/docs/vt510-rm/DECSTBM.html +// +// Deprecated: use [SetTopBottomMargins] instead. +func SetScrollingRegion(t, b int) string { + if t < 0 { + t = 0 + } + if b < 0 { + b = 0 + } + return "\x1b[" + strconv.Itoa(t) + ";" + strconv.Itoa(b) + "r" +} + +// InsertCharacter (ICH) inserts n blank characters at the current cursor +// position. Existing characters move to the right. Characters moved past the +// right margin are lost. ICH has no effect outside the scrolling margins. +// +// Default is 1. +// +// CSI Pn @ +// +// See: https://vt100.net/docs/vt510-rm/ICH.html +func InsertCharacter(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "@" +} + +// ICH is an alias for [InsertCharacter]. +func ICH(n int) string { + return InsertCharacter(n) +} + +// DeleteCharacter (DCH) deletes n characters at the current cursor position. +// As the characters are deleted, the remaining characters move to the left and +// the cursor remains at the same position. +// +// Default is 1. +// +// CSI Pn P +// +// See: https://vt100.net/docs/vt510-rm/DCH.html +func DeleteCharacter(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "P" +} + +// DCH is an alias for [DeleteCharacter]. +func DCH(n int) string { + return DeleteCharacter(n) +} + +// SetTabEvery8Columns (DECST8C) sets the tab stops at every 8 columns. +// +// CSI ? 5 W +// +// See: https://vt100.net/docs/vt510-rm/DECST8C.html +const ( + SetTabEvery8Columns = "\x1b[?5W" + DECST8C = SetTabEvery8Columns +) + +// HorizontalTabSet (HTS) sets a horizontal tab stop at the current cursor +// column. +// +// This is equivalent to [HTS]. +// +// ESC H +// +// See: https://vt100.net/docs/vt510-rm/HTS.html +const HorizontalTabSet = "\x1bH" + +// TabClear (TBC) clears tab stops. +// +// Default is 0. +// +// Possible values: +// 0: Clear tab stop at the current column. (default) +// 3: Clear all tab stops. +// +// CSI Pn g +// +// See: https://vt100.net/docs/vt510-rm/TBC.html +func TabClear(n int) string { + var s string + if n > 0 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "g" +} + +// TBC is an alias for [TabClear]. +func TBC(n int) string { + return TabClear(n) +} + +// RequestPresentationStateReport (DECRQPSR) requests the terminal to send a +// report of the presentation state. This includes the cursor information [DECCIR], +// and tab stop [DECTABSR] reports. +// +// Default is 0. +// +// Possible values: +// 0: Error, request ignored. +// 1: Cursor information report [DECCIR]. +// 2: Tab stop report [DECTABSR]. +// +// CSI Ps $ w +// +// See: https://vt100.net/docs/vt510-rm/DECRQPSR.html +func RequestPresentationStateReport(n int) string { + var s string + if n > 0 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "$w" +} + +// DECRQPSR is an alias for [RequestPresentationStateReport]. +func DECRQPSR(n int) string { + return RequestPresentationStateReport(n) +} + +// TabStopReport (DECTABSR) is the response to a tab stop report request. +// It reports the tab stops set in the terminal. +// +// The response is a list of tab stops separated by a slash (/) character. +// +// DCS 2 $ u D ... D ST +// +// Where D is a decimal number representing a tab stop. +// +// See: https://vt100.net/docs/vt510-rm/DECTABSR.html +func TabStopReport(stops ...int) string { + var s []string + for _, v := range stops { + s = append(s, strconv.Itoa(v)) + } + return "\x1bP2$u" + strings.Join(s, "/") + "\x1b\\" +} + +// DECTABSR is an alias for [TabStopReport]. +func DECTABSR(stops ...int) string { + return TabStopReport(stops...) +} + +// CursorInformationReport (DECCIR) is the response to a cursor information +// report request. It reports the cursor position, visual attributes, and +// character protection attributes. It also reports the status of origin mode +// [DECOM] and the current active character set. +// +// The response is a list of values separated by a semicolon (;) character. +// +// DCS 1 $ u D ... D ST +// +// Where D is a decimal number representing a value. +// +// See: https://vt100.net/docs/vt510-rm/DECCIR.html +func CursorInformationReport(values ...int) string { + var s []string + for _, v := range values { + s = append(s, strconv.Itoa(v)) + } + return "\x1bP1$u" + strings.Join(s, ";") + "\x1b\\" +} + +// DECCIR is an alias for [CursorInformationReport]. +func DECCIR(values ...int) string { + return CursorInformationReport(values...) +} + +// RepeatPreviousCharacter (REP) repeats the previous character n times. +// This is identical to typing the same character n times. +// +// Default is 1. +// +// CSI Pn b +// +// See: ECMA-48 § 8.3.103 +func RepeatPreviousCharacter(n int) string { + var s string + if n > 1 { + s = strconv.Itoa(n) + } + return "\x1b[" + s + "b" +} + +// REP is an alias for [RepeatPreviousCharacter]. +func REP(n int) string { + return RepeatPreviousCharacter(n) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/sgr.go b/vendor/github.com/charmbracelet/x/ansi/sgr.go new file mode 100644 index 00000000..c4bd2afa --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/sgr.go @@ -0,0 +1,79 @@ +package ansi + +// Select Graphic Rendition (SGR) is a command that sets display attributes. +// +// Default is 0. +// +// CSI Ps ; Ps ... m +// +// See: https://vt100.net/docs/vt510-rm/SGR.html +func SelectGraphicRendition(ps ...Attr) string { + if len(ps) == 0 { + return ResetStyle + } + + return NewStyle(ps...).String() +} + +// SGR is an alias for [SelectGraphicRendition]. +func SGR(ps ...Attr) string { + return SelectGraphicRendition(ps...) +} + +var attrStrings = map[int]string{ + ResetAttr: resetAttr, + BoldAttr: boldAttr, + FaintAttr: faintAttr, + ItalicAttr: italicAttr, + UnderlineAttr: underlineAttr, + SlowBlinkAttr: slowBlinkAttr, + RapidBlinkAttr: rapidBlinkAttr, + ReverseAttr: reverseAttr, + ConcealAttr: concealAttr, + StrikethroughAttr: strikethroughAttr, + NormalIntensityAttr: normalIntensityAttr, + NoItalicAttr: noItalicAttr, + NoUnderlineAttr: noUnderlineAttr, + NoBlinkAttr: noBlinkAttr, + NoReverseAttr: noReverseAttr, + NoConcealAttr: noConcealAttr, + NoStrikethroughAttr: noStrikethroughAttr, + BlackForegroundColorAttr: blackForegroundColorAttr, + RedForegroundColorAttr: redForegroundColorAttr, + GreenForegroundColorAttr: greenForegroundColorAttr, + YellowForegroundColorAttr: yellowForegroundColorAttr, + BlueForegroundColorAttr: blueForegroundColorAttr, + MagentaForegroundColorAttr: magentaForegroundColorAttr, + CyanForegroundColorAttr: cyanForegroundColorAttr, + WhiteForegroundColorAttr: whiteForegroundColorAttr, + ExtendedForegroundColorAttr: extendedForegroundColorAttr, + DefaultForegroundColorAttr: defaultForegroundColorAttr, + BlackBackgroundColorAttr: blackBackgroundColorAttr, + RedBackgroundColorAttr: redBackgroundColorAttr, + GreenBackgroundColorAttr: greenBackgroundColorAttr, + YellowBackgroundColorAttr: yellowBackgroundColorAttr, + BlueBackgroundColorAttr: blueBackgroundColorAttr, + MagentaBackgroundColorAttr: magentaBackgroundColorAttr, + CyanBackgroundColorAttr: cyanBackgroundColorAttr, + WhiteBackgroundColorAttr: whiteBackgroundColorAttr, + ExtendedBackgroundColorAttr: extendedBackgroundColorAttr, + DefaultBackgroundColorAttr: defaultBackgroundColorAttr, + ExtendedUnderlineColorAttr: extendedUnderlineColorAttr, + DefaultUnderlineColorAttr: defaultUnderlineColorAttr, + BrightBlackForegroundColorAttr: brightBlackForegroundColorAttr, + BrightRedForegroundColorAttr: brightRedForegroundColorAttr, + BrightGreenForegroundColorAttr: brightGreenForegroundColorAttr, + BrightYellowForegroundColorAttr: brightYellowForegroundColorAttr, + BrightBlueForegroundColorAttr: brightBlueForegroundColorAttr, + BrightMagentaForegroundColorAttr: brightMagentaForegroundColorAttr, + BrightCyanForegroundColorAttr: brightCyanForegroundColorAttr, + BrightWhiteForegroundColorAttr: brightWhiteForegroundColorAttr, + BrightBlackBackgroundColorAttr: brightBlackBackgroundColorAttr, + BrightRedBackgroundColorAttr: brightRedBackgroundColorAttr, + BrightGreenBackgroundColorAttr: brightGreenBackgroundColorAttr, + BrightYellowBackgroundColorAttr: brightYellowBackgroundColorAttr, + BrightBlueBackgroundColorAttr: brightBlueBackgroundColorAttr, + BrightMagentaBackgroundColorAttr: brightMagentaBackgroundColorAttr, + BrightCyanBackgroundColorAttr: brightCyanBackgroundColorAttr, + BrightWhiteBackgroundColorAttr: brightWhiteBackgroundColorAttr, +} diff --git a/vendor/github.com/charmbracelet/x/ansi/status.go b/vendor/github.com/charmbracelet/x/ansi/status.go new file mode 100644 index 00000000..4337e189 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/status.go @@ -0,0 +1,144 @@ +package ansi + +import ( + "strconv" + "strings" +) + +// StatusReport represents a terminal status report. +type StatusReport interface { + // StatusReport returns the status report identifier. + StatusReport() int +} + +// ANSIReport represents an ANSI terminal status report. +type ANSIStatusReport int //nolint:revive + +// Report returns the status report identifier. +func (s ANSIStatusReport) StatusReport() int { + return int(s) +} + +// DECStatusReport represents a DEC terminal status report. +type DECStatusReport int + +// Status returns the status report identifier. +func (s DECStatusReport) StatusReport() int { + return int(s) +} + +// DeviceStatusReport (DSR) is a control sequence that reports the terminal's +// status. +// The terminal responds with a DSR sequence. +// +// CSI Ps n +// CSI ? Ps n +// +// If one of the statuses is a [DECStatus], the sequence will use the DEC +// format. +// +// See also https://vt100.net/docs/vt510-rm/DSR.html +func DeviceStatusReport(statues ...StatusReport) string { + var dec bool + list := make([]string, len(statues)) + seq := "\x1b[" + for i, status := range statues { + list[i] = strconv.Itoa(status.StatusReport()) + switch status.(type) { + case DECStatusReport: + dec = true + } + } + if dec { + seq += "?" + } + return seq + strings.Join(list, ";") + "n" +} + +// DSR is an alias for [DeviceStatusReport]. +func DSR(status StatusReport) string { + return DeviceStatusReport(status) +} + +// RequestCursorPositionReport is an escape sequence that requests the current +// cursor position. +// +// CSI 6 n +// +// The terminal will report the cursor position as a CSI sequence in the +// following format: +// +// CSI Pl ; Pc R +// +// Where Pl is the line number and Pc is the column number. +// See: https://vt100.net/docs/vt510-rm/CPR.html +const RequestCursorPositionReport = "\x1b[6n" + +// RequestExtendedCursorPositionReport (DECXCPR) is a sequence for requesting +// the cursor position report including the current page number. +// +// CSI ? 6 n +// +// The terminal will report the cursor position as a CSI sequence in the +// following format: +// +// CSI ? Pl ; Pc ; Pp R +// +// Where Pl is the line number, Pc is the column number, and Pp is the page +// number. +// See: https://vt100.net/docs/vt510-rm/DECXCPR.html +const RequestExtendedCursorPositionReport = "\x1b[?6n" + +// CursorPositionReport (CPR) is a control sequence that reports the cursor's +// position. +// +// CSI Pl ; Pc R +// +// Where Pl is the line number and Pc is the column number. +// +// See also https://vt100.net/docs/vt510-rm/CPR.html +func CursorPositionReport(line, column int) string { + if line < 1 { + line = 1 + } + if column < 1 { + column = 1 + } + return "\x1b[" + strconv.Itoa(line) + ";" + strconv.Itoa(column) + "R" +} + +// CPR is an alias for [CursorPositionReport]. +func CPR(line, column int) string { + return CursorPositionReport(line, column) +} + +// ExtendedCursorPositionReport (DECXCPR) is a control sequence that reports the +// cursor's position along with the page number (optional). +// +// CSI ? Pl ; Pc R +// CSI ? Pl ; Pc ; Pv R +// +// Where Pl is the line number, Pc is the column number, and Pv is the page +// number. +// +// If the page number is zero or negative, the returned sequence won't include +// the page number. +// +// See also https://vt100.net/docs/vt510-rm/DECXCPR.html +func ExtendedCursorPositionReport(line, column, page int) string { + if line < 1 { + line = 1 + } + if column < 1 { + column = 1 + } + if page < 1 { + return "\x1b[?" + strconv.Itoa(line) + ";" + strconv.Itoa(column) + "R" + } + return "\x1b[?" + strconv.Itoa(line) + ";" + strconv.Itoa(column) + ";" + strconv.Itoa(page) + "R" +} + +// DECXCPR is an alias for [ExtendedCursorPositionReport]. +func DECXCPR(line, column, page int) string { + return ExtendedCursorPositionReport(line, column, page) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/style.go b/vendor/github.com/charmbracelet/x/ansi/style.go new file mode 100644 index 00000000..c8663f32 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/style.go @@ -0,0 +1,673 @@ +package ansi + +import ( + "image/color" + "strconv" + "strings" +) + +// ResetStyle is a SGR (Select Graphic Rendition) style sequence that resets +// all attributes. +// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters +const ResetStyle = "\x1b[m" + +// Attr is a SGR (Select Graphic Rendition) style attribute. +type Attr = int + +// Style represents an ANSI SGR (Select Graphic Rendition) style. +type Style []string + +// NewStyle returns a new style with the given attributes. +func NewStyle(attrs ...Attr) Style { + if len(attrs) == 0 { + return Style{} + } + s := make(Style, 0, len(attrs)) + for _, a := range attrs { + attr, ok := attrStrings[a] + if ok { + s = append(s, attr) + } else { + if a < 0 { + a = 0 + } + s = append(s, strconv.Itoa(a)) + } + } + return s +} + +// String returns the ANSI SGR (Select Graphic Rendition) style sequence for +// the given style. +func (s Style) String() string { + if len(s) == 0 { + return ResetStyle + } + return "\x1b[" + strings.Join(s, ";") + "m" +} + +// Styled returns a styled string with the given style applied. +func (s Style) Styled(str string) string { + if len(s) == 0 { + return str + } + return s.String() + str + ResetStyle +} + +// Reset appends the reset style attribute to the style. +func (s Style) Reset() Style { + return append(s, resetAttr) +} + +// Bold appends the bold style attribute to the style. +func (s Style) Bold() Style { + return append(s, boldAttr) +} + +// Faint appends the faint style attribute to the style. +func (s Style) Faint() Style { + return append(s, faintAttr) +} + +// Italic appends the italic style attribute to the style. +func (s Style) Italic() Style { + return append(s, italicAttr) +} + +// Underline appends the underline style attribute to the style. +func (s Style) Underline() Style { + return append(s, underlineAttr) +} + +// UnderlineStyle appends the underline style attribute to the style. +func (s Style) UnderlineStyle(u UnderlineStyle) Style { + switch u { + case NoUnderlineStyle: + return s.NoUnderline() + case SingleUnderlineStyle: + return s.Underline() + case DoubleUnderlineStyle: + return append(s, doubleUnderlineStyle) + case CurlyUnderlineStyle: + return append(s, curlyUnderlineStyle) + case DottedUnderlineStyle: + return append(s, dottedUnderlineStyle) + case DashedUnderlineStyle: + return append(s, dashedUnderlineStyle) + } + return s +} + +// DoubleUnderline appends the double underline style attribute to the style. +// This is a convenience method for UnderlineStyle(DoubleUnderlineStyle). +func (s Style) DoubleUnderline() Style { + return s.UnderlineStyle(DoubleUnderlineStyle) +} + +// CurlyUnderline appends the curly underline style attribute to the style. +// This is a convenience method for UnderlineStyle(CurlyUnderlineStyle). +func (s Style) CurlyUnderline() Style { + return s.UnderlineStyle(CurlyUnderlineStyle) +} + +// DottedUnderline appends the dotted underline style attribute to the style. +// This is a convenience method for UnderlineStyle(DottedUnderlineStyle). +func (s Style) DottedUnderline() Style { + return s.UnderlineStyle(DottedUnderlineStyle) +} + +// DashedUnderline appends the dashed underline style attribute to the style. +// This is a convenience method for UnderlineStyle(DashedUnderlineStyle). +func (s Style) DashedUnderline() Style { + return s.UnderlineStyle(DashedUnderlineStyle) +} + +// SlowBlink appends the slow blink style attribute to the style. +func (s Style) SlowBlink() Style { + return append(s, slowBlinkAttr) +} + +// RapidBlink appends the rapid blink style attribute to the style. +func (s Style) RapidBlink() Style { + return append(s, rapidBlinkAttr) +} + +// Reverse appends the reverse style attribute to the style. +func (s Style) Reverse() Style { + return append(s, reverseAttr) +} + +// Conceal appends the conceal style attribute to the style. +func (s Style) Conceal() Style { + return append(s, concealAttr) +} + +// Strikethrough appends the strikethrough style attribute to the style. +func (s Style) Strikethrough() Style { + return append(s, strikethroughAttr) +} + +// NormalIntensity appends the normal intensity style attribute to the style. +func (s Style) NormalIntensity() Style { + return append(s, normalIntensityAttr) +} + +// NoItalic appends the no italic style attribute to the style. +func (s Style) NoItalic() Style { + return append(s, noItalicAttr) +} + +// NoUnderline appends the no underline style attribute to the style. +func (s Style) NoUnderline() Style { + return append(s, noUnderlineAttr) +} + +// NoBlink appends the no blink style attribute to the style. +func (s Style) NoBlink() Style { + return append(s, noBlinkAttr) +} + +// NoReverse appends the no reverse style attribute to the style. +func (s Style) NoReverse() Style { + return append(s, noReverseAttr) +} + +// NoConceal appends the no conceal style attribute to the style. +func (s Style) NoConceal() Style { + return append(s, noConcealAttr) +} + +// NoStrikethrough appends the no strikethrough style attribute to the style. +func (s Style) NoStrikethrough() Style { + return append(s, noStrikethroughAttr) +} + +// DefaultForegroundColor appends the default foreground color style attribute to the style. +func (s Style) DefaultForegroundColor() Style { + return append(s, defaultForegroundColorAttr) +} + +// DefaultBackgroundColor appends the default background color style attribute to the style. +func (s Style) DefaultBackgroundColor() Style { + return append(s, defaultBackgroundColorAttr) +} + +// DefaultUnderlineColor appends the default underline color style attribute to the style. +func (s Style) DefaultUnderlineColor() Style { + return append(s, defaultUnderlineColorAttr) +} + +// ForegroundColor appends the foreground color style attribute to the style. +func (s Style) ForegroundColor(c Color) Style { + return append(s, foregroundColorString(c)) +} + +// BackgroundColor appends the background color style attribute to the style. +func (s Style) BackgroundColor(c Color) Style { + return append(s, backgroundColorString(c)) +} + +// UnderlineColor appends the underline color style attribute to the style. +func (s Style) UnderlineColor(c Color) Style { + return append(s, underlineColorString(c)) +} + +// UnderlineStyle represents an ANSI SGR (Select Graphic Rendition) underline +// style. +type UnderlineStyle = byte + +const ( + doubleUnderlineStyle = "4:2" + curlyUnderlineStyle = "4:3" + dottedUnderlineStyle = "4:4" + dashedUnderlineStyle = "4:5" +) + +const ( + // NoUnderlineStyle is the default underline style. + NoUnderlineStyle UnderlineStyle = iota + // SingleUnderlineStyle is a single underline style. + SingleUnderlineStyle + // DoubleUnderlineStyle is a double underline style. + DoubleUnderlineStyle + // CurlyUnderlineStyle is a curly underline style. + CurlyUnderlineStyle + // DottedUnderlineStyle is a dotted underline style. + DottedUnderlineStyle + // DashedUnderlineStyle is a dashed underline style. + DashedUnderlineStyle +) + +// SGR (Select Graphic Rendition) style attributes. +// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters +const ( + ResetAttr Attr = 0 + BoldAttr Attr = 1 + FaintAttr Attr = 2 + ItalicAttr Attr = 3 + UnderlineAttr Attr = 4 + SlowBlinkAttr Attr = 5 + RapidBlinkAttr Attr = 6 + ReverseAttr Attr = 7 + ConcealAttr Attr = 8 + StrikethroughAttr Attr = 9 + NormalIntensityAttr Attr = 22 + NoItalicAttr Attr = 23 + NoUnderlineAttr Attr = 24 + NoBlinkAttr Attr = 25 + NoReverseAttr Attr = 27 + NoConcealAttr Attr = 28 + NoStrikethroughAttr Attr = 29 + BlackForegroundColorAttr Attr = 30 + RedForegroundColorAttr Attr = 31 + GreenForegroundColorAttr Attr = 32 + YellowForegroundColorAttr Attr = 33 + BlueForegroundColorAttr Attr = 34 + MagentaForegroundColorAttr Attr = 35 + CyanForegroundColorAttr Attr = 36 + WhiteForegroundColorAttr Attr = 37 + ExtendedForegroundColorAttr Attr = 38 + DefaultForegroundColorAttr Attr = 39 + BlackBackgroundColorAttr Attr = 40 + RedBackgroundColorAttr Attr = 41 + GreenBackgroundColorAttr Attr = 42 + YellowBackgroundColorAttr Attr = 43 + BlueBackgroundColorAttr Attr = 44 + MagentaBackgroundColorAttr Attr = 45 + CyanBackgroundColorAttr Attr = 46 + WhiteBackgroundColorAttr Attr = 47 + ExtendedBackgroundColorAttr Attr = 48 + DefaultBackgroundColorAttr Attr = 49 + ExtendedUnderlineColorAttr Attr = 58 + DefaultUnderlineColorAttr Attr = 59 + BrightBlackForegroundColorAttr Attr = 90 + BrightRedForegroundColorAttr Attr = 91 + BrightGreenForegroundColorAttr Attr = 92 + BrightYellowForegroundColorAttr Attr = 93 + BrightBlueForegroundColorAttr Attr = 94 + BrightMagentaForegroundColorAttr Attr = 95 + BrightCyanForegroundColorAttr Attr = 96 + BrightWhiteForegroundColorAttr Attr = 97 + BrightBlackBackgroundColorAttr Attr = 100 + BrightRedBackgroundColorAttr Attr = 101 + BrightGreenBackgroundColorAttr Attr = 102 + BrightYellowBackgroundColorAttr Attr = 103 + BrightBlueBackgroundColorAttr Attr = 104 + BrightMagentaBackgroundColorAttr Attr = 105 + BrightCyanBackgroundColorAttr Attr = 106 + BrightWhiteBackgroundColorAttr Attr = 107 + + RGBColorIntroducerAttr Attr = 2 + ExtendedColorIntroducerAttr Attr = 5 +) + +const ( + resetAttr = "0" + boldAttr = "1" + faintAttr = "2" + italicAttr = "3" + underlineAttr = "4" + slowBlinkAttr = "5" + rapidBlinkAttr = "6" + reverseAttr = "7" + concealAttr = "8" + strikethroughAttr = "9" + normalIntensityAttr = "22" + noItalicAttr = "23" + noUnderlineAttr = "24" + noBlinkAttr = "25" + noReverseAttr = "27" + noConcealAttr = "28" + noStrikethroughAttr = "29" + blackForegroundColorAttr = "30" + redForegroundColorAttr = "31" + greenForegroundColorAttr = "32" + yellowForegroundColorAttr = "33" + blueForegroundColorAttr = "34" + magentaForegroundColorAttr = "35" + cyanForegroundColorAttr = "36" + whiteForegroundColorAttr = "37" + extendedForegroundColorAttr = "38" + defaultForegroundColorAttr = "39" + blackBackgroundColorAttr = "40" + redBackgroundColorAttr = "41" + greenBackgroundColorAttr = "42" + yellowBackgroundColorAttr = "43" + blueBackgroundColorAttr = "44" + magentaBackgroundColorAttr = "45" + cyanBackgroundColorAttr = "46" + whiteBackgroundColorAttr = "47" + extendedBackgroundColorAttr = "48" + defaultBackgroundColorAttr = "49" + extendedUnderlineColorAttr = "58" + defaultUnderlineColorAttr = "59" + brightBlackForegroundColorAttr = "90" + brightRedForegroundColorAttr = "91" + brightGreenForegroundColorAttr = "92" + brightYellowForegroundColorAttr = "93" + brightBlueForegroundColorAttr = "94" + brightMagentaForegroundColorAttr = "95" + brightCyanForegroundColorAttr = "96" + brightWhiteForegroundColorAttr = "97" + brightBlackBackgroundColorAttr = "100" + brightRedBackgroundColorAttr = "101" + brightGreenBackgroundColorAttr = "102" + brightYellowBackgroundColorAttr = "103" + brightBlueBackgroundColorAttr = "104" + brightMagentaBackgroundColorAttr = "105" + brightCyanBackgroundColorAttr = "106" + brightWhiteBackgroundColorAttr = "107" +) + +// foregroundColorString returns the style SGR attribute for the given +// foreground color. +// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters +func foregroundColorString(c Color) string { + switch c := c.(type) { + case BasicColor: + // 3-bit or 4-bit ANSI foreground + // "3" or "9" where n is the color number from 0 to 7 + switch c { + case Black: + return blackForegroundColorAttr + case Red: + return redForegroundColorAttr + case Green: + return greenForegroundColorAttr + case Yellow: + return yellowForegroundColorAttr + case Blue: + return blueForegroundColorAttr + case Magenta: + return magentaForegroundColorAttr + case Cyan: + return cyanForegroundColorAttr + case White: + return whiteForegroundColorAttr + case BrightBlack: + return brightBlackForegroundColorAttr + case BrightRed: + return brightRedForegroundColorAttr + case BrightGreen: + return brightGreenForegroundColorAttr + case BrightYellow: + return brightYellowForegroundColorAttr + case BrightBlue: + return brightBlueForegroundColorAttr + case BrightMagenta: + return brightMagentaForegroundColorAttr + case BrightCyan: + return brightCyanForegroundColorAttr + case BrightWhite: + return brightWhiteForegroundColorAttr + } + case ExtendedColor: + // 256-color ANSI foreground + // "38;5;" + return "38;5;" + strconv.FormatUint(uint64(c), 10) + case TrueColor, color.Color: + // 24-bit "true color" foreground + // "38;2;;;" + r, g, b, _ := c.RGBA() + return "38;2;" + + strconv.FormatUint(uint64(shift(r)), 10) + ";" + + strconv.FormatUint(uint64(shift(g)), 10) + ";" + + strconv.FormatUint(uint64(shift(b)), 10) + } + return defaultForegroundColorAttr +} + +// backgroundColorString returns the style SGR attribute for the given +// background color. +// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters +func backgroundColorString(c Color) string { + switch c := c.(type) { + case BasicColor: + // 3-bit or 4-bit ANSI foreground + // "4" or "10" where n is the color number from 0 to 7 + switch c { + case Black: + return blackBackgroundColorAttr + case Red: + return redBackgroundColorAttr + case Green: + return greenBackgroundColorAttr + case Yellow: + return yellowBackgroundColorAttr + case Blue: + return blueBackgroundColorAttr + case Magenta: + return magentaBackgroundColorAttr + case Cyan: + return cyanBackgroundColorAttr + case White: + return whiteBackgroundColorAttr + case BrightBlack: + return brightBlackBackgroundColorAttr + case BrightRed: + return brightRedBackgroundColorAttr + case BrightGreen: + return brightGreenBackgroundColorAttr + case BrightYellow: + return brightYellowBackgroundColorAttr + case BrightBlue: + return brightBlueBackgroundColorAttr + case BrightMagenta: + return brightMagentaBackgroundColorAttr + case BrightCyan: + return brightCyanBackgroundColorAttr + case BrightWhite: + return brightWhiteBackgroundColorAttr + } + case ExtendedColor: + // 256-color ANSI foreground + // "48;5;" + return "48;5;" + strconv.FormatUint(uint64(c), 10) + case TrueColor, color.Color: + // 24-bit "true color" foreground + // "38;2;;;" + r, g, b, _ := c.RGBA() + return "48;2;" + + strconv.FormatUint(uint64(shift(r)), 10) + ";" + + strconv.FormatUint(uint64(shift(g)), 10) + ";" + + strconv.FormatUint(uint64(shift(b)), 10) + } + return defaultBackgroundColorAttr +} + +// underlineColorString returns the style SGR attribute for the given underline +// color. +// See: https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters +func underlineColorString(c Color) string { + switch c := c.(type) { + // NOTE: we can't use 3-bit and 4-bit ANSI color codes with underline + // color, use 256-color instead. + // + // 256-color ANSI underline color + // "58;5;" + case BasicColor: + return "58;5;" + strconv.FormatUint(uint64(c), 10) + case ExtendedColor: + return "58;5;" + strconv.FormatUint(uint64(c), 10) + case TrueColor, color.Color: + // 24-bit "true color" foreground + // "38;2;;;" + r, g, b, _ := c.RGBA() + return "58;2;" + + strconv.FormatUint(uint64(shift(r)), 10) + ";" + + strconv.FormatUint(uint64(shift(g)), 10) + ";" + + strconv.FormatUint(uint64(shift(b)), 10) + } + return defaultUnderlineColorAttr +} + +// ReadStyleColor decodes a color from a slice of parameters. It returns the +// number of parameters read and the color. This function is used to read SGR +// color parameters following the ITU T.416 standard. +// +// It supports reading the following color types: +// - 0: implementation defined +// - 1: transparent +// - 2: RGB direct color +// - 3: CMY direct color +// - 4: CMYK direct color +// - 5: indexed color +// - 6: RGBA direct color (WezTerm extension) +// +// The parameters can be separated by semicolons (;) or colons (:). Mixing +// separators is not allowed. +// +// The specs supports defining a color space id, a color tolerance value, and a +// tolerance color space id. However, these values have no effect on the +// returned color and will be ignored. +// +// This implementation includes a few modifications to the specs: +// 1. Support for legacy color values separated by semicolons (;) with respect to RGB, and indexed colors +// 2. Support ignoring and omitting the color space id (second parameter) with respect to RGB colors +// 3. Support ignoring and omitting the 6th parameter with respect to RGB and CMY colors +// 4. Support reading RGBA colors +func ReadStyleColor(params Params, co *color.Color) (n int) { + if len(params) < 2 { // Need at least SGR type and color type + return 0 + } + + // First parameter indicates one of 38, 48, or 58 (foreground, background, or underline) + s := params[0] + p := params[1] + colorType := p.Param(0) + n = 2 + + paramsfn := func() (p1, p2, p3, p4 int) { + // Where should we start reading the color? + switch { + 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(): + // We have color space id, a 6th parameter, a tolerance value, and a tolerance color space + n += 7 + return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0) + case s.HasMore() && p.HasMore() && len(params) > 7 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && params[5].HasMore() && params[6].HasMore(): + // We have color space id, a 6th parameter, and a tolerance value + n += 6 + return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0) + case s.HasMore() && p.HasMore() && len(params) > 6 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && params[5].HasMore(): + // We have color space id and a 6th parameter + // 48 : 4 : : 1 : 2 : 3 :4 + n += 5 + return params[3].Param(0), params[4].Param(0), params[5].Param(0), params[6].Param(0) + case s.HasMore() && p.HasMore() && len(params) > 5 && params[2].HasMore() && params[3].HasMore() && params[4].HasMore() && !params[5].HasMore(): + // We have color space + // 48 : 3 : : 1 : 2 : 3 + n += 4 + return params[3].Param(0), params[4].Param(0), params[5].Param(0), -1 + case s.HasMore() && p.HasMore() && p.Param(0) == 2 && params[2].HasMore() && params[3].HasMore() && !params[4].HasMore(): + // We have color values separated by colons (:) + // 48 : 2 : 1 : 2 : 3 + fallthrough + case !s.HasMore() && !p.HasMore() && p.Param(0) == 2 && !params[2].HasMore() && !params[3].HasMore() && !params[4].HasMore(): + // Support legacy color values separated by semicolons (;) + // 48 ; 2 ; 1 ; 2 ; 3 + n += 3 + return params[2].Param(0), params[3].Param(0), params[4].Param(0), -1 + } + // Ambiguous SGR color + return -1, -1, -1, -1 + } + + switch colorType { + case 0: // implementation defined + return 2 + case 1: // transparent + *co = color.Transparent + return 2 + case 2: // RGB direct color + if len(params) < 5 { + return 0 + } + + r, g, b, _ := paramsfn() + if r == -1 || g == -1 || b == -1 { + return 0 + } + + *co = color.RGBA{ + R: uint8(r), //nolint:gosec + G: uint8(g), //nolint:gosec + B: uint8(b), //nolint:gosec + A: 0xff, + } + return + + case 3: // CMY direct color + if len(params) < 5 { + return 0 + } + + c, m, y, _ := paramsfn() + if c == -1 || m == -1 || y == -1 { + return 0 + } + + *co = color.CMYK{ + C: uint8(c), //nolint:gosec + M: uint8(m), //nolint:gosec + Y: uint8(y), //nolint:gosec + K: 0, + } + return + + case 4: // CMYK direct color + if len(params) < 6 { + return 0 + } + + c, m, y, k := paramsfn() + if c == -1 || m == -1 || y == -1 || k == -1 { + return 0 + } + + *co = color.CMYK{ + C: uint8(c), //nolint:gosec + M: uint8(m), //nolint:gosec + Y: uint8(y), //nolint:gosec + K: uint8(k), //nolint:gosec + } + return + + case 5: // indexed color + if len(params) < 3 { + return 0 + } + switch { + case s.HasMore() && p.HasMore() && !params[2].HasMore(): + // Colon separated indexed color + // 38 : 5 : 234 + case !s.HasMore() && !p.HasMore() && !params[2].HasMore(): + // Legacy semicolon indexed color + // 38 ; 5 ; 234 + default: + return 0 + } + *co = ExtendedColor(params[2].Param(0)) //nolint:gosec + return 3 + + case 6: // RGBA direct color + if len(params) < 6 { + return 0 + } + + r, g, b, a := paramsfn() + if r == -1 || g == -1 || b == -1 || a == -1 { + return 0 + } + + *co = color.RGBA{ + R: uint8(r), //nolint:gosec + G: uint8(g), //nolint:gosec + B: uint8(b), //nolint:gosec + A: uint8(a), //nolint:gosec + } + return + + default: + return 0 + } +} diff --git a/vendor/github.com/charmbracelet/x/ansi/termcap.go b/vendor/github.com/charmbracelet/x/ansi/termcap.go new file mode 100644 index 00000000..3c5c7da9 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/termcap.go @@ -0,0 +1,41 @@ +package ansi + +import ( + "encoding/hex" + "strings" +) + +// RequestTermcap (XTGETTCAP) requests Termcap/Terminfo strings. +// +// DCS + q ST +// +// Where is a list of Termcap/Terminfo capabilities, encoded in 2-digit +// hexadecimals, separated by semicolons. +// +// See: https://man7.org/linux/man-pages/man5/terminfo.5.html +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands +func XTGETTCAP(caps ...string) string { + if len(caps) == 0 { + return "" + } + + s := "\x1bP+q" + for i, c := range caps { + if i > 0 { + s += ";" + } + s += strings.ToUpper(hex.EncodeToString([]byte(c))) + } + + return s + "\x1b\\" +} + +// RequestTermcap is an alias for [XTGETTCAP]. +func RequestTermcap(caps ...string) string { + return XTGETTCAP(caps...) +} + +// RequestTerminfo is an alias for [XTGETTCAP]. +func RequestTerminfo(caps ...string) string { + return XTGETTCAP(caps...) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/title.go b/vendor/github.com/charmbracelet/x/ansi/title.go new file mode 100644 index 00000000..54ef9423 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/title.go @@ -0,0 +1,48 @@ +package ansi + +// SetIconNameWindowTitle returns a sequence for setting the icon name and +// window title. +// +// OSC 0 ; title ST +// OSC 0 ; title BEL +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands +func SetIconNameWindowTitle(s string) string { + return "\x1b]0;" + s + "\x07" +} + +// SetIconName returns a sequence for setting the icon name. +// +// OSC 1 ; title ST +// OSC 1 ; title BEL +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands +func SetIconName(s string) string { + return "\x1b]1;" + s + "\x07" +} + +// SetWindowTitle returns a sequence for setting the window title. +// +// OSC 2 ; title ST +// OSC 2 ; title BEL +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h2-Operating-System-Commands +func SetWindowTitle(s string) string { + return "\x1b]2;" + s + "\x07" +} + +// DECSWT is a sequence for setting the window title. +// +// This is an alias for [SetWindowTitle]("1;"). +// See: EK-VT520-RM 5–156 https://vt100.net/dec/ek-vt520-rm.pdf +func DECSWT(name string) string { + return SetWindowTitle("1;" + name) +} + +// DECSIN is a sequence for setting the icon name. +// +// This is an alias for [SetWindowTitle]("L;"). +// See: EK-VT520-RM 5–134 https://vt100.net/dec/ek-vt520-rm.pdf +func DECSIN(name string) string { + return SetWindowTitle("L;" + name) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/truncate.go b/vendor/github.com/charmbracelet/x/ansi/truncate.go new file mode 100644 index 00000000..3f541fa5 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/truncate.go @@ -0,0 +1,299 @@ +package ansi + +import ( + "bytes" + + "github.com/charmbracelet/x/ansi/parser" + "github.com/mattn/go-runewidth" + "github.com/rivo/uniseg" +) + +// Cut the string, without adding any prefix or tail strings. This function is +// aware of ANSI escape codes and will not break them, and accounts for +// wide-characters (such as East-Asian characters and emojis). +// This treats the text as a sequence of graphemes. +func Cut(s string, left, right int) string { + return cut(GraphemeWidth, s, left, right) +} + +// CutWc the string, without adding any prefix or tail strings. This function is +// aware of ANSI escape codes and will not break them, and accounts for +// wide-characters (such as East-Asian characters and emojis). +// Note that the [left] parameter is inclusive, while [right] isn't, +// which is to say it'll return `[left, right)`. +// +// This treats the text as a sequence of wide characters and runes. +func CutWc(s string, left, right int) string { + return cut(WcWidth, s, left, right) +} + +func cut(m Method, s string, left, right int) string { + if right <= left { + return "" + } + + truncate := Truncate + truncateLeft := TruncateLeft + if m == WcWidth { + truncate = TruncateWc + truncateLeft = TruncateWc + } + + if left == 0 { + return truncate(s, right, "") + } + return truncateLeft(truncate(s, right, ""), left, "") +} + +// Truncate truncates a string to a given length, adding a tail to the end if +// the string is longer than the given length. This function is aware of ANSI +// escape codes and will not break them, and accounts for wide-characters (such +// as East-Asian characters and emojis). +// This treats the text as a sequence of graphemes. +func Truncate(s string, length int, tail string) string { + return truncate(GraphemeWidth, s, length, tail) +} + +// TruncateWc truncates a string to a given length, adding a tail to the end if +// the string is longer than the given length. This function is aware of ANSI +// escape codes and will not break them, and accounts for wide-characters (such +// as East-Asian characters and emojis). +// This treats the text as a sequence of wide characters and runes. +func TruncateWc(s string, length int, tail string) string { + return truncate(WcWidth, s, length, tail) +} + +func truncate(m Method, s string, length int, tail string) string { + if sw := StringWidth(s); sw <= length { + return s + } + + tw := StringWidth(tail) + length -= tw + if length < 0 { + return "" + } + + var cluster []byte + var buf bytes.Buffer + curWidth := 0 + ignoring := false + pstate := parser.GroundState // initial state + b := []byte(s) + i := 0 + + // Here we iterate over the bytes of the string and collect printable + // characters and runes. We also keep track of the width of the string + // in cells. + // + // Once we reach the given length, we start ignoring characters and only + // collect ANSI escape codes until we reach the end of string. + for i < len(b) { + state, action := parser.Table.Transition(pstate, b[i]) + if state == parser.Utf8State { + // This action happens when we transition to the Utf8State. + var width int + cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1) + if m == WcWidth { + width = runewidth.StringWidth(string(cluster)) + } + + // increment the index by the length of the cluster + i += len(cluster) + curWidth += width + + // Are we ignoring? Skip to the next byte + if ignoring { + continue + } + + // Is this gonna be too wide? + // If so write the tail and stop collecting. + if curWidth > length && !ignoring { + ignoring = true + buf.WriteString(tail) + } + + if curWidth > length { + continue + } + + buf.Write(cluster) + + // Done collecting, now we're back in the ground state. + pstate = parser.GroundState + continue + } + + switch action { + case parser.PrintAction: + // Is this gonna be too wide? + // If so write the tail and stop collecting. + if curWidth >= length && !ignoring { + ignoring = true + buf.WriteString(tail) + } + + // Skip to the next byte if we're ignoring + if ignoring { + i++ + continue + } + + // collects printable ASCII + curWidth++ + fallthrough + case parser.ExecuteAction: + // execute action will be things like \n, which, if outside the cut, + // should be ignored. + if ignoring { + i++ + continue + } + fallthrough + default: + buf.WriteByte(b[i]) + i++ + } + + // Transition to the next state. + pstate = state + + // Once we reach the given length, we start ignoring runes and write + // the tail to the buffer. + if curWidth > length && !ignoring { + ignoring = true + buf.WriteString(tail) + } + } + + return buf.String() +} + +// TruncateLeft truncates a string from the left side by removing n characters, +// adding a prefix to the beginning if the string is longer than n. +// This function is aware of ANSI escape codes and will not break them, and +// accounts for wide-characters (such as East-Asian characters and emojis). +// This treats the text as a sequence of graphemes. +func TruncateLeft(s string, n int, prefix string) string { + return truncateLeft(GraphemeWidth, s, n, prefix) +} + +// TruncateLeftWc truncates a string from the left side by removing n characters, +// adding a prefix to the beginning if the string is longer than n. +// This function is aware of ANSI escape codes and will not break them, and +// accounts for wide-characters (such as East-Asian characters and emojis). +// This treats the text as a sequence of wide characters and runes. +func TruncateLeftWc(s string, n int, prefix string) string { + return truncateLeft(WcWidth, s, n, prefix) +} + +func truncateLeft(m Method, s string, n int, prefix string) string { + if n <= 0 { + return s + } + + var cluster []byte + var buf bytes.Buffer + curWidth := 0 + ignoring := true + pstate := parser.GroundState + b := []byte(s) + i := 0 + + for i < len(b) { + if !ignoring { + buf.Write(b[i:]) + break + } + + state, action := parser.Table.Transition(pstate, b[i]) + if state == parser.Utf8State { + var width int + cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1) + if m == WcWidth { + width = runewidth.StringWidth(string(cluster)) + } + + i += len(cluster) + curWidth += width + + if curWidth > n && ignoring { + ignoring = false + buf.WriteString(prefix) + } + + if curWidth > n { + buf.Write(cluster) + } + + if ignoring { + continue + } + + pstate = parser.GroundState + continue + } + + switch action { + case parser.PrintAction: + curWidth++ + + if curWidth > n && ignoring { + ignoring = false + buf.WriteString(prefix) + } + + if ignoring { + i++ + continue + } + + fallthrough + case parser.ExecuteAction: + // execute action will be things like \n, which, if outside the cut, + // should be ignored. + if ignoring { + i++ + continue + } + fallthrough + default: + buf.WriteByte(b[i]) + i++ + } + + pstate = state + if curWidth > n && ignoring { + ignoring = false + buf.WriteString(prefix) + } + } + + return buf.String() +} + +// ByteToGraphemeRange takes start and stop byte positions and converts them to +// grapheme-aware char positions. +// You can use this with [Truncate], [TruncateLeft], and [Cut]. +func ByteToGraphemeRange(str string, byteStart, byteStop int) (charStart, charStop int) { + bytePos, charPos := 0, 0 + gr := uniseg.NewGraphemes(str) + for byteStart > bytePos { + if !gr.Next() { + break + } + bytePos += len(gr.Str()) + charPos += max(1, gr.Width()) + } + charStart = charPos + for byteStop > bytePos { + if !gr.Next() { + break + } + bytePos += len(gr.Str()) + charPos += max(1, gr.Width()) + } + charStop = charPos + return +} diff --git a/vendor/github.com/charmbracelet/x/ansi/util.go b/vendor/github.com/charmbracelet/x/ansi/util.go new file mode 100644 index 00000000..0f5cea78 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/util.go @@ -0,0 +1,106 @@ +package ansi + +import ( + "fmt" + "image/color" + "strconv" + "strings" + + "github.com/lucasb-eyer/go-colorful" +) + +// colorToHexString returns a hex string representation of a color. +func colorToHexString(c color.Color) string { //nolint:unused + if c == nil { + return "" + } + shift := func(v uint32) uint32 { + if v > 0xff { + return v >> 8 + } + return v + } + r, g, b, _ := c.RGBA() + r, g, b = shift(r), shift(g), shift(b) + return fmt.Sprintf("#%02x%02x%02x", r, g, b) +} + +// rgbToHex converts red, green, and blue values to a hexadecimal value. +// +// hex := rgbToHex(0, 0, 255) // 0x0000FF +func rgbToHex(r, g, b uint32) uint32 { //nolint:unused + return r<<16 + g<<8 + b +} + +type shiftable interface { + ~uint | ~uint16 | ~uint32 | ~uint64 +} + +func shift[T shiftable](x T) T { + if x > 0xff { + x >>= 8 + } + return x +} + +// XParseColor is a helper function that parses a string into a color.Color. It +// provides a similar interface to the XParseColor function in Xlib. It +// supports the following formats: +// +// - #RGB +// - #RRGGBB +// - rgb:RRRR/GGGG/BBBB +// - rgba:RRRR/GGGG/BBBB/AAAA +// +// If the string is not a valid color, nil is returned. +// +// See: https://linux.die.net/man/3/xparsecolor +func XParseColor(s string) color.Color { + switch { + case strings.HasPrefix(s, "#"): + c, err := colorful.Hex(s) + if err != nil { + return nil + } + + return c + case strings.HasPrefix(s, "rgb:"): + parts := strings.Split(s[4:], "/") + if len(parts) != 3 { + return nil + } + + r, _ := strconv.ParseUint(parts[0], 16, 32) + g, _ := strconv.ParseUint(parts[1], 16, 32) + b, _ := strconv.ParseUint(parts[2], 16, 32) + + return color.RGBA{uint8(shift(r)), uint8(shift(g)), uint8(shift(b)), 255} //nolint:gosec + case strings.HasPrefix(s, "rgba:"): + parts := strings.Split(s[5:], "/") + if len(parts) != 4 { + return nil + } + + r, _ := strconv.ParseUint(parts[0], 16, 32) + g, _ := strconv.ParseUint(parts[1], 16, 32) + b, _ := strconv.ParseUint(parts[2], 16, 32) + a, _ := strconv.ParseUint(parts[3], 16, 32) + + return color.RGBA{uint8(shift(r)), uint8(shift(g)), uint8(shift(b)), uint8(shift(a))} //nolint:gosec + } + return nil +} + +type ordered interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | + ~float32 | ~float64 | + ~string +} + +func max[T ordered](a, b T) T { //nolint:predeclared + if a > b { + return a + } + return b +} diff --git a/vendor/github.com/charmbracelet/x/ansi/width.go b/vendor/github.com/charmbracelet/x/ansi/width.go new file mode 100644 index 00000000..cc085816 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/width.go @@ -0,0 +1,113 @@ +package ansi + +import ( + "bytes" + + "github.com/charmbracelet/x/ansi/parser" + "github.com/mattn/go-runewidth" + "github.com/rivo/uniseg" +) + +// Strip removes ANSI escape codes from a string. +func Strip(s string) string { + var ( + buf bytes.Buffer // buffer for collecting printable characters + ri int // rune index + rw int // rune width + pstate = parser.GroundState // initial state + ) + + // This implements a subset of the Parser to only collect runes and + // printable characters. + for i := range len(s) { + if pstate == parser.Utf8State { + // During this state, collect rw bytes to form a valid rune in the + // buffer. After getting all the rune bytes into the buffer, + // transition to GroundState and reset the counters. + buf.WriteByte(s[i]) + ri++ + if ri < rw { + continue + } + pstate = parser.GroundState + ri = 0 + rw = 0 + continue + } + + state, action := parser.Table.Transition(pstate, s[i]) + switch action { + case parser.CollectAction: + if state == parser.Utf8State { + // This action happens when we transition to the Utf8State. + rw = utf8ByteLen(s[i]) + buf.WriteByte(s[i]) + ri++ + } + case parser.PrintAction, parser.ExecuteAction: + // collects printable ASCII and non-printable characters + buf.WriteByte(s[i]) + } + + // Transition to the next state. + // The Utf8State is managed separately above. + if pstate != parser.Utf8State { + pstate = state + } + } + + return buf.String() +} + +// StringWidth returns the width of a string in cells. This is the number of +// cells that the string will occupy when printed in a terminal. ANSI escape +// codes are ignored and wide characters (such as East Asians and emojis) are +// accounted for. +// This treats the text as a sequence of grapheme clusters. +func StringWidth(s string) int { + return stringWidth(GraphemeWidth, s) +} + +// StringWidthWc returns the width of a string in cells. This is the number of +// cells that the string will occupy when printed in a terminal. ANSI escape +// codes are ignored and wide characters (such as East Asians and emojis) are +// accounted for. +// This treats the text as a sequence of wide characters and runes. +func StringWidthWc(s string) int { + return stringWidth(WcWidth, s) +} + +func stringWidth(m Method, s string) int { + if s == "" { + return 0 + } + + var ( + pstate = parser.GroundState // initial state + cluster string + width int + ) + + for i := 0; i < len(s); i++ { + state, action := parser.Table.Transition(pstate, s[i]) + if state == parser.Utf8State { + var w int + cluster, _, w, _ = uniseg.FirstGraphemeClusterInString(s[i:], -1) + if m == WcWidth { + w = runewidth.StringWidth(cluster) + } + width += w + i += len(cluster) - 1 + pstate = parser.GroundState + continue + } + + if action == parser.PrintAction { + width++ + } + + pstate = state + } + + return width +} diff --git a/vendor/github.com/charmbracelet/x/ansi/winop.go b/vendor/github.com/charmbracelet/x/ansi/winop.go new file mode 100644 index 00000000..0238780d --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/winop.go @@ -0,0 +1,53 @@ +package ansi + +import ( + "strconv" + "strings" +) + +const ( + // ResizeWindowWinOp is a window operation that resizes the terminal + // window. + ResizeWindowWinOp = 4 + + // RequestWindowSizeWinOp is a window operation that requests a report of + // the size of the terminal window in pixels. The response is in the form: + // CSI 4 ; height ; width t + RequestWindowSizeWinOp = 14 + + // RequestCellSizeWinOp is a window operation that requests a report of + // the size of the terminal cell size in pixels. The response is in the form: + // CSI 6 ; height ; width t + RequestCellSizeWinOp = 16 +) + +// WindowOp (XTWINOPS) is a sequence that manipulates the terminal window. +// +// CSI Ps ; Ps ; Ps t +// +// Ps is a semicolon-separated list of parameters. +// See https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps;Ps;Ps-t.1EB0 +func WindowOp(p int, ps ...int) string { + if p <= 0 { + return "" + } + + if len(ps) == 0 { + return "\x1b[" + strconv.Itoa(p) + "t" + } + + params := make([]string, 0, len(ps)+1) + params = append(params, strconv.Itoa(p)) + for _, p := range ps { + if p >= 0 { + params = append(params, strconv.Itoa(p)) + } + } + + return "\x1b[" + strings.Join(params, ";") + "t" +} + +// XTWINOPS is an alias for [WindowOp]. +func XTWINOPS(p int, ps ...int) string { + return WindowOp(p, ps...) +} diff --git a/vendor/github.com/charmbracelet/x/ansi/wrap.go b/vendor/github.com/charmbracelet/x/ansi/wrap.go new file mode 100644 index 00000000..bfafac7c --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/wrap.go @@ -0,0 +1,474 @@ +package ansi + +import ( + "bytes" + "unicode" + "unicode/utf8" + + "github.com/charmbracelet/x/ansi/parser" + "github.com/mattn/go-runewidth" + "github.com/rivo/uniseg" +) + +// nbsp is a non-breaking space +const nbsp = 0xA0 + +// Hardwrap wraps a string or a block of text to a given line length, breaking +// word boundaries. This will preserve ANSI escape codes and will account for +// wide-characters in the string. +// When preserveSpace is true, spaces at the beginning of a line will be +// preserved. +// This treats the text as a sequence of graphemes. +func Hardwrap(s string, limit int, preserveSpace bool) string { + return hardwrap(GraphemeWidth, s, limit, preserveSpace) +} + +// HardwrapWc wraps a string or a block of text to a given line length, breaking +// word boundaries. This will preserve ANSI escape codes and will account for +// wide-characters in the string. +// When preserveSpace is true, spaces at the beginning of a line will be +// preserved. +// This treats the text as a sequence of wide characters and runes. +func HardwrapWc(s string, limit int, preserveSpace bool) string { + return hardwrap(WcWidth, s, limit, preserveSpace) +} + +func hardwrap(m Method, s string, limit int, preserveSpace bool) string { + if limit < 1 { + return s + } + + var ( + cluster []byte + buf bytes.Buffer + curWidth int + forceNewline bool + pstate = parser.GroundState // initial state + b = []byte(s) + ) + + addNewline := func() { + buf.WriteByte('\n') + curWidth = 0 + } + + i := 0 + for i < len(b) { + state, action := parser.Table.Transition(pstate, b[i]) + if state == parser.Utf8State { + var width int + cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1) + if m == WcWidth { + width = runewidth.StringWidth(string(cluster)) + } + i += len(cluster) + + if curWidth+width > limit { + addNewline() + } + if !preserveSpace && curWidth == 0 && len(cluster) <= 4 { + // Skip spaces at the beginning of a line + if r, _ := utf8.DecodeRune(cluster); r != utf8.RuneError && unicode.IsSpace(r) { + pstate = parser.GroundState + continue + } + } + + buf.Write(cluster) + curWidth += width + pstate = parser.GroundState + continue + } + + switch action { + case parser.PrintAction, parser.ExecuteAction: + if b[i] == '\n' { + addNewline() + forceNewline = false + break + } + + if curWidth+1 > limit { + addNewline() + forceNewline = true + } + + // Skip spaces at the beginning of a line + if curWidth == 0 { + if !preserveSpace && forceNewline && unicode.IsSpace(rune(b[i])) { + break + } + forceNewline = false + } + + buf.WriteByte(b[i]) + if action == parser.PrintAction { + curWidth++ + } + default: + buf.WriteByte(b[i]) + } + + // We manage the UTF8 state separately manually above. + if pstate != parser.Utf8State { + pstate = state + } + i++ + } + + return buf.String() +} + +// Wordwrap wraps a string or a block of text to a given line length, not +// breaking word boundaries. This will preserve ANSI escape codes and will +// account for wide-characters in the string. +// The breakpoints string is a list of characters that are considered +// breakpoints for word wrapping. A hyphen (-) is always considered a +// breakpoint. +// +// Note: breakpoints must be a string of 1-cell wide rune characters. +// +// This treats the text as a sequence of graphemes. +func Wordwrap(s string, limit int, breakpoints string) string { + return wordwrap(GraphemeWidth, s, limit, breakpoints) +} + +// WordwrapWc wraps a string or a block of text to a given line length, not +// breaking word boundaries. This will preserve ANSI escape codes and will +// account for wide-characters in the string. +// The breakpoints string is a list of characters that are considered +// breakpoints for word wrapping. A hyphen (-) is always considered a +// breakpoint. +// +// Note: breakpoints must be a string of 1-cell wide rune characters. +// +// This treats the text as a sequence of wide characters and runes. +func WordwrapWc(s string, limit int, breakpoints string) string { + return wordwrap(WcWidth, s, limit, breakpoints) +} + +func wordwrap(m Method, s string, limit int, breakpoints string) string { + if limit < 1 { + return s + } + + var ( + cluster []byte + buf bytes.Buffer + word bytes.Buffer + space bytes.Buffer + curWidth int + wordLen int + pstate = parser.GroundState // initial state + b = []byte(s) + ) + + addSpace := func() { + curWidth += space.Len() + buf.Write(space.Bytes()) + space.Reset() + } + + addWord := func() { + if word.Len() == 0 { + return + } + + addSpace() + curWidth += wordLen + buf.Write(word.Bytes()) + word.Reset() + wordLen = 0 + } + + addNewline := func() { + buf.WriteByte('\n') + curWidth = 0 + space.Reset() + } + + i := 0 + for i < len(b) { + state, action := parser.Table.Transition(pstate, b[i]) + if state == parser.Utf8State { + var width int + cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1) + if m == WcWidth { + width = runewidth.StringWidth(string(cluster)) + } + i += len(cluster) + + r, _ := utf8.DecodeRune(cluster) + if r != utf8.RuneError && unicode.IsSpace(r) && r != nbsp { + addWord() + space.WriteRune(r) + } else if bytes.ContainsAny(cluster, breakpoints) { + addSpace() + addWord() + buf.Write(cluster) + curWidth++ + } else { + word.Write(cluster) + wordLen += width + if curWidth+space.Len()+wordLen > limit && + wordLen < limit { + addNewline() + } + } + + pstate = parser.GroundState + continue + } + + switch action { + case parser.PrintAction, parser.ExecuteAction: + r := rune(b[i]) + switch { + case r == '\n': + if wordLen == 0 { + if curWidth+space.Len() > limit { + curWidth = 0 + } else { + buf.Write(space.Bytes()) + } + space.Reset() + } + + addWord() + addNewline() + case unicode.IsSpace(r): + addWord() + space.WriteByte(b[i]) + case r == '-': + fallthrough + case runeContainsAny(r, breakpoints): + addSpace() + addWord() + buf.WriteByte(b[i]) + curWidth++ + default: + word.WriteByte(b[i]) + wordLen++ + if curWidth+space.Len()+wordLen > limit && + wordLen < limit { + addNewline() + } + } + + default: + word.WriteByte(b[i]) + } + + // We manage the UTF8 state separately manually above. + if pstate != parser.Utf8State { + pstate = state + } + i++ + } + + addWord() + + return buf.String() +} + +// Wrap wraps a string or a block of text to a given line length, breaking word +// boundaries if necessary. This will preserve ANSI escape codes and will +// account for wide-characters in the string. The breakpoints string is a list +// of characters that are considered breakpoints for word wrapping. A hyphen +// (-) is always considered a breakpoint. +// +// Note: breakpoints must be a string of 1-cell wide rune characters. +// +// This treats the text as a sequence of graphemes. +func Wrap(s string, limit int, breakpoints string) string { + return wrap(GraphemeWidth, s, limit, breakpoints) +} + +// WrapWc wraps a string or a block of text to a given line length, breaking word +// boundaries if necessary. This will preserve ANSI escape codes and will +// account for wide-characters in the string. The breakpoints string is a list +// of characters that are considered breakpoints for word wrapping. A hyphen +// (-) is always considered a breakpoint. +// +// Note: breakpoints must be a string of 1-cell wide rune characters. +// +// This treats the text as a sequence of wide characters and runes. +func WrapWc(s string, limit int, breakpoints string) string { + return wrap(WcWidth, s, limit, breakpoints) +} + +func wrap(m Method, s string, limit int, breakpoints string) string { + if limit < 1 { + return s + } + + var ( + cluster []byte + buf bytes.Buffer + word bytes.Buffer + space bytes.Buffer + spaceWidth int // width of the space buffer + curWidth int // written width of the line + wordLen int // word buffer len without ANSI escape codes + pstate = parser.GroundState // initial state + b = []byte(s) + ) + + addSpace := func() { + curWidth += spaceWidth + buf.Write(space.Bytes()) + space.Reset() + spaceWidth = 0 + } + + addWord := func() { + if word.Len() == 0 { + return + } + + addSpace() + curWidth += wordLen + buf.Write(word.Bytes()) + word.Reset() + wordLen = 0 + } + + addNewline := func() { + buf.WriteByte('\n') + curWidth = 0 + space.Reset() + spaceWidth = 0 + } + + i := 0 + for i < len(b) { + state, action := parser.Table.Transition(pstate, b[i]) + if state == parser.Utf8State { + var width int + cluster, _, width, _ = uniseg.FirstGraphemeCluster(b[i:], -1) + if m == WcWidth { + width = runewidth.StringWidth(string(cluster)) + } + i += len(cluster) + + r, _ := utf8.DecodeRune(cluster) + switch { + case r != utf8.RuneError && unicode.IsSpace(r) && r != nbsp: // nbsp is a non-breaking space + addWord() + space.WriteRune(r) + spaceWidth += width + case bytes.ContainsAny(cluster, breakpoints): + addSpace() + if curWidth+wordLen+width > limit { + word.Write(cluster) + wordLen += width + } else { + addWord() + buf.Write(cluster) + curWidth += width + } + default: + if wordLen+width > limit { + // Hardwrap the word if it's too long + addWord() + } + + word.Write(cluster) + wordLen += width + + if curWidth+wordLen+spaceWidth > limit { + addNewline() + } + } + + pstate = parser.GroundState + continue + } + + switch action { + case parser.PrintAction, parser.ExecuteAction: + switch r := rune(b[i]); { + case r == '\n': + if wordLen == 0 { + if curWidth+spaceWidth > limit { + curWidth = 0 + } else { + // preserve whitespaces + buf.Write(space.Bytes()) + } + space.Reset() + spaceWidth = 0 + } + + addWord() + addNewline() + case unicode.IsSpace(r): + addWord() + space.WriteRune(r) + spaceWidth++ + case r == '-': + fallthrough + case runeContainsAny(r, breakpoints): + addSpace() + if curWidth+wordLen >= limit { + // We can't fit the breakpoint in the current line, treat + // it as part of the word. + word.WriteRune(r) + wordLen++ + } else { + addWord() + buf.WriteRune(r) + curWidth++ + } + default: + if curWidth == limit { + addNewline() + } + word.WriteRune(r) + wordLen++ + + if wordLen == limit { + // Hardwrap the word if it's too long + addWord() + } + + if curWidth+wordLen+spaceWidth > limit { + addNewline() + } + } + + default: + word.WriteByte(b[i]) + } + + // We manage the UTF8 state separately manually above. + if pstate != parser.Utf8State { + pstate = state + } + i++ + } + + if wordLen == 0 { + if curWidth+spaceWidth > limit { + curWidth = 0 + } else { + // preserve whitespaces + buf.Write(space.Bytes()) + } + space.Reset() + spaceWidth = 0 + } + + addWord() + + return buf.String() +} + +func runeContainsAny(r rune, s string) bool { + for _, c := range s { + if c == r { + return true + } + } + return false +} diff --git a/vendor/github.com/charmbracelet/x/ansi/xterm.go b/vendor/github.com/charmbracelet/x/ansi/xterm.go new file mode 100644 index 00000000..83fd4bdc --- /dev/null +++ b/vendor/github.com/charmbracelet/x/ansi/xterm.go @@ -0,0 +1,138 @@ +package ansi + +import "strconv" + +// KeyModifierOptions (XTMODKEYS) sets/resets xterm key modifier options. +// +// Default is 0. +// +// CSI > Pp m +// CSI > Pp ; Pv m +// +// If Pv is omitted, the resource is reset to its initial value. +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ +func KeyModifierOptions(p int, vs ...int) string { + var pp, pv string + if p > 0 { + pp = strconv.Itoa(p) + } + + if len(vs) == 0 { + return "\x1b[>" + strconv.Itoa(p) + "m" + } + + v := vs[0] + if v > 0 { + pv = strconv.Itoa(v) + return "\x1b[>" + pp + ";" + pv + "m" + } + + return "\x1b[>" + pp + "m" +} + +// XTMODKEYS is an alias for [KeyModifierOptions]. +func XTMODKEYS(p int, vs ...int) string { + return KeyModifierOptions(p, vs...) +} + +// SetKeyModifierOptions sets xterm key modifier options. +// This is an alias for [KeyModifierOptions]. +func SetKeyModifierOptions(pp int, pv int) string { + return KeyModifierOptions(pp, pv) +} + +// ResetKeyModifierOptions resets xterm key modifier options. +// This is an alias for [KeyModifierOptions]. +func ResetKeyModifierOptions(pp int) string { + return KeyModifierOptions(pp) +} + +// QueryKeyModifierOptions (XTQMODKEYS) requests xterm key modifier options. +// +// Default is 0. +// +// CSI ? Pp m +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ +func QueryKeyModifierOptions(pp int) string { + var p string + if pp > 0 { + p = strconv.Itoa(pp) + } + return "\x1b[?" + p + "m" +} + +// XTQMODKEYS is an alias for [QueryKeyModifierOptions]. +func XTQMODKEYS(pp int) string { + return QueryKeyModifierOptions(pp) +} + +// Modify Other Keys (modifyOtherKeys) is an xterm feature that allows the +// terminal to modify the behavior of certain keys to send different escape +// sequences when pressed. +// +// See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys +const ( + SetModifyOtherKeys1 = "\x1b[>4;1m" + SetModifyOtherKeys2 = "\x1b[>4;2m" + ResetModifyOtherKeys = "\x1b[>4m" + QueryModifyOtherKeys = "\x1b[?4m" +) + +// ModifyOtherKeys returns a sequence that sets XTerm modifyOtherKeys mode. +// The mode argument specifies the mode to set. +// +// 0: Disable modifyOtherKeys mode. +// 1: Enable modifyOtherKeys mode 1. +// 2: Enable modifyOtherKeys mode 2. +// +// CSI > 4 ; mode m +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ +// See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys +// +// Deprecated: use [SetModifyOtherKeys1] or [SetModifyOtherKeys2] instead. +func ModifyOtherKeys(mode int) string { + return "\x1b[>4;" + strconv.Itoa(mode) + "m" +} + +// DisableModifyOtherKeys disables the modifyOtherKeys mode. +// +// CSI > 4 ; 0 m +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ +// See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys +// +// Deprecated: use [ResetModifyOtherKeys] instead. +const DisableModifyOtherKeys = "\x1b[>4;0m" + +// EnableModifyOtherKeys1 enables the modifyOtherKeys mode 1. +// +// CSI > 4 ; 1 m +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ +// See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys +// +// Deprecated: use [SetModifyOtherKeys1] instead. +const EnableModifyOtherKeys1 = "\x1b[>4;1m" + +// EnableModifyOtherKeys2 enables the modifyOtherKeys mode 2. +// +// CSI > 4 ; 2 m +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ +// See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys +// +// Deprecated: use [SetModifyOtherKeys2] instead. +const EnableModifyOtherKeys2 = "\x1b[>4;2m" + +// RequestModifyOtherKeys requests the modifyOtherKeys mode. +// +// CSI ? 4 m +// +// See: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_ +// See: https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys +// +// Deprecated: use [QueryModifyOtherKeys] instead. +const RequestModifyOtherKeys = "\x1b[?4m" diff --git a/vendor/github.com/charmbracelet/x/cellbuf/LICENSE b/vendor/github.com/charmbracelet/x/cellbuf/LICENSE new file mode 100644 index 00000000..65a5654e --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Charmbracelet, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/charmbracelet/x/cellbuf/buffer.go b/vendor/github.com/charmbracelet/x/cellbuf/buffer.go new file mode 100644 index 00000000..790d1f7c --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/buffer.go @@ -0,0 +1,473 @@ +package cellbuf + +import ( + "strings" + + "github.com/mattn/go-runewidth" + "github.com/rivo/uniseg" +) + +// NewCell returns a new cell. This is a convenience function that initializes a +// new cell with the given content. The cell's width is determined by the +// content using [runewidth.RuneWidth]. +// This will only account for the first combined rune in the content. If the +// content is empty, it will return an empty cell with a width of 0. +func NewCell(r rune, comb ...rune) (c *Cell) { + c = new(Cell) + c.Rune = r + c.Width = runewidth.RuneWidth(r) + for _, r := range comb { + if runewidth.RuneWidth(r) > 0 { + break + } + c.Comb = append(c.Comb, r) + } + c.Comb = comb + c.Width = runewidth.StringWidth(string(append([]rune{r}, comb...))) + return +} + +// NewCellString returns a new cell with the given string content. This is a +// convenience function that initializes a new cell with the given content. The +// cell's width is determined by the content using [runewidth.StringWidth]. +// This will only use the first combined rune in the string. If the string is +// empty, it will return an empty cell with a width of 0. +func NewCellString(s string) (c *Cell) { + c = new(Cell) + for i, r := range s { + if i == 0 { + c.Rune = r + // We only care about the first rune's width + c.Width = runewidth.RuneWidth(r) + } else { + if runewidth.RuneWidth(r) > 0 { + break + } + c.Comb = append(c.Comb, r) + } + } + return +} + +// NewGraphemeCell returns a new cell. This is a convenience function that +// initializes a new cell with the given content. The cell's width is determined +// by the content using [uniseg.FirstGraphemeClusterInString]. +// This is used when the content is a grapheme cluster i.e. a sequence of runes +// that form a single visual unit. +// This will only return the first grapheme cluster in the string. If the +// string is empty, it will return an empty cell with a width of 0. +func NewGraphemeCell(s string) (c *Cell) { + g, _, w, _ := uniseg.FirstGraphemeClusterInString(s, -1) + return newGraphemeCell(g, w) +} + +func newGraphemeCell(s string, w int) (c *Cell) { + c = new(Cell) + c.Width = w + for i, r := range s { + if i == 0 { + c.Rune = r + } else { + c.Comb = append(c.Comb, r) + } + } + return +} + +// Line represents a line in the terminal. +// A nil cell represents an blank cell, a cell with a space character and a +// width of 1. +// If a cell has no content and a width of 0, it is a placeholder for a wide +// cell. +type Line []*Cell + +// Width returns the width of the line. +func (l Line) Width() int { + return len(l) +} + +// Len returns the length of the line. +func (l Line) Len() int { + return len(l) +} + +// String returns the string representation of the line. Any trailing spaces +// are removed. +func (l Line) String() (s string) { + for _, c := range l { + if c == nil { + s += " " + } else if c.Empty() { + continue + } else { + s += c.String() + } + } + s = strings.TrimRight(s, " ") + return +} + +// At returns the cell at the given x position. +// If the cell does not exist, it returns nil. +func (l Line) At(x int) *Cell { + if x < 0 || x >= len(l) { + return nil + } + + c := l[x] + if c == nil { + newCell := BlankCell + return &newCell + } + + return c +} + +// Set sets the cell at the given x position. If a wide cell is given, it will +// set the cell and the following cells to [EmptyCell]. It returns true if the +// cell was set. +func (l Line) Set(x int, c *Cell) bool { + return l.set(x, c, true) +} + +func (l Line) set(x int, c *Cell, clone bool) bool { + width := l.Width() + if x < 0 || x >= width { + return false + } + + // When a wide cell is partially overwritten, we need + // to fill the rest of the cell with space cells to + // avoid rendering issues. + prev := l.At(x) + if prev != nil && prev.Width > 1 { + // Writing to the first wide cell + for j := 0; j < prev.Width && x+j < l.Width(); j++ { + l[x+j] = prev.Clone().Blank() + } + } else if prev != nil && prev.Width == 0 { + // Writing to wide cell placeholders + for j := 1; j < maxCellWidth && x-j >= 0; j++ { + wide := l.At(x - j) + if wide != nil && wide.Width > 1 && j < wide.Width { + for k := 0; k < wide.Width; k++ { + l[x-j+k] = wide.Clone().Blank() + } + break + } + } + } + + if clone && c != nil { + // Clone the cell if not nil. + c = c.Clone() + } + + if c != nil && x+c.Width > width { + // If the cell is too wide, we write blanks with the same style. + for i := 0; i < c.Width && x+i < width; i++ { + l[x+i] = c.Clone().Blank() + } + } else { + l[x] = c + + // Mark wide cells with an empty cell zero width + // We set the wide cell down below + if c != nil && c.Width > 1 { + for j := 1; j < c.Width && x+j < l.Width(); j++ { + var wide Cell + l[x+j] = &wide + } + } + } + + return true +} + +// Buffer is a 2D grid of cells representing a screen or terminal. +type Buffer struct { + // Lines holds the lines of the buffer. + Lines []Line +} + +// NewBuffer creates a new buffer with the given width and height. +// This is a convenience function that initializes a new buffer and resizes it. +func NewBuffer(width int, height int) *Buffer { + b := new(Buffer) + b.Resize(width, height) + return b +} + +// String returns the string representation of the buffer. +func (b *Buffer) String() (s string) { + for i, l := range b.Lines { + s += l.String() + if i < len(b.Lines)-1 { + s += "\r\n" + } + } + return +} + +// Line returns a pointer to the line at the given y position. +// If the line does not exist, it returns nil. +func (b *Buffer) Line(y int) Line { + if y < 0 || y >= len(b.Lines) { + return nil + } + return b.Lines[y] +} + +// Cell implements Screen. +func (b *Buffer) Cell(x int, y int) *Cell { + if y < 0 || y >= len(b.Lines) { + return nil + } + return b.Lines[y].At(x) +} + +// maxCellWidth is the maximum width a terminal cell can get. +const maxCellWidth = 4 + +// SetCell sets the cell at the given x, y position. +func (b *Buffer) SetCell(x, y int, c *Cell) bool { + return b.setCell(x, y, c, true) +} + +// setCell sets the cell at the given x, y position. This will always clone and +// allocates a new cell if c is not nil. +func (b *Buffer) setCell(x, y int, c *Cell, clone bool) bool { + if y < 0 || y >= len(b.Lines) { + return false + } + return b.Lines[y].set(x, c, clone) +} + +// Height implements Screen. +func (b *Buffer) Height() int { + return len(b.Lines) +} + +// Width implements Screen. +func (b *Buffer) Width() int { + if len(b.Lines) == 0 { + return 0 + } + return b.Lines[0].Width() +} + +// Bounds returns the bounds of the buffer. +func (b *Buffer) Bounds() Rectangle { + return Rect(0, 0, b.Width(), b.Height()) +} + +// Resize resizes the buffer to the given width and height. +func (b *Buffer) Resize(width int, height int) { + if width == 0 || height == 0 { + b.Lines = nil + return + } + + if width > b.Width() { + line := make(Line, width-b.Width()) + for i := range b.Lines { + b.Lines[i] = append(b.Lines[i], line...) + } + } else if width < b.Width() { + for i := range b.Lines { + b.Lines[i] = b.Lines[i][:width] + } + } + + if height > len(b.Lines) { + for i := len(b.Lines); i < height; i++ { + b.Lines = append(b.Lines, make(Line, width)) + } + } else if height < len(b.Lines) { + b.Lines = b.Lines[:height] + } +} + +// FillRect fills the buffer with the given cell and rectangle. +func (b *Buffer) FillRect(c *Cell, rect Rectangle) { + cellWidth := 1 + if c != nil && c.Width > 1 { + cellWidth = c.Width + } + for y := rect.Min.Y; y < rect.Max.Y; y++ { + for x := rect.Min.X; x < rect.Max.X; x += cellWidth { + b.setCell(x, y, c, false) //nolint:errcheck + } + } +} + +// Fill fills the buffer with the given cell and rectangle. +func (b *Buffer) Fill(c *Cell) { + b.FillRect(c, b.Bounds()) +} + +// Clear clears the buffer with space cells and rectangle. +func (b *Buffer) Clear() { + b.ClearRect(b.Bounds()) +} + +// ClearRect clears the buffer with space cells within the specified +// rectangles. Only cells within the rectangle's bounds are affected. +func (b *Buffer) ClearRect(rect Rectangle) { + b.FillRect(nil, rect) +} + +// InsertLine inserts n lines at the given line position, with the given +// optional cell, within the specified rectangles. If no rectangles are +// specified, it inserts lines in the entire buffer. Only cells within the +// rectangle's horizontal bounds are affected. Lines are pushed out of the +// rectangle bounds and lost. This follows terminal [ansi.IL] behavior. +// It returns the pushed out lines. +func (b *Buffer) InsertLine(y, n int, c *Cell) { + b.InsertLineRect(y, n, c, b.Bounds()) +} + +// InsertLineRect inserts new lines at the given line position, with the +// given optional cell, within the rectangle bounds. Only cells within the +// rectangle's horizontal bounds are affected. Lines are pushed out of the +// rectangle bounds and lost. This follows terminal [ansi.IL] behavior. +func (b *Buffer) InsertLineRect(y, n int, c *Cell, rect Rectangle) { + if n <= 0 || y < rect.Min.Y || y >= rect.Max.Y || y >= b.Height() { + return + } + + // Limit number of lines to insert to available space + if y+n > rect.Max.Y { + n = rect.Max.Y - y + } + + // Move existing lines down within the bounds + for i := rect.Max.Y - 1; i >= y+n; i-- { + for x := rect.Min.X; x < rect.Max.X; x++ { + // We don't need to clone c here because we're just moving lines down. + b.setCell(x, i, b.Lines[i-n][x], false) + } + } + + // Clear the newly inserted lines within bounds + for i := y; i < y+n; i++ { + for x := rect.Min.X; x < rect.Max.X; x++ { + b.setCell(x, i, c, true) + } + } +} + +// DeleteLineRect deletes lines at the given line position, with the given +// optional cell, within the rectangle bounds. Only cells within the +// rectangle's bounds are affected. Lines are shifted up within the bounds and +// new blank lines are created at the bottom. This follows terminal [ansi.DL] +// behavior. +func (b *Buffer) DeleteLineRect(y, n int, c *Cell, rect Rectangle) { + if n <= 0 || y < rect.Min.Y || y >= rect.Max.Y || y >= b.Height() { + return + } + + // Limit deletion count to available space in scroll region + if n > rect.Max.Y-y { + n = rect.Max.Y - y + } + + // Shift cells up within the bounds + for dst := y; dst < rect.Max.Y-n; dst++ { + src := dst + n + for x := rect.Min.X; x < rect.Max.X; x++ { + // We don't need to clone c here because we're just moving cells up. + // b.lines[dst][x] = b.lines[src][x] + b.setCell(x, dst, b.Lines[src][x], false) + } + } + + // Fill the bottom n lines with blank cells + for i := rect.Max.Y - n; i < rect.Max.Y; i++ { + for x := rect.Min.X; x < rect.Max.X; x++ { + b.setCell(x, i, c, true) + } + } +} + +// DeleteLine deletes n lines at the given line position, with the given +// optional cell, within the specified rectangles. If no rectangles are +// specified, it deletes lines in the entire buffer. +func (b *Buffer) DeleteLine(y, n int, c *Cell) { + b.DeleteLineRect(y, n, c, b.Bounds()) +} + +// InsertCell inserts new cells at the given position, with the given optional +// cell, within the specified rectangles. If no rectangles are specified, it +// inserts cells in the entire buffer. This follows terminal [ansi.ICH] +// behavior. +func (b *Buffer) InsertCell(x, y, n int, c *Cell) { + b.InsertCellRect(x, y, n, c, b.Bounds()) +} + +// InsertCellRect inserts new cells at the given position, with the given +// optional cell, within the rectangle bounds. Only cells within the +// rectangle's bounds are affected, following terminal [ansi.ICH] behavior. +func (b *Buffer) InsertCellRect(x, y, n int, c *Cell, rect Rectangle) { + if n <= 0 || y < rect.Min.Y || y >= rect.Max.Y || y >= b.Height() || + x < rect.Min.X || x >= rect.Max.X || x >= b.Width() { + return + } + + // Limit number of cells to insert to available space + if x+n > rect.Max.X { + n = rect.Max.X - x + } + + // Move existing cells within rectangle bounds to the right + for i := rect.Max.X - 1; i >= x+n && i-n >= rect.Min.X; i-- { + // We don't need to clone c here because we're just moving cells to the + // right. + // b.lines[y][i] = b.lines[y][i-n] + b.setCell(i, y, b.Lines[y][i-n], false) + } + + // Clear the newly inserted cells within rectangle bounds + for i := x; i < x+n && i < rect.Max.X; i++ { + b.setCell(i, y, c, true) + } +} + +// DeleteCell deletes cells at the given position, with the given optional +// cell, within the specified rectangles. If no rectangles are specified, it +// deletes cells in the entire buffer. This follows terminal [ansi.DCH] +// behavior. +func (b *Buffer) DeleteCell(x, y, n int, c *Cell) { + b.DeleteCellRect(x, y, n, c, b.Bounds()) +} + +// DeleteCellRect deletes cells at the given position, with the given +// optional cell, within the rectangle bounds. Only cells within the +// rectangle's bounds are affected, following terminal [ansi.DCH] behavior. +func (b *Buffer) DeleteCellRect(x, y, n int, c *Cell, rect Rectangle) { + if n <= 0 || y < rect.Min.Y || y >= rect.Max.Y || y >= b.Height() || + x < rect.Min.X || x >= rect.Max.X || x >= b.Width() { + return + } + + // Calculate how many positions we can actually delete + remainingCells := rect.Max.X - x + if n > remainingCells { + n = remainingCells + } + + // Shift the remaining cells to the left + for i := x; i < rect.Max.X-n; i++ { + if i+n < rect.Max.X { + // We don't need to clone c here because we're just moving cells to + // the left. + // b.lines[y][i] = b.lines[y][i+n] + b.setCell(i, y, b.Lines[y][i+n], false) + } + } + + // Fill the vacated positions with the given cell + for i := rect.Max.X - n; i < rect.Max.X; i++ { + b.setCell(i, y, c, true) + } +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/cell.go b/vendor/github.com/charmbracelet/x/cellbuf/cell.go new file mode 100644 index 00000000..991c919e --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/cell.go @@ -0,0 +1,503 @@ +package cellbuf + +import ( + "github.com/charmbracelet/x/ansi" +) + +var ( + // BlankCell is a cell with a single space, width of 1, and no style or link. + BlankCell = Cell{Rune: ' ', Width: 1} + + // EmptyCell is just an empty cell used for comparisons and as a placeholder + // for wide cells. + EmptyCell = Cell{} +) + +// Cell represents a single cell in the terminal screen. +type Cell struct { + // The style of the cell. Nil style means no style. Zero value prints a + // reset sequence. + Style Style + + // Link is the hyperlink of the cell. + Link Link + + // Comb is the combining runes of the cell. This is nil if the cell is a + // single rune or if it's a zero width cell that is part of a wider cell. + Comb []rune + + // Width is the mono-space width of the grapheme cluster. + Width int + + // Rune is the main rune of the cell. This is zero if the cell is part of a + // wider cell. + Rune rune +} + +// Append appends runes to the cell without changing the width. This is useful +// when we want to use the cell to store escape sequences or other runes that +// don't affect the width of the cell. +func (c *Cell) Append(r ...rune) { + for i, r := range r { + if i == 0 && c.Rune == 0 { + c.Rune = r + continue + } + c.Comb = append(c.Comb, r) + } +} + +// String returns the string content of the cell excluding any styles, links, +// and escape sequences. +func (c Cell) String() string { + if c.Rune == 0 { + return "" + } + if len(c.Comb) == 0 { + return string(c.Rune) + } + return string(append([]rune{c.Rune}, c.Comb...)) +} + +// Equal returns whether the cell is equal to the other cell. +func (c *Cell) Equal(o *Cell) bool { + return o != nil && + c.Width == o.Width && + c.Rune == o.Rune && + runesEqual(c.Comb, o.Comb) && + c.Style.Equal(&o.Style) && + c.Link.Equal(&o.Link) +} + +// Empty returns whether the cell is an empty cell. An empty cell is a cell +// with a width of 0, a rune of 0, and no combining runes. +func (c Cell) Empty() bool { + return c.Width == 0 && + c.Rune == 0 && + len(c.Comb) == 0 +} + +// Reset resets the cell to the default state zero value. +func (c *Cell) Reset() { + c.Rune = 0 + c.Comb = nil + c.Width = 0 + c.Style.Reset() + c.Link.Reset() +} + +// Clear returns whether the cell consists of only attributes that don't +// affect appearance of a space character. +func (c *Cell) Clear() bool { + return c.Rune == ' ' && len(c.Comb) == 0 && c.Width == 1 && c.Style.Clear() && c.Link.Empty() +} + +// Clone returns a copy of the cell. +func (c *Cell) Clone() (n *Cell) { + n = new(Cell) + *n = *c + return +} + +// Blank makes the cell a blank cell by setting the rune to a space, comb to +// nil, and the width to 1. +func (c *Cell) Blank() *Cell { + c.Rune = ' ' + c.Comb = nil + c.Width = 1 + return c +} + +// Link represents a hyperlink in the terminal screen. +type Link struct { + URL string + Params string +} + +// String returns a string representation of the hyperlink. +func (h Link) String() string { + return h.URL +} + +// Reset resets the hyperlink to the default state zero value. +func (h *Link) Reset() { + h.URL = "" + h.Params = "" +} + +// Equal returns whether the hyperlink is equal to the other hyperlink. +func (h *Link) Equal(o *Link) bool { + return o != nil && h.URL == o.URL && h.Params == o.Params +} + +// Empty returns whether the hyperlink is empty. +func (h Link) Empty() bool { + return h.URL == "" && h.Params == "" +} + +// AttrMask is a bitmask for text attributes that can change the look of text. +// These attributes can be combined to create different styles. +type AttrMask uint8 + +// These are the available text attributes that can be combined to create +// different styles. +const ( + BoldAttr AttrMask = 1 << iota + FaintAttr + ItalicAttr + SlowBlinkAttr + RapidBlinkAttr + ReverseAttr + ConcealAttr + StrikethroughAttr + + ResetAttr AttrMask = 0 +) + +// UnderlineStyle is the style of underline to use for text. +type UnderlineStyle = ansi.UnderlineStyle + +// These are the available underline styles. +const ( + NoUnderline = ansi.NoUnderlineStyle + SingleUnderline = ansi.SingleUnderlineStyle + DoubleUnderline = ansi.DoubleUnderlineStyle + CurlyUnderline = ansi.CurlyUnderlineStyle + DottedUnderline = ansi.DottedUnderlineStyle + DashedUnderline = ansi.DashedUnderlineStyle +) + +// Style represents the Style of a cell. +type Style struct { + Fg ansi.Color + Bg ansi.Color + Ul ansi.Color + Attrs AttrMask + UlStyle UnderlineStyle +} + +// Sequence returns the ANSI sequence that sets the style. +func (s Style) Sequence() string { + if s.Empty() { + return ansi.ResetStyle + } + + var b ansi.Style + + if s.Attrs != 0 { + if s.Attrs&BoldAttr != 0 { + b = b.Bold() + } + if s.Attrs&FaintAttr != 0 { + b = b.Faint() + } + if s.Attrs&ItalicAttr != 0 { + b = b.Italic() + } + if s.Attrs&SlowBlinkAttr != 0 { + b = b.SlowBlink() + } + if s.Attrs&RapidBlinkAttr != 0 { + b = b.RapidBlink() + } + if s.Attrs&ReverseAttr != 0 { + b = b.Reverse() + } + if s.Attrs&ConcealAttr != 0 { + b = b.Conceal() + } + if s.Attrs&StrikethroughAttr != 0 { + b = b.Strikethrough() + } + } + if s.UlStyle != NoUnderline { + switch s.UlStyle { + case SingleUnderline: + b = b.Underline() + case DoubleUnderline: + b = b.DoubleUnderline() + case CurlyUnderline: + b = b.CurlyUnderline() + case DottedUnderline: + b = b.DottedUnderline() + case DashedUnderline: + b = b.DashedUnderline() + } + } + if s.Fg != nil { + b = b.ForegroundColor(s.Fg) + } + if s.Bg != nil { + b = b.BackgroundColor(s.Bg) + } + if s.Ul != nil { + b = b.UnderlineColor(s.Ul) + } + + return b.String() +} + +// DiffSequence returns the ANSI sequence that sets the style as a diff from +// another style. +func (s Style) DiffSequence(o Style) string { + if o.Empty() { + return s.Sequence() + } + + var b ansi.Style + + if !colorEqual(s.Fg, o.Fg) { + b = b.ForegroundColor(s.Fg) + } + + if !colorEqual(s.Bg, o.Bg) { + b = b.BackgroundColor(s.Bg) + } + + if !colorEqual(s.Ul, o.Ul) { + b = b.UnderlineColor(s.Ul) + } + + var ( + noBlink bool + isNormal bool + ) + + if s.Attrs != o.Attrs { + if s.Attrs&BoldAttr != o.Attrs&BoldAttr { + if s.Attrs&BoldAttr != 0 { + b = b.Bold() + } else if !isNormal { + isNormal = true + b = b.NormalIntensity() + } + } + if s.Attrs&FaintAttr != o.Attrs&FaintAttr { + if s.Attrs&FaintAttr != 0 { + b = b.Faint() + } else if !isNormal { + b = b.NormalIntensity() + } + } + if s.Attrs&ItalicAttr != o.Attrs&ItalicAttr { + if s.Attrs&ItalicAttr != 0 { + b = b.Italic() + } else { + b = b.NoItalic() + } + } + if s.Attrs&SlowBlinkAttr != o.Attrs&SlowBlinkAttr { + if s.Attrs&SlowBlinkAttr != 0 { + b = b.SlowBlink() + } else if !noBlink { + noBlink = true + b = b.NoBlink() + } + } + if s.Attrs&RapidBlinkAttr != o.Attrs&RapidBlinkAttr { + if s.Attrs&RapidBlinkAttr != 0 { + b = b.RapidBlink() + } else if !noBlink { + b = b.NoBlink() + } + } + if s.Attrs&ReverseAttr != o.Attrs&ReverseAttr { + if s.Attrs&ReverseAttr != 0 { + b = b.Reverse() + } else { + b = b.NoReverse() + } + } + if s.Attrs&ConcealAttr != o.Attrs&ConcealAttr { + if s.Attrs&ConcealAttr != 0 { + b = b.Conceal() + } else { + b = b.NoConceal() + } + } + if s.Attrs&StrikethroughAttr != o.Attrs&StrikethroughAttr { + if s.Attrs&StrikethroughAttr != 0 { + b = b.Strikethrough() + } else { + b = b.NoStrikethrough() + } + } + } + + if s.UlStyle != o.UlStyle { + b = b.UnderlineStyle(s.UlStyle) + } + + return b.String() +} + +// Equal returns true if the style is equal to the other style. +func (s *Style) Equal(o *Style) bool { + return s.Attrs == o.Attrs && + s.UlStyle == o.UlStyle && + colorEqual(s.Fg, o.Fg) && + colorEqual(s.Bg, o.Bg) && + colorEqual(s.Ul, o.Ul) +} + +func colorEqual(c, o ansi.Color) bool { + if c == nil && o == nil { + return true + } + if c == nil || o == nil { + return false + } + cr, cg, cb, ca := c.RGBA() + or, og, ob, oa := o.RGBA() + return cr == or && cg == og && cb == ob && ca == oa +} + +// Bold sets the bold attribute. +func (s *Style) Bold(v bool) *Style { + if v { + s.Attrs |= BoldAttr + } else { + s.Attrs &^= BoldAttr + } + return s +} + +// Faint sets the faint attribute. +func (s *Style) Faint(v bool) *Style { + if v { + s.Attrs |= FaintAttr + } else { + s.Attrs &^= FaintAttr + } + return s +} + +// Italic sets the italic attribute. +func (s *Style) Italic(v bool) *Style { + if v { + s.Attrs |= ItalicAttr + } else { + s.Attrs &^= ItalicAttr + } + return s +} + +// SlowBlink sets the slow blink attribute. +func (s *Style) SlowBlink(v bool) *Style { + if v { + s.Attrs |= SlowBlinkAttr + } else { + s.Attrs &^= SlowBlinkAttr + } + return s +} + +// RapidBlink sets the rapid blink attribute. +func (s *Style) RapidBlink(v bool) *Style { + if v { + s.Attrs |= RapidBlinkAttr + } else { + s.Attrs &^= RapidBlinkAttr + } + return s +} + +// Reverse sets the reverse attribute. +func (s *Style) Reverse(v bool) *Style { + if v { + s.Attrs |= ReverseAttr + } else { + s.Attrs &^= ReverseAttr + } + return s +} + +// Conceal sets the conceal attribute. +func (s *Style) Conceal(v bool) *Style { + if v { + s.Attrs |= ConcealAttr + } else { + s.Attrs &^= ConcealAttr + } + return s +} + +// Strikethrough sets the strikethrough attribute. +func (s *Style) Strikethrough(v bool) *Style { + if v { + s.Attrs |= StrikethroughAttr + } else { + s.Attrs &^= StrikethroughAttr + } + return s +} + +// UnderlineStyle sets the underline style. +func (s *Style) UnderlineStyle(style UnderlineStyle) *Style { + s.UlStyle = style + return s +} + +// Underline sets the underline attribute. +// This is a syntactic sugar for [UnderlineStyle]. +func (s *Style) Underline(v bool) *Style { + if v { + return s.UnderlineStyle(SingleUnderline) + } + return s.UnderlineStyle(NoUnderline) +} + +// Foreground sets the foreground color. +func (s *Style) Foreground(c ansi.Color) *Style { + s.Fg = c + return s +} + +// Background sets the background color. +func (s *Style) Background(c ansi.Color) *Style { + s.Bg = c + return s +} + +// UnderlineColor sets the underline color. +func (s *Style) UnderlineColor(c ansi.Color) *Style { + s.Ul = c + return s +} + +// Reset resets the style to default. +func (s *Style) Reset() *Style { + s.Fg = nil + s.Bg = nil + s.Ul = nil + s.Attrs = ResetAttr + s.UlStyle = NoUnderline + return s +} + +// Empty returns true if the style is empty. +func (s *Style) Empty() bool { + return s.Fg == nil && s.Bg == nil && s.Ul == nil && s.Attrs == ResetAttr && s.UlStyle == NoUnderline +} + +// Clear returns whether the style consists of only attributes that don't +// affect appearance of a space character. +func (s *Style) Clear() bool { + return s.UlStyle == NoUnderline && + s.Attrs&^(BoldAttr|FaintAttr|ItalicAttr|SlowBlinkAttr|RapidBlinkAttr) == 0 && + s.Fg == nil && + s.Bg == nil && + s.Ul == nil +} + +func runesEqual(a, b []rune) bool { + if len(a) != len(b) { + return false + } + for i, r := range a { + if r != b[i] { + return false + } + } + return true +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/errors.go b/vendor/github.com/charmbracelet/x/cellbuf/errors.go new file mode 100644 index 00000000..64258fe3 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/errors.go @@ -0,0 +1,6 @@ +package cellbuf + +import "errors" + +// ErrOutOfBounds is returned when the given x, y position is out of bounds. +var ErrOutOfBounds = errors.New("out of bounds") diff --git a/vendor/github.com/charmbracelet/x/cellbuf/geom.go b/vendor/github.com/charmbracelet/x/cellbuf/geom.go new file mode 100644 index 00000000..c12e6fb1 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/geom.go @@ -0,0 +1,21 @@ +package cellbuf + +import ( + "image" +) + +// Position represents an x, y position. +type Position = image.Point + +// Pos is a shorthand for Position{X: x, Y: y}. +func Pos(x, y int) Position { + return image.Pt(x, y) +} + +// Rectange represents a rectangle. +type Rectangle = image.Rectangle + +// Rect is a shorthand for Rectangle. +func Rect(x, y, w, h int) Rectangle { + return image.Rect(x, y, x+w, y+h) +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/hardscroll.go b/vendor/github.com/charmbracelet/x/cellbuf/hardscroll.go new file mode 100644 index 00000000..402ac06a --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/hardscroll.go @@ -0,0 +1,272 @@ +package cellbuf + +import ( + "strings" + + "github.com/charmbracelet/x/ansi" +) + +// scrollOptimize optimizes the screen to transform the old buffer into the new +// buffer. +func (s *Screen) scrollOptimize() { + height := s.newbuf.Height() + if s.oldnum == nil || len(s.oldnum) < height { + s.oldnum = make([]int, height) + } + + // Calculate the indices + s.updateHashmap() + if len(s.hashtab) < height { + return + } + + // Pass 1 - from top to bottom scrolling up + for i := 0; i < height; { + for i < height && (s.oldnum[i] == newIndex || s.oldnum[i] <= i) { + i++ + } + if i >= height { + break + } + + shift := s.oldnum[i] - i // shift > 0 + start := i + + i++ + for i < height && s.oldnum[i] != newIndex && s.oldnum[i]-i == shift { + i++ + } + end := i - 1 + shift + + if !s.scrolln(shift, start, end, height-1) { + continue + } + } + + // Pass 2 - from bottom to top scrolling down + for i := height - 1; i >= 0; { + for i >= 0 && (s.oldnum[i] == newIndex || s.oldnum[i] >= i) { + i-- + } + if i < 0 { + break + } + + shift := s.oldnum[i] - i // shift < 0 + end := i + + i-- + for i >= 0 && s.oldnum[i] != newIndex && s.oldnum[i]-i == shift { + i-- + } + + start := i + 1 - (-shift) + if !s.scrolln(shift, start, end, height-1) { + continue + } + } +} + +// scrolln scrolls the screen up by n lines. +func (s *Screen) scrolln(n, top, bot, maxY int) (v bool) { //nolint:unparam + const ( + nonDestScrollRegion = false + memoryBelow = false + ) + + blank := s.clearBlank() + if n > 0 { + // Scroll up (forward) + v = s.scrollUp(n, top, bot, 0, maxY, blank) + if !v { + s.buf.WriteString(ansi.SetTopBottomMargins(top+1, bot+1)) + + // XXX: How should we handle this in inline mode when not using alternate screen? + s.cur.X, s.cur.Y = -1, -1 + v = s.scrollUp(n, top, bot, top, bot, blank) + s.buf.WriteString(ansi.SetTopBottomMargins(1, maxY+1)) + s.cur.X, s.cur.Y = -1, -1 + } + + if !v { + v = s.scrollIdl(n, top, bot-n+1, blank) + } + + // Clear newly shifted-in lines. + if v && + (nonDestScrollRegion || (memoryBelow && bot == maxY)) { + if bot == maxY { + s.move(0, bot-n+1) + s.clearToBottom(nil) + } else { + for i := 0; i < n; i++ { + s.move(0, bot-i) + s.clearToEnd(nil, false) + } + } + } + } else if n < 0 { + // Scroll down (backward) + v = s.scrollDown(-n, top, bot, 0, maxY, blank) + if !v { + s.buf.WriteString(ansi.SetTopBottomMargins(top+1, bot+1)) + + // XXX: How should we handle this in inline mode when not using alternate screen? + s.cur.X, s.cur.Y = -1, -1 + v = s.scrollDown(-n, top, bot, top, bot, blank) + s.buf.WriteString(ansi.SetTopBottomMargins(1, maxY+1)) + s.cur.X, s.cur.Y = -1, -1 + + if !v { + v = s.scrollIdl(-n, bot+n+1, top, blank) + } + + // Clear newly shifted-in lines. + if v && + (nonDestScrollRegion || (memoryBelow && top == 0)) { + for i := 0; i < -n; i++ { + s.move(0, top+i) + s.clearToEnd(nil, false) + } + } + } + } + + if !v { + return + } + + s.scrollBuffer(s.curbuf, n, top, bot, blank) + + // shift hash values too, they can be reused + s.scrollOldhash(n, top, bot) + + return true +} + +// scrollBuffer scrolls the buffer by n lines. +func (s *Screen) scrollBuffer(b *Buffer, n, top, bot int, blank *Cell) { + if top < 0 || bot < top || bot >= b.Height() { + // Nothing to scroll + return + } + + if n < 0 { + // shift n lines downwards + limit := top - n + for line := bot; line >= limit && line >= 0 && line >= top; line-- { + copy(b.Lines[line], b.Lines[line+n]) + } + for line := top; line < limit && line <= b.Height()-1 && line <= bot; line++ { + b.FillRect(blank, Rect(0, line, b.Width(), 1)) + } + } + + if n > 0 { + // shift n lines upwards + limit := bot - n + for line := top; line <= limit && line <= b.Height()-1 && line <= bot; line++ { + copy(b.Lines[line], b.Lines[line+n]) + } + for line := bot; line > limit && line >= 0 && line >= top; line-- { + b.FillRect(blank, Rect(0, line, b.Width(), 1)) + } + } + + s.touchLine(b.Width(), b.Height(), top, bot-top+1, true) +} + +// touchLine marks the line as touched. +func (s *Screen) touchLine(width, height, y, n int, changed bool) { + if n < 0 || y < 0 || y >= height { + return // Nothing to touch + } + + for i := y; i < y+n && i < height; i++ { + if changed { + s.touch[i] = lineData{firstCell: 0, lastCell: width - 1} + } else { + delete(s.touch, i) + } + } +} + +// scrollUp scrolls the screen up by n lines. +func (s *Screen) scrollUp(n, top, bot, minY, maxY int, blank *Cell) bool { + if n == 1 && top == minY && bot == maxY { + s.move(0, bot) + s.updatePen(blank) + s.buf.WriteByte('\n') + } else if n == 1 && bot == maxY { + s.move(0, top) + s.updatePen(blank) + s.buf.WriteString(ansi.DeleteLine(1)) + } else if top == minY && bot == maxY { + if s.xtermLike { + s.move(0, bot) + } else { + s.move(0, top) + } + s.updatePen(blank) + if s.xtermLike { + s.buf.WriteString(ansi.ScrollUp(n)) + } else { + s.buf.WriteString(strings.Repeat("\n", n)) + } + } else if bot == maxY { + s.move(0, top) + s.updatePen(blank) + s.buf.WriteString(ansi.DeleteLine(n)) + } else { + return false + } + return true +} + +// scrollDown scrolls the screen down by n lines. +func (s *Screen) scrollDown(n, top, bot, minY, maxY int, blank *Cell) bool { + if n == 1 && top == minY && bot == maxY { + s.move(0, top) + s.updatePen(blank) + s.buf.WriteString(ansi.ReverseIndex) + } else if n == 1 && bot == maxY { + s.move(0, top) + s.updatePen(blank) + s.buf.WriteString(ansi.InsertLine(1)) + } else if top == minY && bot == maxY { + s.move(0, top) + s.updatePen(blank) + if s.xtermLike { + s.buf.WriteString(ansi.ScrollDown(n)) + } else { + s.buf.WriteString(strings.Repeat(ansi.ReverseIndex, n)) + } + } else if bot == maxY { + s.move(0, top) + s.updatePen(blank) + s.buf.WriteString(ansi.InsertLine(n)) + } else { + return false + } + return true +} + +// scrollIdl scrolls the screen n lines by using [ansi.DL] at del and using +// [ansi.IL] at ins. +func (s *Screen) scrollIdl(n, del, ins int, blank *Cell) bool { + if n < 0 { + return false + } + + // Delete lines + s.move(0, del) + s.updatePen(blank) + s.buf.WriteString(ansi.DeleteLine(n)) + + // Insert lines + s.move(0, ins) + s.updatePen(blank) + s.buf.WriteString(ansi.InsertLine(n)) + + return true +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/hashmap.go b/vendor/github.com/charmbracelet/x/cellbuf/hashmap.go new file mode 100644 index 00000000..0d25b549 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/hashmap.go @@ -0,0 +1,301 @@ +package cellbuf + +import ( + "github.com/charmbracelet/x/ansi" +) + +// hash returns the hash value of a [Line]. +func hash(l Line) (h uint64) { + for _, c := range l { + var r rune + if c == nil { + r = ansi.SP + } else { + r = c.Rune + } + h += (h << 5) + uint64(r) + } + return +} + +// hashmap represents a single [Line] hash. +type hashmap struct { + value uint64 + oldcount, newcount int + oldindex, newindex int +} + +// The value used to indicate lines created by insertions and scrolls. +const newIndex = -1 + +// updateHashmap updates the hashmap with the new hash value. +func (s *Screen) updateHashmap() { + height := s.newbuf.Height() + if len(s.oldhash) >= height && len(s.newhash) >= height { + // rehash changed lines + for i := 0; i < height; i++ { + _, ok := s.touch[i] + if ok { + s.oldhash[i] = hash(s.curbuf.Line(i)) + s.newhash[i] = hash(s.newbuf.Line(i)) + } + } + } else { + // rehash all + if len(s.oldhash) != height { + s.oldhash = make([]uint64, height) + } + if len(s.newhash) != height { + s.newhash = make([]uint64, height) + } + for i := 0; i < height; i++ { + s.oldhash[i] = hash(s.curbuf.Line(i)) + s.newhash[i] = hash(s.newbuf.Line(i)) + } + } + + s.hashtab = make([]hashmap, height*2) + for i := 0; i < height; i++ { + hashval := s.oldhash[i] + + // Find matching hash or empty slot + idx := 0 + for idx < len(s.hashtab) && s.hashtab[idx].value != 0 { + if s.hashtab[idx].value == hashval { + break + } + idx++ + } + + s.hashtab[idx].value = hashval // in case this is a new hash + s.hashtab[idx].oldcount++ + s.hashtab[idx].oldindex = i + } + for i := 0; i < height; i++ { + hashval := s.newhash[i] + + // Find matching hash or empty slot + idx := 0 + for idx < len(s.hashtab) && s.hashtab[idx].value != 0 { + if s.hashtab[idx].value == hashval { + break + } + idx++ + } + + s.hashtab[idx].value = hashval // in case this is a new hash + s.hashtab[idx].newcount++ + s.hashtab[idx].newindex = i + + s.oldnum[i] = newIndex // init old indices slice + } + + // Mark line pair corresponding to unique hash pairs. + for i := 0; i < len(s.hashtab) && s.hashtab[i].value != 0; i++ { + hsp := &s.hashtab[i] + if hsp.oldcount == 1 && hsp.newcount == 1 && hsp.oldindex != hsp.newindex { + s.oldnum[hsp.newindex] = hsp.oldindex + } + } + + s.growHunks() + + // Eliminate bad or impossible shifts. This includes removing those hunks + // which could not grow because of conflicts, as well those which are to be + // moved too far, they are likely to destroy more than carry. + for i := 0; i < height; { + var start, shift, size int + for i < height && s.oldnum[i] == newIndex { + i++ + } + if i >= height { + break + } + start = i + shift = s.oldnum[i] - i + i++ + for i < height && s.oldnum[i] != newIndex && s.oldnum[i]-i == shift { + i++ + } + size = i - start + if size < 3 || size+min(size/8, 2) < abs(shift) { + for start < i { + s.oldnum[start] = newIndex + start++ + } + } + } + + // After clearing invalid hunks, try grow the rest. + s.growHunks() +} + +// scrollOldhash +func (s *Screen) scrollOldhash(n, top, bot int) { + if len(s.oldhash) == 0 { + return + } + + size := bot - top + 1 - abs(n) + if n > 0 { + // Move existing hashes up + copy(s.oldhash[top:], s.oldhash[top+n:top+n+size]) + // Recalculate hashes for newly shifted-in lines + for i := bot; i > bot-n; i-- { + s.oldhash[i] = hash(s.curbuf.Line(i)) + } + } else { + // Move existing hashes down + copy(s.oldhash[top-n:], s.oldhash[top:top+size]) + // Recalculate hashes for newly shifted-in lines + for i := top; i < top-n; i++ { + s.oldhash[i] = hash(s.curbuf.Line(i)) + } + } +} + +func (s *Screen) growHunks() { + var ( + backLimit int // limits for cells to fill + backRefLimit int // limit for references + i int + nextHunk int + ) + + height := s.newbuf.Height() + for i < height && s.oldnum[i] == newIndex { + i++ + } + for ; i < height; i = nextHunk { + var ( + forwardLimit int + forwardRefLimit int + end int + start = i + shift = s.oldnum[i] - i + ) + + // get forward limit + i = start + 1 + for i < height && + s.oldnum[i] != newIndex && + s.oldnum[i]-i == shift { + i++ + } + + end = i + for i < height && s.oldnum[i] == newIndex { + i++ + } + + nextHunk = i + forwardLimit = i + if i >= height || s.oldnum[i] >= i { + forwardRefLimit = i + } else { + forwardRefLimit = s.oldnum[i] + } + + i = start - 1 + + // grow back + if shift < 0 { + backLimit = backRefLimit + (-shift) + } + for i >= backLimit { + if s.newhash[i] == s.oldhash[i+shift] || + s.costEffective(i+shift, i, shift < 0) { + s.oldnum[i] = i + shift + } else { + break + } + i-- + } + + i = end + // grow forward + if shift > 0 { + forwardLimit = forwardRefLimit - shift + } + for i < forwardLimit { + if s.newhash[i] == s.oldhash[i+shift] || + s.costEffective(i+shift, i, shift > 0) { + s.oldnum[i] = i + shift + } else { + break + } + i++ + } + + backLimit = i + backRefLimit = backLimit + if shift > 0 { + backRefLimit += shift + } + } +} + +// costEffective returns true if the cost of moving line 'from' to line 'to' seems to be +// cost effective. 'blank' indicates whether the line 'to' would become blank. +func (s *Screen) costEffective(from, to int, blank bool) bool { + if from == to { + return false + } + + newFrom := s.oldnum[from] + if newFrom == newIndex { + newFrom = from + } + + // On the left side of >= is the cost before moving. On the right side -- + // cost after moving. + + // Calculate costs before moving. + var costBeforeMove int + if blank { + // Cost of updating blank line at destination. + costBeforeMove = s.updateCostBlank(s.newbuf.Line(to)) + } else { + // Cost of updating exiting line at destination. + costBeforeMove = s.updateCost(s.curbuf.Line(to), s.newbuf.Line(to)) + } + + // Add cost of updating source line + costBeforeMove += s.updateCost(s.curbuf.Line(newFrom), s.newbuf.Line(from)) + + // Calculate costs after moving. + var costAfterMove int + if newFrom == from { + // Source becomes blank after move + costAfterMove = s.updateCostBlank(s.newbuf.Line(from)) + } else { + // Source gets updated from another line + costAfterMove = s.updateCost(s.curbuf.Line(newFrom), s.newbuf.Line(from)) + } + + // Add cost of moving source line to destination + costAfterMove += s.updateCost(s.curbuf.Line(from), s.newbuf.Line(to)) + + // Return true if moving is cost effective (costs less or equal) + return costBeforeMove >= costAfterMove +} + +func (s *Screen) updateCost(from, to Line) (cost int) { + var fidx, tidx int + for i := s.newbuf.Width() - 1; i > 0; i, fidx, tidx = i-1, fidx+1, tidx+1 { + if !cellEqual(from.At(fidx), to.At(tidx)) { + cost++ + } + } + return +} + +func (s *Screen) updateCostBlank(to Line) (cost int) { + var tidx int + for i := s.newbuf.Width() - 1; i > 0; i, tidx = i-1, tidx+1 { + if !cellEqual(nil, to.At(tidx)) { + cost++ + } + } + return +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/link.go b/vendor/github.com/charmbracelet/x/cellbuf/link.go new file mode 100644 index 00000000..112f8e8a --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/link.go @@ -0,0 +1,14 @@ +package cellbuf + +import ( + "github.com/charmbracelet/colorprofile" +) + +// Convert converts a hyperlink to respect the given color profile. +func ConvertLink(h Link, p colorprofile.Profile) Link { + if p == colorprofile.NoTTY { + return Link{} + } + + return h +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/screen.go b/vendor/github.com/charmbracelet/x/cellbuf/screen.go new file mode 100644 index 00000000..963b9cac --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/screen.go @@ -0,0 +1,1457 @@ +package cellbuf + +import ( + "bytes" + "errors" + "io" + "os" + "strings" + "sync" + + "github.com/charmbracelet/colorprofile" + "github.com/charmbracelet/x/ansi" + "github.com/charmbracelet/x/term" +) + +// ErrInvalidDimensions is returned when the dimensions of a window are invalid +// for the operation. +var ErrInvalidDimensions = errors.New("invalid dimensions") + +// notLocal returns whether the coordinates are not considered local movement +// using the defined thresholds. +// This takes the number of columns, and the coordinates of the current and +// target positions. +func notLocal(cols, fx, fy, tx, ty int) bool { + // The typical distance for a [ansi.CUP] sequence. Anything less than this + // is considered local movement. + const longDist = 8 - 1 + return (tx > longDist) && + (tx < cols-1-longDist) && + (abs(ty-fy)+abs(tx-fx) > longDist) +} + +// relativeCursorMove returns the relative cursor movement sequence using one or two +// of the following sequences [ansi.CUU], [ansi.CUD], [ansi.CUF], [ansi.CUB], +// [ansi.VPA], [ansi.HPA]. +// When overwrite is true, this will try to optimize the sequence by using the +// screen cells values to move the cursor instead of using escape sequences. +func relativeCursorMove(s *Screen, fx, fy, tx, ty int, overwrite, useTabs, useBackspace bool) string { + var seq strings.Builder + + width, height := s.newbuf.Width(), s.newbuf.Height() + if ty != fy { + var yseq string + if s.xtermLike && !s.opts.RelativeCursor { + yseq = ansi.VerticalPositionAbsolute(ty + 1) + } + + // OPTIM: Use [ansi.LF] and [ansi.ReverseIndex] as optimizations. + + if ty > fy { + n := ty - fy + if cud := ansi.CursorDown(n); yseq == "" || len(cud) < len(yseq) { + yseq = cud + } + shouldScroll := !s.opts.AltScreen && fy+n >= s.scrollHeight + if lf := strings.Repeat("\n", n); shouldScroll || (fy+n < height && len(lf) < len(yseq)) { + // TODO: Ensure we're not unintentionally scrolling the screen down. + yseq = lf + s.scrollHeight = max(s.scrollHeight, fy+n) + } + } else if ty < fy { + n := fy - ty + if cuu := ansi.CursorUp(n); yseq == "" || len(cuu) < len(yseq) { + yseq = cuu + } + if n == 1 && fy-1 > 0 { + // TODO: Ensure we're not unintentionally scrolling the screen up. + yseq = ansi.ReverseIndex + } + } + + seq.WriteString(yseq) + } + + if tx != fx { + var xseq string + if s.xtermLike && !s.opts.RelativeCursor { + xseq = ansi.HorizontalPositionAbsolute(tx + 1) + } + + if tx > fx { + n := tx - fx + if useTabs { + var tabs int + var col int + for col = fx; s.tabs.Next(col) <= tx; col = s.tabs.Next(col) { + tabs++ + if col == s.tabs.Next(col) || col >= width-1 { + break + } + } + + if tabs > 0 { + cht := ansi.CursorHorizontalForwardTab(tabs) + tab := strings.Repeat("\t", tabs) + if false && s.xtermLike && len(cht) < len(tab) { + // TODO: The linux console and some terminals such as + // Alacritty don't support [ansi.CHT]. Enable this when + // we have a way to detect this, or after 5 years when + // we're sure everyone has updated their terminals :P + seq.WriteString(cht) + } else { + seq.WriteString(tab) + } + + n = tx - col + fx = col + } + } + + if cuf := ansi.CursorForward(n); xseq == "" || len(cuf) < len(xseq) { + xseq = cuf + } + + // If we have no attribute and style changes, overwrite is cheaper. + var ovw string + if overwrite && ty >= 0 { + for i := 0; i < n; i++ { + cell := s.newbuf.Cell(fx+i, ty) + if cell != nil && cell.Width > 0 { + i += cell.Width - 1 + if !cell.Style.Equal(&s.cur.Style) || !cell.Link.Equal(&s.cur.Link) { + overwrite = false + break + } + } + } + } + + if overwrite && ty >= 0 { + for i := 0; i < n; i++ { + cell := s.newbuf.Cell(fx+i, ty) + if cell != nil && cell.Width > 0 { + ovw += cell.String() + i += cell.Width - 1 + } else { + ovw += " " + } + } + } + + if overwrite && len(ovw) < len(xseq) { + xseq = ovw + } + } else if tx < fx { + n := fx - tx + if useTabs && s.xtermLike { + // VT100 does not support backward tabs [ansi.CBT]. + + col := fx + + var cbt int // cursor backward tabs count + for s.tabs.Prev(col) >= tx { + col = s.tabs.Prev(col) + cbt++ + if col == s.tabs.Prev(col) || col <= 0 { + break + } + } + + if cbt > 0 { + seq.WriteString(ansi.CursorBackwardTab(cbt)) + n = col - tx + } + } + + if cub := ansi.CursorBackward(n); xseq == "" || len(cub) < len(xseq) { + xseq = cub + } + + if useBackspace && n < len(xseq) { + xseq = strings.Repeat("\b", n) + } + } + + seq.WriteString(xseq) + } + + return seq.String() +} + +// moveCursor moves and returns the cursor movement sequence to move the cursor +// to the specified position. +// When overwrite is true, this will try to optimize the sequence by using the +// screen cells values to move the cursor instead of using escape sequences. +func moveCursor(s *Screen, x, y int, overwrite bool) (seq string) { + fx, fy := s.cur.X, s.cur.Y + + if !s.opts.RelativeCursor { + // Method #0: Use [ansi.CUP] if the distance is long. + seq = ansi.CursorPosition(x+1, y+1) + if fx == -1 || fy == -1 || notLocal(s.newbuf.Width(), fx, fy, x, y) { + return + } + } + + // Optimize based on options. + trials := 0 + if s.opts.HardTabs { + trials |= 2 // 0b10 in binary + } + if s.opts.Backspace { + trials |= 1 // 0b01 in binary + } + + // Try all possible combinations of hard tabs and backspace optimizations. + for i := 0; i <= trials; i++ { + // Skip combinations that are not enabled. + if i & ^trials != 0 { + continue + } + + useHardTabs := i&2 != 0 + useBackspace := i&1 != 0 + + // Method #1: Use local movement sequences. + nseq := relativeCursorMove(s, fx, fy, x, y, overwrite, useHardTabs, useBackspace) + if (i == 0 && len(seq) == 0) || len(nseq) < len(seq) { + seq = nseq + } + + // Method #2: Use [ansi.CR] and local movement sequences. + nseq = "\r" + relativeCursorMove(s, 0, fy, x, y, overwrite, useHardTabs, useBackspace) + if len(nseq) < len(seq) { + seq = nseq + } + + if !s.opts.RelativeCursor { + // Method #3: Use [ansi.CursorHomePosition] and local movement sequences. + nseq = ansi.CursorHomePosition + relativeCursorMove(s, 0, 0, x, y, overwrite, useHardTabs, useBackspace) + if len(nseq) < len(seq) { + seq = nseq + } + } + } + + return +} + +// moveCursor moves the cursor to the specified position. +func (s *Screen) moveCursor(x, y int, overwrite bool) { + if !s.opts.AltScreen && s.cur.X == -1 && s.cur.Y == -1 { + // First cursor movement in inline mode, move the cursor to the first + // column before moving to the target position. + s.buf.WriteByte('\r') //nolint:errcheck + s.cur.X, s.cur.Y = 0, 0 + } + s.buf.WriteString(moveCursor(s, x, y, overwrite)) //nolint:errcheck + s.cur.X, s.cur.Y = x, y +} + +func (s *Screen) move(x, y int) { + // XXX: Make sure we use the max height and width of the buffer in case + // we're in the middle of a resize operation. + width := max(s.newbuf.Width(), s.curbuf.Width()) + height := max(s.newbuf.Height(), s.curbuf.Height()) + + if width > 0 && x >= width { + // Handle autowrap + y += (x / width) + x %= width + } + + // XXX: Disable styles if there's any + // Some move operations such as [ansi.LF] can apply styles to the new + // cursor position, thus, we need to reset the styles before moving the + // cursor. + blank := s.clearBlank() + resetPen := y != s.cur.Y && !blank.Equal(&BlankCell) + if resetPen { + s.updatePen(nil) + } + + // Reset wrap around (phantom cursor) state + if s.atPhantom { + s.cur.X = 0 + s.buf.WriteByte('\r') //nolint:errcheck + s.atPhantom = false // reset phantom cell state + } + + // TODO: Investigate if we need to handle this case and/or if we need the + // following code. + // + // if width > 0 && s.cur.X >= width { + // l := (s.cur.X + 1) / width + // + // s.cur.Y += l + // if height > 0 && s.cur.Y >= height { + // l -= s.cur.Y - height - 1 + // } + // + // if l > 0 { + // s.cur.X = 0 + // s.buf.WriteString("\r" + strings.Repeat("\n", l)) //nolint:errcheck + // } + // } + + if height > 0 { + if s.cur.Y > height-1 { + s.cur.Y = height - 1 + } + if y > height-1 { + y = height - 1 + } + } + + if x == s.cur.X && y == s.cur.Y { + // We give up later because we need to run checks for the phantom cell + // and others before we can determine if we can give up. + return + } + + // We set the new cursor in [Screen.moveCursor]. + s.moveCursor(x, y, true) // Overwrite cells if possible +} + +// Cursor represents a terminal Cursor. +type Cursor struct { + Style + Link + Position +} + +// ScreenOptions are options for the screen. +type ScreenOptions struct { + // Term is the terminal type to use when writing to the screen. When empty, + // `$TERM` is used from [os.Getenv]. + Term string + // Profile is the color profile to use when writing to the screen. + Profile colorprofile.Profile + // RelativeCursor is whether to use relative cursor movements. This is + // useful when alt-screen is not used or when using inline mode. + RelativeCursor bool + // AltScreen is whether to use the alternate screen buffer. + AltScreen bool + // ShowCursor is whether to show the cursor. + ShowCursor bool + // HardTabs is whether to use hard tabs to optimize cursor movements. + HardTabs bool + // Backspace is whether to use backspace characters to move the cursor. + Backspace bool +} + +// lineData represents the metadata for a line. +type lineData struct { + // first and last changed cell indices + firstCell, lastCell int + // old index used for scrolling + oldIndex int //nolint:unused +} + +// Screen represents the terminal screen. +type Screen struct { + w io.Writer + buf *bytes.Buffer // buffer for writing to the screen + curbuf *Buffer // the current buffer + newbuf *Buffer // the new buffer + tabs *TabStops + touch map[int]lineData + queueAbove []string // the queue of strings to write above the screen + oldhash, newhash []uint64 // the old and new hash values for each line + hashtab []hashmap // the hashmap table + oldnum []int // old indices from previous hash + cur, saved Cursor // the current and saved cursors + opts ScreenOptions + mu sync.Mutex + method ansi.Method + scrollHeight int // keeps track of how many lines we've scrolled down (inline mode) + altScreenMode bool // whether alternate screen mode is enabled + cursorHidden bool // whether text cursor mode is enabled + clear bool // whether to force clear the screen + xtermLike bool // whether to use xterm-like optimizations, otherwise, it uses vt100 only + queuedText bool // whether we have queued non-zero width text queued up + atPhantom bool // whether the cursor is out of bounds and at a phantom cell +} + +// SetMethod sets the method used to calculate the width of cells. +func (s *Screen) SetMethod(method ansi.Method) { + s.method = method +} + +// UseBackspaces sets whether to use backspace characters to move the cursor. +func (s *Screen) UseBackspaces(v bool) { + s.opts.Backspace = v +} + +// UseHardTabs sets whether to use hard tabs to optimize cursor movements. +func (s *Screen) UseHardTabs(v bool) { + s.opts.HardTabs = v +} + +// SetColorProfile sets the color profile to use when writing to the screen. +func (s *Screen) SetColorProfile(p colorprofile.Profile) { + s.opts.Profile = p +} + +// SetRelativeCursor sets whether to use relative cursor movements. +func (s *Screen) SetRelativeCursor(v bool) { + s.opts.RelativeCursor = v +} + +// EnterAltScreen enters the alternate screen buffer. +func (s *Screen) EnterAltScreen() { + s.opts.AltScreen = true + s.clear = true + s.saved = s.cur +} + +// ExitAltScreen exits the alternate screen buffer. +func (s *Screen) ExitAltScreen() { + s.opts.AltScreen = false + s.clear = true + s.cur = s.saved +} + +// ShowCursor shows the cursor. +func (s *Screen) ShowCursor() { + s.opts.ShowCursor = true +} + +// HideCursor hides the cursor. +func (s *Screen) HideCursor() { + s.opts.ShowCursor = false +} + +// Bounds implements Window. +func (s *Screen) Bounds() Rectangle { + // Always return the new buffer bounds. + return s.newbuf.Bounds() +} + +// Cell implements Window. +func (s *Screen) Cell(x int, y int) *Cell { + return s.newbuf.Cell(x, y) +} + +// Redraw forces a full redraw of the screen. +func (s *Screen) Redraw() { + s.mu.Lock() + s.clear = true + s.mu.Unlock() +} + +// Clear clears the screen with blank cells. This is a convenience method for +// [Screen.Fill] with a nil cell. +func (s *Screen) Clear() bool { + return s.ClearRect(s.newbuf.Bounds()) +} + +// ClearRect clears the given rectangle with blank cells. This is a convenience +// method for [Screen.FillRect] with a nil cell. +func (s *Screen) ClearRect(r Rectangle) bool { + return s.FillRect(nil, r) +} + +// SetCell implements Window. +func (s *Screen) SetCell(x int, y int, cell *Cell) (v bool) { + s.mu.Lock() + defer s.mu.Unlock() + cellWidth := 1 + if cell != nil { + cellWidth = cell.Width + } + if prev := s.curbuf.Cell(x, y); !cellEqual(prev, cell) { + chg, ok := s.touch[y] + if !ok { + chg = lineData{firstCell: x, lastCell: x + cellWidth} + } else { + chg.firstCell = min(chg.firstCell, x) + chg.lastCell = max(chg.lastCell, x+cellWidth) + } + s.touch[y] = chg + } + + return s.newbuf.SetCell(x, y, cell) +} + +// Fill implements Window. +func (s *Screen) Fill(cell *Cell) bool { + return s.FillRect(cell, s.newbuf.Bounds()) +} + +// FillRect implements Window. +func (s *Screen) FillRect(cell *Cell, r Rectangle) bool { + s.mu.Lock() + defer s.mu.Unlock() + s.newbuf.FillRect(cell, r) + for i := r.Min.Y; i < r.Max.Y; i++ { + s.touch[i] = lineData{firstCell: r.Min.X, lastCell: r.Max.X} + } + return true +} + +// isXtermLike returns whether the terminal is xterm-like. This means that the +// terminal supports ECMA-48 and ANSI X3.64 escape sequences. +// TODO: Should this be a lookup table into each $TERM terminfo database? Like +// we could keep a map of ANSI escape sequence to terminfo capability name and +// check if the database supports the escape sequence. Instead of keeping a +// list of terminal names here. +func isXtermLike(termtype string) (v bool) { + parts := strings.Split(termtype, "-") + if len(parts) == 0 { + return + } + + switch parts[0] { + case + "alacritty", + "contour", + "foot", + "ghostty", + "kitty", + "linux", + "rio", + "screen", + "st", + "tmux", + "wezterm", + "xterm": + v = true + } + + return +} + +// NewScreen creates a new Screen. +func NewScreen(w io.Writer, width, height int, opts *ScreenOptions) (s *Screen) { + s = new(Screen) + s.w = w + if opts != nil { + s.opts = *opts + } + + if s.opts.Term == "" { + s.opts.Term = os.Getenv("TERM") + } + + if width <= 0 || height <= 0 { + if f, ok := w.(term.File); ok { + width, height, _ = term.GetSize(f.Fd()) + } + } + if width < 0 { + width = 0 + } + if height < 0 { + height = 0 + } + + s.buf = new(bytes.Buffer) + s.xtermLike = isXtermLike(s.opts.Term) + s.curbuf = NewBuffer(width, height) + s.newbuf = NewBuffer(width, height) + s.cur = Cursor{Position: Pos(-1, -1)} // start at -1 to force a move + s.saved = s.cur + s.reset() + + return +} + +// Width returns the width of the screen. +func (s *Screen) Width() int { + return s.newbuf.Width() +} + +// Height returns the height of the screen. +func (s *Screen) Height() int { + return s.newbuf.Height() +} + +// cellEqual returns whether the two cells are equal. A nil cell is considered +// a [BlankCell]. +func cellEqual(a, b *Cell) bool { + if a == b { + return true + } + if a == nil { + a = &BlankCell + } + if b == nil { + b = &BlankCell + } + return a.Equal(b) +} + +// putCell draws a cell at the current cursor position. +func (s *Screen) putCell(cell *Cell) { + width, height := s.newbuf.Width(), s.newbuf.Height() + if s.opts.AltScreen && s.cur.X == width-1 && s.cur.Y == height-1 { + s.putCellLR(cell) + } else { + s.putAttrCell(cell) + } +} + +// wrapCursor wraps the cursor to the next line. +// +//nolint:unused +func (s *Screen) wrapCursor() { + const autoRightMargin = true + if autoRightMargin { + // Assume we have auto wrap mode enabled. + s.cur.X = 0 + s.cur.Y++ + } else { + s.cur.X-- + } +} + +func (s *Screen) putAttrCell(cell *Cell) { + if cell != nil && cell.Empty() { + // XXX: Zero width cells are special and should not be written to the + // screen no matter what other attributes they have. + // Zero width cells are used for wide characters that are split into + // multiple cells. + return + } + + if cell == nil { + cell = s.clearBlank() + } + + // We're at pending wrap state (phantom cell), incoming cell should + // wrap. + if s.atPhantom { + s.wrapCursor() + s.atPhantom = false + } + + s.updatePen(cell) + s.buf.WriteRune(cell.Rune) //nolint:errcheck + for _, c := range cell.Comb { + s.buf.WriteRune(c) //nolint:errcheck + } + + s.cur.X += cell.Width + + if cell.Width > 0 { + s.queuedText = true + } + + if s.cur.X >= s.newbuf.Width() { + s.atPhantom = true + } +} + +// putCellLR draws a cell at the lower right corner of the screen. +func (s *Screen) putCellLR(cell *Cell) { + // Optimize for the lower right corner cell. + curX := s.cur.X + if cell == nil || !cell.Empty() { + s.buf.WriteString(ansi.ResetAutoWrapMode) //nolint:errcheck + s.putAttrCell(cell) + // Writing to lower-right corner cell should not wrap. + s.atPhantom = false + s.cur.X = curX + s.buf.WriteString(ansi.SetAutoWrapMode) //nolint:errcheck + } +} + +// updatePen updates the cursor pen styles. +func (s *Screen) updatePen(cell *Cell) { + if cell == nil { + cell = &BlankCell + } + + if s.opts.Profile != 0 { + // Downsample colors to the given color profile. + cell.Style = ConvertStyle(cell.Style, s.opts.Profile) + cell.Link = ConvertLink(cell.Link, s.opts.Profile) + } + + if !cell.Style.Equal(&s.cur.Style) { + seq := cell.Style.DiffSequence(s.cur.Style) + if cell.Style.Empty() && len(seq) > len(ansi.ResetStyle) { + seq = ansi.ResetStyle + } + s.buf.WriteString(seq) //nolint:errcheck + s.cur.Style = cell.Style + } + if !cell.Link.Equal(&s.cur.Link) { + s.buf.WriteString(ansi.SetHyperlink(cell.Link.URL, cell.Link.Params)) //nolint:errcheck + s.cur.Link = cell.Link + } +} + +// emitRange emits a range of cells to the buffer. It it equivalent to calling +// [Screen.putCell] for each cell in the range. This is optimized to use +// [ansi.ECH] and [ansi.REP]. +// Returns whether the cursor is at the end of interval or somewhere in the +// middle. +func (s *Screen) emitRange(line Line, n int) (eoi bool) { + for n > 0 { + var count int + for n > 1 && !cellEqual(line.At(0), line.At(1)) { + s.putCell(line.At(0)) + line = line[1:] + n-- + } + + cell0 := line[0] + if n == 1 { + s.putCell(cell0) + return false + } + + count = 2 + for count < n && cellEqual(line.At(count), cell0) { + count++ + } + + ech := ansi.EraseCharacter(count) + cup := ansi.CursorPosition(s.cur.X+count, s.cur.Y) + rep := ansi.RepeatPreviousCharacter(count) + if s.xtermLike && count > len(ech)+len(cup) && cell0 != nil && cell0.Clear() { + s.updatePen(cell0) + s.buf.WriteString(ech) //nolint:errcheck + + // If this is the last cell, we don't need to move the cursor. + if count < n { + s.move(s.cur.X+count, s.cur.Y) + } else { + return true // cursor in the middle + } + } else if s.xtermLike && count > len(rep) && + (cell0 == nil || (len(cell0.Comb) == 0 && cell0.Rune < 256)) { + // We only support ASCII characters. Most terminals will handle + // non-ASCII characters correctly, but some might not, ahem xterm. + // + // NOTE: [ansi.REP] only repeats the last rune and won't work + // if the last cell contains multiple runes. + + wrapPossible := s.cur.X+count >= s.newbuf.Width() + repCount := count + if wrapPossible { + repCount-- + } + + s.updatePen(cell0) + s.putCell(cell0) + repCount-- // cell0 is a single width cell ASCII character + + s.buf.WriteString(ansi.RepeatPreviousCharacter(repCount)) //nolint:errcheck + s.cur.X += repCount + if wrapPossible { + s.putCell(cell0) + } + } else { + for i := 0; i < count; i++ { + s.putCell(line.At(i)) + } + } + + line = line[clamp(count, 0, len(line)):] + n -= count + } + + return +} + +// putRange puts a range of cells from the old line to the new line. +// Returns whether the cursor is at the end of interval or somewhere in the +// middle. +func (s *Screen) putRange(oldLine, newLine Line, y, start, end int) (eoi bool) { + inline := min(len(ansi.CursorPosition(start+1, y+1)), + min(len(ansi.HorizontalPositionAbsolute(start+1)), + len(ansi.CursorForward(start+1)))) + if (end - start + 1) > inline { + var j, same int + for j, same = start, 0; j <= end; j++ { + oldCell, newCell := oldLine.At(j), newLine.At(j) + if same == 0 && oldCell != nil && oldCell.Empty() { + continue + } + if cellEqual(oldCell, newCell) { + same++ + } else { + if same > end-start { + s.emitRange(newLine[start:], j-same-start) + s.move(j, y) + start = j + } + same = 0 + } + } + + i := s.emitRange(newLine[start:], j-same-start) + + // Always return 1 for the next [Screen.move] after a [Screen.putRange] if + // we found identical characters at end of interval. + if same == 0 { + return i + } + return true + } + + return s.emitRange(newLine[start:], end-start+1) +} + +// clearToEnd clears the screen from the current cursor position to the end of +// line. +func (s *Screen) clearToEnd(blank *Cell, force bool) { //nolint:unparam + if s.cur.Y >= 0 { + curline := s.curbuf.Line(s.cur.Y) + for j := s.cur.X; j < s.curbuf.Width(); j++ { + if j >= 0 { + c := curline.At(j) + if !cellEqual(c, blank) { + curline.Set(j, blank) + force = true + } + } + } + } + + if force { + s.updatePen(blank) + count := s.newbuf.Width() - s.cur.X + if s.el0Cost() <= count { + s.buf.WriteString(ansi.EraseLineRight) //nolint:errcheck + } else { + for i := 0; i < count; i++ { + s.putCell(blank) + } + } + } +} + +// clearBlank returns a blank cell based on the current cursor background color. +func (s *Screen) clearBlank() *Cell { + c := BlankCell + if !s.cur.Style.Empty() || !s.cur.Link.Empty() { + c.Style = s.cur.Style + c.Link = s.cur.Link + } + return &c +} + +// insertCells inserts the count cells pointed by the given line at the current +// cursor position. +func (s *Screen) insertCells(line Line, count int) { + if s.xtermLike { + // Use [ansi.ICH] as an optimization. + s.buf.WriteString(ansi.InsertCharacter(count)) //nolint:errcheck + } else { + // Otherwise, use [ansi.IRM] mode. + s.buf.WriteString(ansi.SetInsertReplaceMode) //nolint:errcheck + } + + for i := 0; count > 0; i++ { + s.putAttrCell(line[i]) + count-- + } + + if !s.xtermLike { + s.buf.WriteString(ansi.ResetInsertReplaceMode) //nolint:errcheck + } +} + +// el0Cost returns the cost of using [ansi.EL] 0 i.e. [ansi.EraseLineRight]. If +// this terminal supports background color erase, it can be cheaper to use +// [ansi.EL] 0 i.e. [ansi.EraseLineRight] to clear +// trailing spaces. +func (s *Screen) el0Cost() int { + if s.xtermLike { + return 0 + } + return len(ansi.EraseLineRight) +} + +// transformLine transforms the given line in the current window to the +// corresponding line in the new window. It uses [ansi.ICH] and [ansi.DCH] to +// insert or delete characters. +func (s *Screen) transformLine(y int) { + var firstCell, oLastCell, nLastCell int // first, old last, new last index + oldLine := s.curbuf.Line(y) + newLine := s.newbuf.Line(y) + + // Find the first changed cell in the line + var lineChanged bool + for i := 0; i < s.newbuf.Width(); i++ { + if !cellEqual(newLine.At(i), oldLine.At(i)) { + lineChanged = true + break + } + } + + const ceolStandoutGlitch = false + if ceolStandoutGlitch && lineChanged { + s.move(0, y) + s.clearToEnd(nil, false) + s.putRange(oldLine, newLine, y, 0, s.newbuf.Width()-1) + } else { + blank := newLine.At(0) + + // It might be cheaper to clear leading spaces with [ansi.EL] 1 i.e. + // [ansi.EraseLineLeft]. + if blank == nil || blank.Clear() { + var oFirstCell, nFirstCell int + for oFirstCell = 0; oFirstCell < s.curbuf.Width(); oFirstCell++ { + if !cellEqual(oldLine.At(oFirstCell), blank) { + break + } + } + for nFirstCell = 0; nFirstCell < s.newbuf.Width(); nFirstCell++ { + if !cellEqual(newLine.At(nFirstCell), blank) { + break + } + } + + if nFirstCell == oFirstCell { + firstCell = nFirstCell + + // Find the first differing cell + for firstCell < s.newbuf.Width() && + cellEqual(oldLine.At(firstCell), newLine.At(firstCell)) { + firstCell++ + } + } else if oFirstCell > nFirstCell { + firstCell = nFirstCell + } else if oFirstCell < nFirstCell { + firstCell = oFirstCell + el1Cost := len(ansi.EraseLineLeft) + if el1Cost < nFirstCell-oFirstCell { + if nFirstCell >= s.newbuf.Width() { + s.move(0, y) + s.updatePen(blank) + s.buf.WriteString(ansi.EraseLineRight) //nolint:errcheck + } else { + s.move(nFirstCell-1, y) + s.updatePen(blank) + s.buf.WriteString(ansi.EraseLineLeft) //nolint:errcheck + } + + for firstCell < nFirstCell { + oldLine.Set(firstCell, blank) + firstCell++ + } + } + } + } else { + // Find the first differing cell + for firstCell < s.newbuf.Width() && cellEqual(newLine.At(firstCell), oldLine.At(firstCell)) { + firstCell++ + } + } + + // If we didn't find one, we're done + if firstCell >= s.newbuf.Width() { + return + } + + blank = newLine.At(s.newbuf.Width() - 1) + if blank != nil && !blank.Clear() { + // Find the last differing cell + nLastCell = s.newbuf.Width() - 1 + for nLastCell > firstCell && cellEqual(newLine.At(nLastCell), oldLine.At(nLastCell)) { + nLastCell-- + } + + if nLastCell >= firstCell { + s.move(firstCell, y) + s.putRange(oldLine, newLine, y, firstCell, nLastCell) + if firstCell < len(oldLine) && firstCell < len(newLine) { + copy(oldLine[firstCell:], newLine[firstCell:]) + } else { + copy(oldLine, newLine) + } + } + + return + } + + // Find last non-blank cell in the old line. + oLastCell = s.curbuf.Width() - 1 + for oLastCell > firstCell && cellEqual(oldLine.At(oLastCell), blank) { + oLastCell-- + } + + // Find last non-blank cell in the new line. + nLastCell = s.newbuf.Width() - 1 + for nLastCell > firstCell && cellEqual(newLine.At(nLastCell), blank) { + nLastCell-- + } + + if nLastCell == firstCell && s.el0Cost() < oLastCell-nLastCell { + s.move(firstCell, y) + if !cellEqual(newLine.At(firstCell), blank) { + s.putCell(newLine.At(firstCell)) + } + s.clearToEnd(blank, false) + } else if nLastCell != oLastCell && + !cellEqual(newLine.At(nLastCell), oldLine.At(oLastCell)) { + s.move(firstCell, y) + if oLastCell-nLastCell > s.el0Cost() { + if s.putRange(oldLine, newLine, y, firstCell, nLastCell) { + s.move(nLastCell+1, y) + } + s.clearToEnd(blank, false) + } else { + n := max(nLastCell, oLastCell) + s.putRange(oldLine, newLine, y, firstCell, n) + } + } else { + nLastNonBlank := nLastCell + oLastNonBlank := oLastCell + + // Find the last cells that really differ. + // Can be -1 if no cells differ. + for cellEqual(newLine.At(nLastCell), oldLine.At(oLastCell)) { + if !cellEqual(newLine.At(nLastCell-1), oldLine.At(oLastCell-1)) { + break + } + nLastCell-- + oLastCell-- + if nLastCell == -1 || oLastCell == -1 { + break + } + } + + n := min(oLastCell, nLastCell) + if n >= firstCell { + s.move(firstCell, y) + s.putRange(oldLine, newLine, y, firstCell, n) + } + + if oLastCell < nLastCell { + m := max(nLastNonBlank, oLastNonBlank) + if n != 0 { + for n > 0 { + wide := newLine.At(n + 1) + if wide == nil || !wide.Empty() { + break + } + n-- + oLastCell-- + } + } else if n >= firstCell && newLine.At(n) != nil && newLine.At(n).Width > 1 { + next := newLine.At(n + 1) + for next != nil && next.Empty() { + n++ + oLastCell++ + } + } + + s.move(n+1, y) + ichCost := 3 + nLastCell - oLastCell + if s.xtermLike && (nLastCell < nLastNonBlank || ichCost > (m-n)) { + s.putRange(oldLine, newLine, y, n+1, m) + } else { + s.insertCells(newLine[n+1:], nLastCell-oLastCell) + } + } else if oLastCell > nLastCell { + s.move(n+1, y) + dchCost := 3 + oLastCell - nLastCell + if dchCost > len(ansi.EraseLineRight)+nLastNonBlank-(n+1) { + if s.putRange(oldLine, newLine, y, n+1, nLastNonBlank) { + s.move(nLastNonBlank+1, y) + } + s.clearToEnd(blank, false) + } else { + s.updatePen(blank) + s.deleteCells(oLastCell - nLastCell) + } + } + } + } + + // Update the old line with the new line + if firstCell < len(oldLine) && firstCell < len(newLine) { + copy(oldLine[firstCell:], newLine[firstCell:]) + } else { + copy(oldLine, newLine) + } +} + +// deleteCells deletes the count cells at the current cursor position and moves +// the rest of the line to the left. This is equivalent to [ansi.DCH]. +func (s *Screen) deleteCells(count int) { + // [ansi.DCH] will shift in cells from the right margin so we need to + // ensure that they are the right style. + s.buf.WriteString(ansi.DeleteCharacter(count)) //nolint:errcheck +} + +// clearToBottom clears the screen from the current cursor position to the end +// of the screen. +func (s *Screen) clearToBottom(blank *Cell) { + row, col := s.cur.Y, s.cur.X + if row < 0 { + row = 0 + } + + s.updatePen(blank) + s.buf.WriteString(ansi.EraseScreenBelow) //nolint:errcheck + // Clear the rest of the current line + s.curbuf.ClearRect(Rect(col, row, s.curbuf.Width()-col, 1)) + // Clear everything below the current line + s.curbuf.ClearRect(Rect(0, row+1, s.curbuf.Width(), s.curbuf.Height()-row-1)) +} + +// clearBottom tests if clearing the end of the screen would satisfy part of +// the screen update. Scan backwards through lines in the screen checking if +// each is blank and one or more are changed. +// It returns the top line. +func (s *Screen) clearBottom(total int) (top int) { + if total <= 0 { + return + } + + top = total + last := s.newbuf.Width() + blank := s.clearBlank() + canClearWithBlank := blank == nil || blank.Clear() + + if canClearWithBlank { + var row int + for row = total - 1; row >= 0; row-- { + oldLine := s.curbuf.Line(row) + newLine := s.newbuf.Line(row) + + var col int + ok := true + for col = 0; ok && col < last; col++ { + ok = cellEqual(newLine.At(col), blank) + } + if !ok { + break + } + + for col = 0; ok && col < last; col++ { + ok = len(oldLine) == last && cellEqual(oldLine.At(col), blank) + } + if !ok { + top = row + } + } + + if top < total { + s.move(0, top-1) // top is 1-based + s.clearToBottom(blank) + if s.oldhash != nil && s.newhash != nil && + row < len(s.oldhash) && row < len(s.newhash) { + for row := top; row < s.newbuf.Height(); row++ { + s.oldhash[row] = s.newhash[row] + } + } + } + } + + return +} + +// clearScreen clears the screen and put cursor at home. +func (s *Screen) clearScreen(blank *Cell) { + s.updatePen(blank) + s.buf.WriteString(ansi.CursorHomePosition) //nolint:errcheck + s.buf.WriteString(ansi.EraseEntireScreen) //nolint:errcheck + s.cur.X, s.cur.Y = 0, 0 + s.curbuf.Fill(blank) +} + +// clearBelow clears everything below and including the row. +func (s *Screen) clearBelow(blank *Cell, row int) { + s.move(0, row) + s.clearToBottom(blank) +} + +// clearUpdate forces a screen redraw. +func (s *Screen) clearUpdate() { + blank := s.clearBlank() + var nonEmpty int + if s.opts.AltScreen { + // XXX: We're using the maximum height of the two buffers to ensure + // we write newly added lines to the screen in [Screen.transformLine]. + nonEmpty = max(s.curbuf.Height(), s.newbuf.Height()) + s.clearScreen(blank) + } else { + nonEmpty = s.newbuf.Height() + s.clearBelow(blank, 0) + } + nonEmpty = s.clearBottom(nonEmpty) + for i := 0; i < nonEmpty; i++ { + s.transformLine(i) + } +} + +// Flush flushes the buffer to the screen. +func (s *Screen) Flush() (err error) { + s.mu.Lock() + defer s.mu.Unlock() + return s.flush() +} + +func (s *Screen) flush() (err error) { + // Write the buffer + if s.buf.Len() > 0 { + _, err = s.w.Write(s.buf.Bytes()) //nolint:errcheck + if err == nil { + s.buf.Reset() + } + } + + return +} + +// Render renders changes of the screen to the internal buffer. Call +// [Screen.Flush] to flush pending changes to the screen. +func (s *Screen) Render() { + s.mu.Lock() + s.render() + s.mu.Unlock() +} + +func (s *Screen) render() { + // Do we need to render anything? + if s.opts.AltScreen == s.altScreenMode && + !s.opts.ShowCursor == s.cursorHidden && + !s.clear && + len(s.touch) == 0 && + len(s.queueAbove) == 0 { + return + } + + // TODO: Investigate whether this is necessary. Theoretically, terminals + // can add/remove tab stops and we should be able to handle that. We could + // use [ansi.DECTABSR] to read the tab stops, but that's not implemented in + // most terminals :/ + // // Are we using hard tabs? If so, ensure tabs are using the + // // default interval using [ansi.DECST8C]. + // if s.opts.HardTabs && !s.initTabs { + // s.buf.WriteString(ansi.SetTabEvery8Columns) + // s.initTabs = true + // } + + // Do we need alt-screen mode? + if s.opts.AltScreen != s.altScreenMode { + if s.opts.AltScreen { + s.buf.WriteString(ansi.SetAltScreenSaveCursorMode) + } else { + s.buf.WriteString(ansi.ResetAltScreenSaveCursorMode) + } + s.altScreenMode = s.opts.AltScreen + } + + // Do we need text cursor mode? + if !s.opts.ShowCursor != s.cursorHidden { + s.cursorHidden = !s.opts.ShowCursor + if s.cursorHidden { + s.buf.WriteString(ansi.HideCursor) + } + } + + // Do we have queued strings to write above the screen? + if len(s.queueAbove) > 0 { + // TODO: Use scrolling region if available. + // TODO: Use [Screen.Write] [io.Writer] interface. + + // We need to scroll the screen up by the number of lines in the queue. + // We can't use [ansi.SU] because we want the cursor to move down until + // it reaches the bottom of the screen. + s.move(0, s.newbuf.Height()-1) + s.buf.WriteString(strings.Repeat("\n", len(s.queueAbove))) + s.cur.Y += len(s.queueAbove) + // XXX: Now go to the top of the screen, insert new lines, and write + // the queued strings. It is important to use [Screen.moveCursor] + // instead of [Screen.move] because we don't want to perform any checks + // on the cursor position. + s.moveCursor(0, 0, false) + s.buf.WriteString(ansi.InsertLine(len(s.queueAbove))) + for _, line := range s.queueAbove { + s.buf.WriteString(line + "\r\n") + } + + // Clear the queue + s.queueAbove = s.queueAbove[:0] + } + + var nonEmpty int + + // XXX: In inline mode, after a screen resize, we need to clear the extra + // lines at the bottom of the screen. This is because in inline mode, we + // don't use the full screen height and the current buffer size might be + // larger than the new buffer size. + partialClear := !s.opts.AltScreen && s.cur.X != -1 && s.cur.Y != -1 && + s.curbuf.Width() == s.newbuf.Width() && + s.curbuf.Height() > 0 && + s.curbuf.Height() > s.newbuf.Height() + + if !s.clear && partialClear { + s.clearBelow(nil, s.newbuf.Height()-1) + } + + if s.clear { + s.clearUpdate() + s.clear = false + } else if len(s.touch) > 0 { + if s.opts.AltScreen { + // Optimize scrolling for the alternate screen buffer. + // TODO: Should we optimize for inline mode as well? If so, we need + // to know the actual cursor position to use [ansi.DECSTBM]. + s.scrollOptimize() + } + + var changedLines int + var i int + + if s.opts.AltScreen { + nonEmpty = min(s.curbuf.Height(), s.newbuf.Height()) + } else { + nonEmpty = s.newbuf.Height() + } + + nonEmpty = s.clearBottom(nonEmpty) + for i = 0; i < nonEmpty; i++ { + _, ok := s.touch[i] + if ok { + s.transformLine(i) + changedLines++ + } + } + } + + // Sync windows and screen + s.touch = make(map[int]lineData, s.newbuf.Height()) + + if s.curbuf.Width() != s.newbuf.Width() || s.curbuf.Height() != s.newbuf.Height() { + // Resize the old buffer to match the new buffer. + _, oldh := s.curbuf.Width(), s.curbuf.Height() + s.curbuf.Resize(s.newbuf.Width(), s.newbuf.Height()) + // Sync new lines to old lines + for i := oldh - 1; i < s.newbuf.Height(); i++ { + copy(s.curbuf.Line(i), s.newbuf.Line(i)) + } + } + + s.updatePen(nil) // nil indicates a blank cell with no styles + + // Do we have enough changes to justify toggling the cursor? + if s.buf.Len() > 1 && s.opts.ShowCursor && !s.cursorHidden && s.queuedText { + nb := new(bytes.Buffer) + nb.Grow(s.buf.Len() + len(ansi.HideCursor) + len(ansi.ShowCursor)) + nb.WriteString(ansi.HideCursor) + nb.Write(s.buf.Bytes()) + nb.WriteString(ansi.ShowCursor) + *s.buf = *nb + } + + s.queuedText = false +} + +// Close writes the final screen update and resets the screen. +func (s *Screen) Close() (err error) { + s.mu.Lock() + defer s.mu.Unlock() + + s.render() + s.updatePen(nil) + // Go to the bottom of the screen + s.move(0, s.newbuf.Height()-1) + + if s.altScreenMode { + s.buf.WriteString(ansi.ResetAltScreenSaveCursorMode) + s.altScreenMode = false + } + + if s.cursorHidden { + s.buf.WriteString(ansi.ShowCursor) + s.cursorHidden = false + } + + // Write the buffer + err = s.flush() + if err != nil { + return + } + + s.reset() + return +} + +// reset resets the screen to its initial state. +func (s *Screen) reset() { + s.scrollHeight = 0 + s.cursorHidden = false + s.altScreenMode = false + s.touch = make(map[int]lineData, s.newbuf.Height()) + if s.curbuf != nil { + s.curbuf.Clear() + } + if s.newbuf != nil { + s.newbuf.Clear() + } + s.buf.Reset() + s.tabs = DefaultTabStops(s.newbuf.Width()) + s.oldhash, s.newhash = nil, nil + + // We always disable HardTabs when termtype is "linux". + if strings.HasPrefix(s.opts.Term, "linux") { + s.opts.HardTabs = false + } +} + +// Resize resizes the screen. +func (s *Screen) Resize(width, height int) bool { + oldw := s.newbuf.Width() + oldh := s.newbuf.Height() + + if s.opts.AltScreen || width != oldw { + // We only clear the whole screen if the width changes. Adding/removing + // rows is handled by the [Screen.render] and [Screen.transformLine] + // methods. + s.clear = true + } + + // Clear new columns and lines + if width > oldh { + s.ClearRect(Rect(max(oldw-1, 0), 0, width-oldw, height)) + } else if width < oldw { + s.ClearRect(Rect(max(width-1, 0), 0, oldw-width, height)) + } + + if height > oldh { + s.ClearRect(Rect(0, max(oldh-1, 0), width, height-oldh)) + } else if height < oldh { + s.ClearRect(Rect(0, max(height-1, 0), width, oldh-height)) + } + + s.mu.Lock() + s.newbuf.Resize(width, height) + s.tabs.Resize(width) + s.oldhash, s.newhash = nil, nil + s.scrollHeight = 0 // reset scroll lines + s.mu.Unlock() + + return true +} + +// MoveTo moves the cursor to the given position. +func (s *Screen) MoveTo(x, y int) { + s.mu.Lock() + s.move(x, y) + s.mu.Unlock() +} + +// InsertAbove inserts string above the screen. The inserted string is not +// managed by the screen. This does nothing when alternate screen mode is +// enabled. +func (s *Screen) InsertAbove(str string) { + if s.opts.AltScreen { + return + } + s.mu.Lock() + for _, line := range strings.Split(str, "\n") { + s.queueAbove = append(s.queueAbove, s.method.Truncate(line, s.Width(), "")) + } + s.mu.Unlock() +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/sequence.go b/vendor/github.com/charmbracelet/x/cellbuf/sequence.go new file mode 100644 index 00000000..613eefef --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/sequence.go @@ -0,0 +1,131 @@ +package cellbuf + +import ( + "bytes" + "image/color" + + "github.com/charmbracelet/x/ansi" +) + +// ReadStyle reads a Select Graphic Rendition (SGR) escape sequences from a +// list of parameters. +func ReadStyle(params ansi.Params, pen *Style) { + if len(params) == 0 { + pen.Reset() + return + } + + for i := 0; i < len(params); i++ { + param, hasMore, _ := params.Param(i, 0) + switch param { + case 0: // Reset + pen.Reset() + case 1: // Bold + pen.Bold(true) + case 2: // Dim/Faint + pen.Faint(true) + case 3: // Italic + pen.Italic(true) + case 4: // Underline + nextParam, _, ok := params.Param(i+1, 0) + if hasMore && ok { // Only accept subparameters i.e. separated by ":" + switch nextParam { + case 0, 1, 2, 3, 4, 5: + i++ + switch nextParam { + case 0: // No Underline + pen.UnderlineStyle(NoUnderline) + case 1: // Single Underline + pen.UnderlineStyle(SingleUnderline) + case 2: // Double Underline + pen.UnderlineStyle(DoubleUnderline) + case 3: // Curly Underline + pen.UnderlineStyle(CurlyUnderline) + case 4: // Dotted Underline + pen.UnderlineStyle(DottedUnderline) + case 5: // Dashed Underline + pen.UnderlineStyle(DashedUnderline) + } + } + } else { + // Single Underline + pen.Underline(true) + } + case 5: // Slow Blink + pen.SlowBlink(true) + case 6: // Rapid Blink + pen.RapidBlink(true) + case 7: // Reverse + pen.Reverse(true) + case 8: // Conceal + pen.Conceal(true) + case 9: // Crossed-out/Strikethrough + pen.Strikethrough(true) + case 22: // Normal Intensity (not bold or faint) + pen.Bold(false).Faint(false) + case 23: // Not italic, not Fraktur + pen.Italic(false) + case 24: // Not underlined + pen.Underline(false) + case 25: // Blink off + pen.SlowBlink(false).RapidBlink(false) + case 27: // Positive (not reverse) + pen.Reverse(false) + case 28: // Reveal + pen.Conceal(false) + case 29: // Not crossed out + pen.Strikethrough(false) + case 30, 31, 32, 33, 34, 35, 36, 37: // Set foreground + pen.Foreground(ansi.Black + ansi.BasicColor(param-30)) //nolint:gosec + case 38: // Set foreground 256 or truecolor + var c color.Color + n := ReadStyleColor(params[i:], &c) + if n > 0 { + pen.Foreground(c) + i += n - 1 + } + case 39: // Default foreground + pen.Foreground(nil) + case 40, 41, 42, 43, 44, 45, 46, 47: // Set background + pen.Background(ansi.Black + ansi.BasicColor(param-40)) //nolint:gosec + case 48: // Set background 256 or truecolor + var c color.Color + n := ReadStyleColor(params[i:], &c) + if n > 0 { + pen.Background(c) + i += n - 1 + } + case 49: // Default Background + pen.Background(nil) + case 58: // Set underline color + var c color.Color + n := ReadStyleColor(params[i:], &c) + if n > 0 { + pen.UnderlineColor(c) + i += n - 1 + } + case 59: // Default underline color + pen.UnderlineColor(nil) + case 90, 91, 92, 93, 94, 95, 96, 97: // Set bright foreground + pen.Foreground(ansi.BrightBlack + ansi.BasicColor(param-90)) //nolint:gosec + case 100, 101, 102, 103, 104, 105, 106, 107: // Set bright background + pen.Background(ansi.BrightBlack + ansi.BasicColor(param-100)) //nolint:gosec + } + } +} + +// ReadLink reads a hyperlink escape sequence from a data buffer. +func ReadLink(p []byte, link *Link) { + params := bytes.Split(p, []byte{';'}) + if len(params) != 3 { + return + } + link.Params = string(params[1]) + link.URL = string(params[2]) +} + +// ReadStyleColor reads a color from a list of parameters. +// See [ansi.ReadStyleColor] for more information. +func ReadStyleColor(params ansi.Params, c *color.Color) int { + return ansi.ReadStyleColor(params, c) +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/style.go b/vendor/github.com/charmbracelet/x/cellbuf/style.go new file mode 100644 index 00000000..82c4afb7 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/style.go @@ -0,0 +1,31 @@ +package cellbuf + +import ( + "github.com/charmbracelet/colorprofile" +) + +// Convert converts a style to respect the given color profile. +func ConvertStyle(s Style, p colorprofile.Profile) Style { + switch p { + case colorprofile.TrueColor: + return s + case colorprofile.Ascii: + s.Fg = nil + s.Bg = nil + s.Ul = nil + case colorprofile.NoTTY: + return Style{} + } + + if s.Fg != nil { + s.Fg = p.Convert(s.Fg) + } + if s.Bg != nil { + s.Bg = p.Convert(s.Bg) + } + if s.Ul != nil { + s.Ul = p.Convert(s.Ul) + } + + return s +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/tabstop.go b/vendor/github.com/charmbracelet/x/cellbuf/tabstop.go new file mode 100644 index 00000000..24eec449 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/tabstop.go @@ -0,0 +1,137 @@ +package cellbuf + +// DefaultTabInterval is the default tab interval. +const DefaultTabInterval = 8 + +// TabStops represents horizontal line tab stops. +type TabStops struct { + stops []int + interval int + width int +} + +// NewTabStops creates a new set of tab stops from a number of columns and an +// interval. +func NewTabStops(width, interval int) *TabStops { + ts := new(TabStops) + ts.interval = interval + ts.width = width + ts.stops = make([]int, (width+(interval-1))/interval) + ts.init(0, width) + return ts +} + +// DefaultTabStops creates a new set of tab stops with the default interval. +func DefaultTabStops(cols int) *TabStops { + return NewTabStops(cols, DefaultTabInterval) +} + +// Resize resizes the tab stops to the given width. +func (ts *TabStops) Resize(width int) { + if width == ts.width { + return + } + + if width < ts.width { + size := (width + (ts.interval - 1)) / ts.interval + ts.stops = ts.stops[:size] + } else { + size := (width - ts.width + (ts.interval - 1)) / ts.interval + ts.stops = append(ts.stops, make([]int, size)...) + } + + ts.init(ts.width, width) + ts.width = width +} + +// IsStop returns true if the given column is a tab stop. +func (ts TabStops) IsStop(col int) bool { + mask := ts.mask(col) + i := col >> 3 + if i < 0 || i >= len(ts.stops) { + return false + } + return ts.stops[i]&mask != 0 +} + +// Next returns the next tab stop after the given column. +func (ts TabStops) Next(col int) int { + return ts.Find(col, 1) +} + +// Prev returns the previous tab stop before the given column. +func (ts TabStops) Prev(col int) int { + return ts.Find(col, -1) +} + +// Find returns the prev/next tab stop before/after the given column and delta. +// If delta is positive, it returns the next tab stop after the given column. +// If delta is negative, it returns the previous tab stop before the given column. +// If delta is zero, it returns the given column. +func (ts TabStops) Find(col, delta int) int { + if delta == 0 { + return col + } + + var prev bool + count := delta + if count < 0 { + count = -count + prev = true + } + + for count > 0 { + if !prev { + if col >= ts.width-1 { + return col + } + + col++ + } else { + if col < 1 { + return col + } + + col-- + } + + if ts.IsStop(col) { + count-- + } + } + + return col +} + +// Set adds a tab stop at the given column. +func (ts *TabStops) Set(col int) { + mask := ts.mask(col) + ts.stops[col>>3] |= mask +} + +// Reset removes the tab stop at the given column. +func (ts *TabStops) Reset(col int) { + mask := ts.mask(col) + ts.stops[col>>3] &= ^mask +} + +// Clear removes all tab stops. +func (ts *TabStops) Clear() { + ts.stops = make([]int, len(ts.stops)) +} + +// mask returns the mask for the given column. +func (ts *TabStops) mask(col int) int { + return 1 << (col & (ts.interval - 1)) +} + +// init initializes the tab stops starting from col until width. +func (ts *TabStops) init(col, width int) { + for x := col; x < width; x++ { + if x%ts.interval == 0 { + ts.Set(x) + } else { + ts.Reset(x) + } + } +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/utils.go b/vendor/github.com/charmbracelet/x/cellbuf/utils.go new file mode 100644 index 00000000..b0452fa9 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/utils.go @@ -0,0 +1,38 @@ +package cellbuf + +import ( + "strings" +) + +// Height returns the height of a string. +func Height(s string) int { + return strings.Count(s, "\n") + 1 +} + +func min(a, b int) int { //nolint:predeclared + if a > b { + return b + } + return a +} + +func max(a, b int) int { //nolint:predeclared + if a > b { + return a + } + return b +} + +func clamp(v, low, high int) int { + if high < low { + low, high = high, low + } + return min(high, max(low, v)) +} + +func abs(a int) int { + if a < 0 { + return -a + } + return a +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/wrap.go b/vendor/github.com/charmbracelet/x/cellbuf/wrap.go new file mode 100644 index 00000000..59a2a337 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/wrap.go @@ -0,0 +1,178 @@ +package cellbuf + +import ( + "bytes" + "unicode" + "unicode/utf8" + + "github.com/charmbracelet/x/ansi" +) + +// Wrap returns a string that is wrapped to the specified limit applying any +// ANSI escape sequences in the string. It tries to wrap the string at word +// boundaries, but will break words if necessary. +// +// The breakpoints string is a list of characters that are considered +// breakpoints for word wrapping. A hyphen (-) is always considered a +// breakpoint. +// +// Note: breakpoints must be a string of 1-cell wide rune characters. +func Wrap(s string, limit int, breakpoints string) string { + if len(s) == 0 { + return "" + } + + if limit < 1 { + return s + } + + p := ansi.GetParser() + defer ansi.PutParser(p) + + var ( + buf bytes.Buffer + word bytes.Buffer + space bytes.Buffer + style, curStyle Style + link, curLink Link + curWidth int + wordLen int + ) + + addSpace := func() { + curWidth += space.Len() + buf.Write(space.Bytes()) + space.Reset() + } + + addWord := func() { + if word.Len() == 0 { + return + } + + curLink = link + curStyle = style + + addSpace() + curWidth += wordLen + buf.Write(word.Bytes()) + word.Reset() + wordLen = 0 + } + + addNewline := func() { + if !curStyle.Empty() { + buf.WriteString(ansi.ResetStyle) + } + if !curLink.Empty() { + buf.WriteString(ansi.ResetHyperlink()) + } + buf.WriteByte('\n') + if !curLink.Empty() { + buf.WriteString(ansi.SetHyperlink(curLink.URL, curLink.Params)) + } + if !curStyle.Empty() { + buf.WriteString(curStyle.Sequence()) + } + curWidth = 0 + space.Reset() + } + + var state byte + for len(s) > 0 { + seq, width, n, newState := ansi.DecodeSequence(s, state, p) + switch width { + case 0: + if ansi.Equal(seq, "\t") { + addWord() + space.WriteString(seq) + break + } else if ansi.Equal(seq, "\n") { + if wordLen == 0 { + if curWidth+space.Len() > limit { + curWidth = 0 + } else { + // preserve whitespaces + buf.Write(space.Bytes()) + } + space.Reset() + } + + addWord() + addNewline() + break + } else if ansi.HasCsiPrefix(seq) && p.Command() == 'm' { + // SGR style sequence [ansi.SGR] + ReadStyle(p.Params(), &style) + } else if ansi.HasOscPrefix(seq) && p.Command() == 8 { + // Hyperlink sequence [ansi.SetHyperlink] + ReadLink(p.Data(), &link) + } + + word.WriteString(seq) + default: + if len(seq) == 1 { + // ASCII + r, _ := utf8.DecodeRuneInString(seq) + if unicode.IsSpace(r) { + addWord() + space.WriteRune(r) + break + } else if r == '-' || runeContainsAny(r, breakpoints) { + addSpace() + if curWidth+wordLen+width <= limit { + addWord() + buf.WriteString(seq) + curWidth += width + break + } + } + } + + if wordLen+width > limit { + // Hardwrap the word if it's too long + addWord() + } + + word.WriteString(seq) + wordLen += width + + if curWidth+wordLen+space.Len() > limit { + addNewline() + } + } + + s = s[n:] + state = newState + } + + if wordLen == 0 { + if curWidth+space.Len() > limit { + curWidth = 0 + } else { + // preserve whitespaces + buf.Write(space.Bytes()) + } + space.Reset() + } + + addWord() + + if !curLink.Empty() { + buf.WriteString(ansi.ResetHyperlink()) + } + if !curStyle.Empty() { + buf.WriteString(ansi.ResetStyle) + } + + return buf.String() +} + +func runeContainsAny[T string | []rune](r rune, s T) bool { + for _, c := range []rune(s) { + if c == r { + return true + } + } + return false +} diff --git a/vendor/github.com/charmbracelet/x/cellbuf/writer.go b/vendor/github.com/charmbracelet/x/cellbuf/writer.go new file mode 100644 index 00000000..ae8b2a81 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/cellbuf/writer.go @@ -0,0 +1,339 @@ +package cellbuf + +import ( + "bytes" + "fmt" + "strings" + + "github.com/charmbracelet/x/ansi" +) + +// CellBuffer is a cell buffer that represents a set of cells in a screen or a +// grid. +type CellBuffer interface { + // Cell returns the cell at the given position. + Cell(x, y int) *Cell + // SetCell sets the cell at the given position to the given cell. It + // returns whether the cell was set successfully. + SetCell(x, y int, c *Cell) bool + // Bounds returns the bounds of the cell buffer. + Bounds() Rectangle +} + +// FillRect fills the rectangle within the cell buffer with the given cell. +// This will not fill cells outside the bounds of the cell buffer. +func FillRect(s CellBuffer, c *Cell, rect Rectangle) { + for y := rect.Min.Y; y < rect.Max.Y; y++ { + for x := rect.Min.X; x < rect.Max.X; x++ { + s.SetCell(x, y, c) //nolint:errcheck + } + } +} + +// Fill fills the cell buffer with the given cell. +func Fill(s CellBuffer, c *Cell) { + FillRect(s, c, s.Bounds()) +} + +// ClearRect clears the rectangle within the cell buffer with blank cells. +func ClearRect(s CellBuffer, rect Rectangle) { + FillRect(s, nil, rect) +} + +// Clear clears the cell buffer with blank cells. +func Clear(s CellBuffer) { + Fill(s, nil) +} + +// SetContentRect clears the rectangle within the cell buffer with blank cells, +// and sets the given string as its content. If the height or width of the +// string exceeds the height or width of the cell buffer, it will be truncated. +func SetContentRect(s CellBuffer, str string, rect Rectangle) { + // Replace all "\n" with "\r\n" to ensure the cursor is reset to the start + // of the line. Make sure we don't replace "\r\n" with "\r\r\n". + str = strings.ReplaceAll(str, "\r\n", "\n") + str = strings.ReplaceAll(str, "\n", "\r\n") + ClearRect(s, rect) + printString(s, ansi.GraphemeWidth, rect.Min.X, rect.Min.Y, rect, str, true, "") +} + +// SetContent clears the cell buffer with blank cells, and sets the given string +// as its content. If the height or width of the string exceeds the height or +// width of the cell buffer, it will be truncated. +func SetContent(s CellBuffer, str string) { + SetContentRect(s, str, s.Bounds()) +} + +// Render returns a string representation of the grid with ANSI escape sequences. +func Render(d CellBuffer) string { + var buf bytes.Buffer + height := d.Bounds().Dy() + for y := 0; y < height; y++ { + _, line := RenderLine(d, y) + buf.WriteString(line) + if y < height-1 { + buf.WriteString("\r\n") + } + } + return buf.String() +} + +// RenderLine returns a string representation of the yth line of the grid along +// with the width of the line. +func RenderLine(d CellBuffer, n int) (w int, line string) { + var pen Style + var link Link + var buf bytes.Buffer + var pendingLine string + var pendingWidth int // this ignores space cells until we hit a non-space cell + + writePending := func() { + // If there's no pending line, we don't need to do anything. + if len(pendingLine) == 0 { + return + } + buf.WriteString(pendingLine) + w += pendingWidth + pendingWidth = 0 + pendingLine = "" + } + + for x := 0; x < d.Bounds().Dx(); x++ { + if cell := d.Cell(x, n); cell != nil && cell.Width > 0 { + // Convert the cell's style and link to the given color profile. + cellStyle := cell.Style + cellLink := cell.Link + if cellStyle.Empty() && !pen.Empty() { + writePending() + buf.WriteString(ansi.ResetStyle) //nolint:errcheck + pen.Reset() + } + if !cellStyle.Equal(&pen) { + writePending() + seq := cellStyle.DiffSequence(pen) + buf.WriteString(seq) // nolint:errcheck + pen = cellStyle + } + + // Write the URL escape sequence + if cellLink != link && link.URL != "" { + writePending() + buf.WriteString(ansi.ResetHyperlink()) //nolint:errcheck + link.Reset() + } + if cellLink != link { + writePending() + buf.WriteString(ansi.SetHyperlink(cellLink.URL, cellLink.Params)) //nolint:errcheck + link = cellLink + } + + // We only write the cell content if it's not empty. If it is, we + // append it to the pending line and width to be evaluated later. + if cell.Equal(&BlankCell) { + pendingLine += cell.String() + pendingWidth += cell.Width + } else { + writePending() + buf.WriteString(cell.String()) + w += cell.Width + } + } + } + if link.URL != "" { + buf.WriteString(ansi.ResetHyperlink()) //nolint:errcheck + } + if !pen.Empty() { + buf.WriteString(ansi.ResetStyle) //nolint:errcheck + } + return w, strings.TrimRight(buf.String(), " ") // Trim trailing spaces +} + +// ScreenWriter represents a writer that writes to a [Screen] parsing ANSI +// escape sequences and Unicode characters and converting them into cells that +// can be written to a cell [Buffer]. +type ScreenWriter struct { + *Screen +} + +// NewScreenWriter creates a new ScreenWriter that writes to the given Screen. +// This is a convenience function for creating a ScreenWriter. +func NewScreenWriter(s *Screen) *ScreenWriter { + return &ScreenWriter{s} +} + +// Write writes the given bytes to the screen. +// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape +// sequences. +func (s *ScreenWriter) Write(p []byte) (n int, err error) { + printString(s.Screen, s.method, + s.cur.X, s.cur.Y, s.Bounds(), + p, false, "") + return len(p), nil +} + +// SetContent clears the screen with blank cells, and sets the given string as +// its content. If the height or width of the string exceeds the height or +// width of the screen, it will be truncated. +// +// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape sequences. +func (s *ScreenWriter) SetContent(str string) { + s.SetContentRect(str, s.Bounds()) +} + +// SetContentRect clears the rectangle within the screen with blank cells, and +// sets the given string as its content. If the height or width of the string +// exceeds the height or width of the screen, it will be truncated. +// +// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape +// sequences. +func (s *ScreenWriter) SetContentRect(str string, rect Rectangle) { + // Replace all "\n" with "\r\n" to ensure the cursor is reset to the start + // of the line. Make sure we don't replace "\r\n" with "\r\r\n". + str = strings.ReplaceAll(str, "\r\n", "\n") + str = strings.ReplaceAll(str, "\n", "\r\n") + s.ClearRect(rect) + printString(s.Screen, s.method, + rect.Min.X, rect.Min.Y, rect, + str, true, "") +} + +// Print prints the string at the current cursor position. It will wrap the +// string to the width of the screen if it exceeds the width of the screen. +// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape +// sequences. +func (s *ScreenWriter) Print(str string, v ...interface{}) { + if len(v) > 0 { + str = fmt.Sprintf(str, v...) + } + printString(s.Screen, s.method, + s.cur.X, s.cur.Y, s.Bounds(), + str, false, "") +} + +// PrintAt prints the string at the given position. It will wrap the string to +// the width of the screen if it exceeds the width of the screen. +// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape +// sequences. +func (s *ScreenWriter) PrintAt(x, y int, str string, v ...interface{}) { + if len(v) > 0 { + str = fmt.Sprintf(str, v...) + } + printString(s.Screen, s.method, + x, y, s.Bounds(), + str, false, "") +} + +// PrintCrop prints the string at the current cursor position and truncates the +// text if it exceeds the width of the screen. Use tail to specify a string to +// append if the string is truncated. +// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape +// sequences. +func (s *ScreenWriter) PrintCrop(str string, tail string) { + printString(s.Screen, s.method, + s.cur.X, s.cur.Y, s.Bounds(), + str, true, tail) +} + +// PrintCropAt prints the string at the given position and truncates the text +// if it exceeds the width of the screen. Use tail to specify a string to append +// if the string is truncated. +// This will recognize ANSI [ansi.SGR] style and [ansi.SetHyperlink] escape +// sequences. +func (s *ScreenWriter) PrintCropAt(x, y int, str string, tail string) { + printString(s.Screen, s.method, + x, y, s.Bounds(), + str, true, tail) +} + +// printString draws a string starting at the given position. +func printString[T []byte | string]( + s CellBuffer, + m ansi.Method, + x, y int, + bounds Rectangle, str T, + truncate bool, tail string, +) { + p := ansi.GetParser() + defer ansi.PutParser(p) + + var tailc Cell + if truncate && len(tail) > 0 { + if m == ansi.WcWidth { + tailc = *NewCellString(tail) + } else { + tailc = *NewGraphemeCell(tail) + } + } + + decoder := ansi.DecodeSequenceWc[T] + if m == ansi.GraphemeWidth { + decoder = ansi.DecodeSequence[T] + } + + var cell Cell + var style Style + var link Link + var state byte + for len(str) > 0 { + seq, width, n, newState := decoder(str, state, p) + + switch width { + case 1, 2, 3, 4: // wide cells can go up to 4 cells wide + cell.Width += width + cell.Append([]rune(string(seq))...) + + if !truncate && x+cell.Width > bounds.Max.X && y+1 < bounds.Max.Y { + // Wrap the string to the width of the window + x = bounds.Min.X + y++ + } + if Pos(x, y).In(bounds) { + if truncate && tailc.Width > 0 && x+cell.Width > bounds.Max.X-tailc.Width { + // Truncate the string and append the tail if any. + cell := tailc + cell.Style = style + cell.Link = link + s.SetCell(x, y, &cell) + x += tailc.Width + } else { + // Print the cell to the screen + cell.Style = style + cell.Link = link + s.SetCell(x, y, &cell) //nolint:errcheck + x += width + } + } + + // String is too long for the line, truncate it. + // Make sure we reset the cell for the next iteration. + cell.Reset() + default: + // Valid sequences always have a non-zero Cmd. + // TODO: Handle cursor movement and other sequences + switch { + case ansi.HasCsiPrefix(seq) && p.Command() == 'm': + // SGR - Select Graphic Rendition + ReadStyle(p.Params(), &style) + case ansi.HasOscPrefix(seq) && p.Command() == 8: + // Hyperlinks + ReadLink(p.Data(), &link) + case ansi.Equal(seq, T("\n")): + y++ + case ansi.Equal(seq, T("\r")): + x = bounds.Min.X + default: + cell.Append([]rune(string(seq))...) + } + } + + // Advance the state and data + state = newState + str = str[n:] + } + + // Make sure to set the last cell if it's not empty. + if !cell.Empty() { + s.SetCell(x, y, &cell) //nolint:errcheck + cell.Reset() + } +} diff --git a/vendor/github.com/charmbracelet/x/term/LICENSE b/vendor/github.com/charmbracelet/x/term/LICENSE new file mode 100644 index 00000000..65a5654e --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2023 Charmbracelet, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/charmbracelet/x/term/term.go b/vendor/github.com/charmbracelet/x/term/term.go new file mode 100644 index 00000000..58d6522c --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/term.go @@ -0,0 +1,49 @@ +package term + +// State contains platform-specific state of a terminal. +type State struct { + state +} + +// IsTerminal returns whether the given file descriptor is a terminal. +func IsTerminal(fd uintptr) bool { + return isTerminal(fd) +} + +// MakeRaw puts the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd uintptr) (*State, error) { + return makeRaw(fd) +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd uintptr) (*State, error) { + return getState(fd) +} + +// SetState sets the given state of the terminal. +func SetState(fd uintptr, state *State) error { + return setState(fd, state) +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd uintptr, oldState *State) error { + return restore(fd, oldState) +} + +// GetSize returns the visible dimensions of the given terminal. +// +// These dimensions don't include any scrollback buffer height. +func GetSize(fd uintptr) (width, height int, err error) { + return getSize(fd) +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd uintptr) ([]byte, error) { + return readPassword(fd) +} diff --git a/vendor/github.com/charmbracelet/x/term/term_other.go b/vendor/github.com/charmbracelet/x/term/term_other.go new file mode 100644 index 00000000..092c7e9d --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/term_other.go @@ -0,0 +1,39 @@ +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !zos && !windows && !solaris && !plan9 +// +build !aix,!darwin,!dragonfly,!freebsd,!linux,!netbsd,!openbsd,!zos,!windows,!solaris,!plan9 + +package term + +import ( + "fmt" + "runtime" +) + +type state struct{} + +func isTerminal(fd uintptr) bool { + return false +} + +func makeRaw(fd uintptr) (*State, error) { + return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func getState(fd uintptr) (*State, error) { + return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func restore(fd uintptr, state *State) error { + return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func getSize(fd uintptr) (width, height int, err error) { + return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func setState(fd uintptr, state *State) error { + return fmt.Errorf("terminal: SetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func readPassword(fd uintptr) ([]byte, error) { + return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} diff --git a/vendor/github.com/charmbracelet/x/term/term_unix.go b/vendor/github.com/charmbracelet/x/term/term_unix.go new file mode 100644 index 00000000..1459cb1b --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/term_unix.go @@ -0,0 +1,96 @@ +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos +// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris zos + +package term + +import ( + "golang.org/x/sys/unix" +) + +type state struct { + unix.Termios +} + +func isTerminal(fd uintptr) bool { + _, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios) + return err == nil +} + +func makeRaw(fd uintptr) (*State, error) { + termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios) + if err != nil { + return nil, err + } + + oldState := State{state{Termios: *termios}} + + // This attempts to replicate the behaviour documented for cfmakeraw in + // the termios(3) manpage. + termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON + termios.Oflag &^= unix.OPOST + termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN + termios.Cflag &^= unix.CSIZE | unix.PARENB + termios.Cflag |= unix.CS8 + termios.Cc[unix.VMIN] = 1 + termios.Cc[unix.VTIME] = 0 + if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios); err != nil { + return nil, err + } + + return &oldState, nil +} + +func setState(fd uintptr, state *State) error { + var termios *unix.Termios + if state != nil { + termios = &state.Termios + } + return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios) +} + +func getState(fd uintptr) (*State, error) { + termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios) + if err != nil { + return nil, err + } + + return &State{state{Termios: *termios}}, nil +} + +func restore(fd uintptr, state *State) error { + return unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &state.Termios) +} + +func getSize(fd uintptr) (width, height int, err error) { + ws, err := unix.IoctlGetWinsize(int(fd), unix.TIOCGWINSZ) + if err != nil { + return 0, 0, err + } + return int(ws.Col), int(ws.Row), nil +} + +// passwordReader is an io.Reader that reads from a specific file descriptor. +type passwordReader int + +func (r passwordReader) Read(buf []byte) (int, error) { + return unix.Read(int(r), buf) +} + +func readPassword(fd uintptr) ([]byte, error) { + termios, err := unix.IoctlGetTermios(int(fd), ioctlReadTermios) + if err != nil { + return nil, err + } + + newState := *termios + newState.Lflag &^= unix.ECHO + newState.Lflag |= unix.ICANON | unix.ISIG + newState.Iflag |= unix.ICRNL + if err := unix.IoctlSetTermios(int(fd), ioctlWriteTermios, &newState); err != nil { + return nil, err + } + + defer unix.IoctlSetTermios(int(fd), ioctlWriteTermios, termios) + + return readPasswordLine(passwordReader(fd)) +} diff --git a/vendor/github.com/charmbracelet/x/term/term_unix_bsd.go b/vendor/github.com/charmbracelet/x/term/term_unix_bsd.go new file mode 100644 index 00000000..b435031a --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/term_unix_bsd.go @@ -0,0 +1,11 @@ +//go:build darwin || dragonfly || freebsd || netbsd || openbsd +// +build darwin dragonfly freebsd netbsd openbsd + +package term + +import "golang.org/x/sys/unix" + +const ( + ioctlReadTermios = unix.TIOCGETA + ioctlWriteTermios = unix.TIOCSETA +) diff --git a/vendor/github.com/charmbracelet/x/term/term_unix_other.go b/vendor/github.com/charmbracelet/x/term/term_unix_other.go new file mode 100644 index 00000000..ee2a29eb --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/term_unix_other.go @@ -0,0 +1,11 @@ +//go:build aix || linux || solaris || zos +// +build aix linux solaris zos + +package term + +import "golang.org/x/sys/unix" + +const ( + ioctlReadTermios = unix.TCGETS + ioctlWriteTermios = unix.TCSETS +) diff --git a/vendor/github.com/charmbracelet/x/term/term_windows.go b/vendor/github.com/charmbracelet/x/term/term_windows.go new file mode 100644 index 00000000..fe7afdec --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/term_windows.go @@ -0,0 +1,87 @@ +//go:build windows +// +build windows + +package term + +import ( + "os" + + "golang.org/x/sys/windows" +) + +type state struct { + Mode uint32 +} + +func isTerminal(fd uintptr) bool { + var st uint32 + err := windows.GetConsoleMode(windows.Handle(fd), &st) + return err == nil +} + +func makeRaw(fd uintptr) (*State, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT + if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { + return nil, err + } + return &State{state{st}}, nil +} + +func setState(fd uintptr, state *State) error { + var mode uint32 + if state != nil { + mode = state.Mode + } + return windows.SetConsoleMode(windows.Handle(fd), mode) +} + +func getState(fd uintptr) (*State, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + return &State{state{st}}, nil +} + +func restore(fd uintptr, state *State) error { + return windows.SetConsoleMode(windows.Handle(fd), state.Mode) +} + +func getSize(fd uintptr) (width, height int, err error) { + var info windows.ConsoleScreenBufferInfo + if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { + return 0, 0, err + } + return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil +} + +func readPassword(fd uintptr) ([]byte, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + old := st + + st &^= (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT) + st |= (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_PROCESSED_INPUT) + if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { + return nil, err + } + + defer windows.SetConsoleMode(windows.Handle(fd), old) + + var h windows.Handle + p, _ := windows.GetCurrentProcess() + if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { + return nil, err + } + + f := os.NewFile(uintptr(h), "stdin") + defer f.Close() + return readPasswordLine(f) +} diff --git a/vendor/github.com/charmbracelet/x/term/terminal.go b/vendor/github.com/charmbracelet/x/term/terminal.go new file mode 100644 index 00000000..8963163f --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/terminal.go @@ -0,0 +1,12 @@ +package term + +import ( + "io" +) + +// File represents a file that has a file descriptor and can be read from, +// written to, and closed. +type File interface { + io.ReadWriteCloser + Fd() uintptr +} diff --git a/vendor/github.com/charmbracelet/x/term/util.go b/vendor/github.com/charmbracelet/x/term/util.go new file mode 100644 index 00000000..b7313418 --- /dev/null +++ b/vendor/github.com/charmbracelet/x/term/util.go @@ -0,0 +1,47 @@ +package term + +import ( + "io" + "runtime" +) + +// readPasswordLine reads from reader until it finds \n or io.EOF. +// The slice returned does not include the \n. +// readPasswordLine also ignores any \r it finds. +// Windows uses \r as end of line. So, on Windows, readPasswordLine +// reads until it finds \r and ignores any \n it finds during processing. +func readPasswordLine(reader io.Reader) ([]byte, error) { + var buf [1]byte + var ret []byte + + for { + n, err := reader.Read(buf[:]) + if n > 0 { + switch buf[0] { + case '\b': + if len(ret) > 0 { + ret = ret[:len(ret)-1] + } + case '\n': + if runtime.GOOS != "windows" { + return ret, nil + } + // otherwise ignore \n + case '\r': + if runtime.GOOS == "windows" { + return ret, nil + } + // otherwise ignore \r + default: + ret = append(ret, buf[0]) + } + continue + } + if err != nil { + if err == io.EOF && len(ret) > 0 { + return ret, nil + } + return ret, err + } + } +} diff --git a/vendor/github.com/erikgeiser/coninput/.gitignore b/vendor/github.com/erikgeiser/coninput/.gitignore new file mode 100644 index 00000000..66fd13c9 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/erikgeiser/coninput/.golangci.yml b/vendor/github.com/erikgeiser/coninput/.golangci.yml new file mode 100644 index 00000000..d3ed7103 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/.golangci.yml @@ -0,0 +1,24 @@ +linters: + enable-all: true + disable: + - golint + - interfacer + - scopelint + - maligned + - rowserrcheck + - funlen + - depguard + - goerr113 + - exhaustivestruct + - testpackage + - gochecknoglobals + - wrapcheck + - forbidigo + - ifshort + - cyclop + - gomoddirectives +linters-settings: + exhaustive: + default-signifies-exhaustive: true +issues: + exclude-use-default: false diff --git a/vendor/github.com/erikgeiser/coninput/LICENSE b/vendor/github.com/erikgeiser/coninput/LICENSE new file mode 100644 index 00000000..83c24408 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Erik G. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/erikgeiser/coninput/README.md b/vendor/github.com/erikgeiser/coninput/README.md new file mode 100644 index 00000000..22619d13 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/README.md @@ -0,0 +1,2 @@ +# coninput +Go library for input handling using Windows Console API diff --git a/vendor/github.com/erikgeiser/coninput/keycodes.go b/vendor/github.com/erikgeiser/coninput/keycodes.go new file mode 100644 index 00000000..902ee1b7 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/keycodes.go @@ -0,0 +1,205 @@ +package coninput + +// VirtualKeyCode holds a virtual key code (see +// https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes). +type VirtualKeyCode uint16 + +const ( + VK_LBUTTON VirtualKeyCode = 0x01 + VK_RBUTTON VirtualKeyCode = 0x02 + VK_CANCEL VirtualKeyCode = 0x03 + VK_MBUTTON VirtualKeyCode = 0x04 + VK_XBUTTON1 VirtualKeyCode = 0x05 + VK_XBUTTON2 VirtualKeyCode = 0x06 + VK_BACK VirtualKeyCode = 0x08 + VK_TAB VirtualKeyCode = 0x09 + VK_CLEAR VirtualKeyCode = 0x0C + VK_RETURN VirtualKeyCode = 0x0D + VK_SHIFT VirtualKeyCode = 0x10 + VK_CONTROL VirtualKeyCode = 0x11 + VK_MENU VirtualKeyCode = 0x12 + VK_PAUSE VirtualKeyCode = 0x13 + VK_CAPITAL VirtualKeyCode = 0x14 + VK_KANA VirtualKeyCode = 0x15 + VK_HANGEUL VirtualKeyCode = 0x15 + VK_HANGUL VirtualKeyCode = 0x15 + VK_IME_ON VirtualKeyCode = 0x16 + VK_JUNJA VirtualKeyCode = 0x17 + VK_FINAL VirtualKeyCode = 0x18 + VK_HANJA VirtualKeyCode = 0x19 + VK_KANJI VirtualKeyCode = 0x19 + VK_IME_OFF VirtualKeyCode = 0x1A + VK_ESCAPE VirtualKeyCode = 0x1B + VK_CONVERT VirtualKeyCode = 0x1C + VK_NONCONVERT VirtualKeyCode = 0x1D + VK_ACCEPT VirtualKeyCode = 0x1E + VK_MODECHANGE VirtualKeyCode = 0x1F + VK_SPACE VirtualKeyCode = 0x20 + VK_PRIOR VirtualKeyCode = 0x21 + VK_NEXT VirtualKeyCode = 0x22 + VK_END VirtualKeyCode = 0x23 + VK_HOME VirtualKeyCode = 0x24 + VK_LEFT VirtualKeyCode = 0x25 + VK_UP VirtualKeyCode = 0x26 + VK_RIGHT VirtualKeyCode = 0x27 + VK_DOWN VirtualKeyCode = 0x28 + VK_SELECT VirtualKeyCode = 0x29 + VK_PRINT VirtualKeyCode = 0x2A + VK_EXECUTE VirtualKeyCode = 0x2B + VK_SNAPSHOT VirtualKeyCode = 0x2C + VK_INSERT VirtualKeyCode = 0x2D + VK_DELETE VirtualKeyCode = 0x2E + VK_HELP VirtualKeyCode = 0x2F + VK_0 VirtualKeyCode = 0x30 + VK_1 VirtualKeyCode = 0x31 + VK_2 VirtualKeyCode = 0x32 + VK_3 VirtualKeyCode = 0x33 + VK_4 VirtualKeyCode = 0x34 + VK_5 VirtualKeyCode = 0x35 + VK_6 VirtualKeyCode = 0x36 + VK_7 VirtualKeyCode = 0x37 + VK_8 VirtualKeyCode = 0x38 + VK_9 VirtualKeyCode = 0x39 + VK_A VirtualKeyCode = 0x41 + VK_B VirtualKeyCode = 0x42 + VK_C VirtualKeyCode = 0x43 + VK_D VirtualKeyCode = 0x44 + VK_E VirtualKeyCode = 0x45 + VK_F VirtualKeyCode = 0x46 + VK_G VirtualKeyCode = 0x47 + VK_H VirtualKeyCode = 0x48 + VK_I VirtualKeyCode = 0x49 + VK_J VirtualKeyCode = 0x4A + VK_K VirtualKeyCode = 0x4B + VK_L VirtualKeyCode = 0x4C + VK_M VirtualKeyCode = 0x4D + VK_N VirtualKeyCode = 0x4E + VK_O VirtualKeyCode = 0x4F + VK_P VirtualKeyCode = 0x50 + VK_Q VirtualKeyCode = 0x51 + VK_R VirtualKeyCode = 0x52 + VK_S VirtualKeyCode = 0x53 + VK_T VirtualKeyCode = 0x54 + VK_U VirtualKeyCode = 0x55 + VK_V VirtualKeyCode = 0x56 + VK_W VirtualKeyCode = 0x57 + VK_X VirtualKeyCode = 0x58 + VK_Y VirtualKeyCode = 0x59 + VK_Z VirtualKeyCode = 0x5A + VK_LWIN VirtualKeyCode = 0x5B + VK_RWIN VirtualKeyCode = 0x5C + VK_APPS VirtualKeyCode = 0x5D + VK_SLEEP VirtualKeyCode = 0x5F + VK_NUMPAD0 VirtualKeyCode = 0x60 + VK_NUMPAD1 VirtualKeyCode = 0x61 + VK_NUMPAD2 VirtualKeyCode = 0x62 + VK_NUMPAD3 VirtualKeyCode = 0x63 + VK_NUMPAD4 VirtualKeyCode = 0x64 + VK_NUMPAD5 VirtualKeyCode = 0x65 + VK_NUMPAD6 VirtualKeyCode = 0x66 + VK_NUMPAD7 VirtualKeyCode = 0x67 + VK_NUMPAD8 VirtualKeyCode = 0x68 + VK_NUMPAD9 VirtualKeyCode = 0x69 + VK_MULTIPLY VirtualKeyCode = 0x6A + VK_ADD VirtualKeyCode = 0x6B + VK_SEPARATOR VirtualKeyCode = 0x6C + VK_SUBTRACT VirtualKeyCode = 0x6D + VK_DECIMAL VirtualKeyCode = 0x6E + VK_DIVIDE VirtualKeyCode = 0x6F + VK_F1 VirtualKeyCode = 0x70 + VK_F2 VirtualKeyCode = 0x71 + VK_F3 VirtualKeyCode = 0x72 + VK_F4 VirtualKeyCode = 0x73 + VK_F5 VirtualKeyCode = 0x74 + VK_F6 VirtualKeyCode = 0x75 + VK_F7 VirtualKeyCode = 0x76 + VK_F8 VirtualKeyCode = 0x77 + VK_F9 VirtualKeyCode = 0x78 + VK_F10 VirtualKeyCode = 0x79 + VK_F11 VirtualKeyCode = 0x7A + VK_F12 VirtualKeyCode = 0x7B + VK_F13 VirtualKeyCode = 0x7C + VK_F14 VirtualKeyCode = 0x7D + VK_F15 VirtualKeyCode = 0x7E + VK_F16 VirtualKeyCode = 0x7F + VK_F17 VirtualKeyCode = 0x80 + VK_F18 VirtualKeyCode = 0x81 + VK_F19 VirtualKeyCode = 0x82 + VK_F20 VirtualKeyCode = 0x83 + VK_F21 VirtualKeyCode = 0x84 + VK_F22 VirtualKeyCode = 0x85 + VK_F23 VirtualKeyCode = 0x86 + VK_F24 VirtualKeyCode = 0x87 + VK_NUMLOCK VirtualKeyCode = 0x90 + VK_SCROLL VirtualKeyCode = 0x91 + VK_OEM_NEC_EQUAL VirtualKeyCode = 0x92 + VK_OEM_FJ_JISHO VirtualKeyCode = 0x92 + VK_OEM_FJ_MASSHOU VirtualKeyCode = 0x93 + VK_OEM_FJ_TOUROKU VirtualKeyCode = 0x94 + VK_OEM_FJ_LOYA VirtualKeyCode = 0x95 + VK_OEM_FJ_ROYA VirtualKeyCode = 0x96 + VK_LSHIFT VirtualKeyCode = 0xA0 + VK_RSHIFT VirtualKeyCode = 0xA1 + VK_LCONTROL VirtualKeyCode = 0xA2 + VK_RCONTROL VirtualKeyCode = 0xA3 + VK_LMENU VirtualKeyCode = 0xA4 + VK_RMENU VirtualKeyCode = 0xA5 + VK_BROWSER_BACK VirtualKeyCode = 0xA6 + VK_BROWSER_FORWARD VirtualKeyCode = 0xA7 + VK_BROWSER_REFRESH VirtualKeyCode = 0xA8 + VK_BROWSER_STOP VirtualKeyCode = 0xA9 + VK_BROWSER_SEARCH VirtualKeyCode = 0xAA + VK_BROWSER_FAVORITES VirtualKeyCode = 0xAB + VK_BROWSER_HOME VirtualKeyCode = 0xAC + VK_VOLUME_MUTE VirtualKeyCode = 0xAD + VK_VOLUME_DOWN VirtualKeyCode = 0xAE + VK_VOLUME_UP VirtualKeyCode = 0xAF + VK_MEDIA_NEXT_TRACK VirtualKeyCode = 0xB0 + VK_MEDIA_PREV_TRACK VirtualKeyCode = 0xB1 + VK_MEDIA_STOP VirtualKeyCode = 0xB2 + VK_MEDIA_PLAY_PAUSE VirtualKeyCode = 0xB3 + VK_LAUNCH_MAIL VirtualKeyCode = 0xB4 + VK_LAUNCH_MEDIA_SELECT VirtualKeyCode = 0xB5 + VK_LAUNCH_APP1 VirtualKeyCode = 0xB6 + VK_LAUNCH_APP2 VirtualKeyCode = 0xB7 + VK_OEM_1 VirtualKeyCode = 0xBA + VK_OEM_PLUS VirtualKeyCode = 0xBB + VK_OEM_COMMA VirtualKeyCode = 0xBC + VK_OEM_MINUS VirtualKeyCode = 0xBD + VK_OEM_PERIOD VirtualKeyCode = 0xBE + VK_OEM_2 VirtualKeyCode = 0xBF + VK_OEM_3 VirtualKeyCode = 0xC0 + VK_OEM_4 VirtualKeyCode = 0xDB + VK_OEM_5 VirtualKeyCode = 0xDC + VK_OEM_6 VirtualKeyCode = 0xDD + VK_OEM_7 VirtualKeyCode = 0xDE + VK_OEM_8 VirtualKeyCode = 0xDF + VK_OEM_AX VirtualKeyCode = 0xE1 + VK_OEM_102 VirtualKeyCode = 0xE2 + VK_ICO_HELP VirtualKeyCode = 0xE3 + VK_ICO_00 VirtualKeyCode = 0xE4 + VK_PROCESSKEY VirtualKeyCode = 0xE5 + VK_ICO_CLEAR VirtualKeyCode = 0xE6 + VK_OEM_RESET VirtualKeyCode = 0xE9 + VK_OEM_JUMP VirtualKeyCode = 0xEA + VK_OEM_PA1 VirtualKeyCode = 0xEB + VK_OEM_PA2 VirtualKeyCode = 0xEC + VK_OEM_PA3 VirtualKeyCode = 0xED + VK_OEM_WSCTRL VirtualKeyCode = 0xEE + VK_OEM_CUSEL VirtualKeyCode = 0xEF + VK_OEM_ATTN VirtualKeyCode = 0xF0 + VK_OEM_FINISH VirtualKeyCode = 0xF1 + VK_OEM_COPY VirtualKeyCode = 0xF2 + VK_OEM_AUTO VirtualKeyCode = 0xF3 + VK_OEM_ENLW VirtualKeyCode = 0xF4 + VK_OEM_BACKTAB VirtualKeyCode = 0xF5 + VK_ATTN VirtualKeyCode = 0xF6 + VK_CRSEL VirtualKeyCode = 0xF7 + VK_EXSEL VirtualKeyCode = 0xF8 + VK_EREOF VirtualKeyCode = 0xF9 + VK_PLAY VirtualKeyCode = 0xFA + VK_ZOOM VirtualKeyCode = 0xFB + VK_NONAME VirtualKeyCode = 0xFC + VK_PA1 VirtualKeyCode = 0xFD + VK_OEM_CLEAR VirtualKeyCode = 0xFE +) diff --git a/vendor/github.com/erikgeiser/coninput/mode.go b/vendor/github.com/erikgeiser/coninput/mode.go new file mode 100644 index 00000000..e6d8bf44 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/mode.go @@ -0,0 +1,82 @@ +//go:build windows +// +build windows + +package coninput + +import ( + "strings" + + "golang.org/x/sys/windows" +) + +// AddInputModes returns the given mode with one or more additional modes enabled. +func AddInputModes(mode uint32, enableModes ...uint32) uint32 { + for _, enableMode := range enableModes { + mode |= enableMode + } + + return mode +} + +// RemoveInputModes returns the given mode with one or more additional modes disabled. +func RemoveInputModes(mode uint32, disableModes ...uint32) uint32 { + for _, disableMode := range disableModes { + mode &^= disableMode + } + + return mode +} + +// ToggleInputModes returns the given mode with one or more additional modes toggeled. +func ToggleInputModes(mode uint32, toggleModes ...uint32) uint32 { + for _, toggeMode := range toggleModes { + mode ^= toggeMode + } + + return mode +} + +var inputModes = []struct { + mode uint32 + name string +}{ + {mode: windows.ENABLE_ECHO_INPUT, name: "ENABLE_ECHO_INPUT"}, + {mode: windows.ENABLE_INSERT_MODE, name: "ENABLE_INSERT_MODE"}, + {mode: windows.ENABLE_LINE_INPUT, name: "ENABLE_LINE_INPUT"}, + {mode: windows.ENABLE_MOUSE_INPUT, name: "ENABLE_MOUSE_INPUT"}, + {mode: windows.ENABLE_PROCESSED_INPUT, name: "ENABLE_PROCESSED_INPUT"}, + {mode: windows.ENABLE_QUICK_EDIT_MODE, name: "ENABLE_QUICK_EDIT_MODE"}, + {mode: windows.ENABLE_WINDOW_INPUT, name: "ENABLE_WINDOW_INPUT"}, + {mode: windows.ENABLE_VIRTUAL_TERMINAL_INPUT, name: "ENABLE_VIRTUAL_TERMINAL_INPUT"}, +} + +// ListInputMode returnes the isolated enabled input modes as a list. +func ListInputModes(mode uint32) []uint32 { + modes := []uint32{} + + for _, inputMode := range inputModes { + if mode&inputMode.mode > 0 { + modes = append(modes, inputMode.mode) + } + } + + return modes +} + +// ListInputMode returnes the isolated enabled input mode names as a list. +func ListInputModeNames(mode uint32) []string { + modes := []string{} + + for _, inputMode := range inputModes { + if mode&inputMode.mode > 0 { + modes = append(modes, inputMode.name) + } + } + + return modes +} + +// DescribeInputMode returns a string containing the names of each enabled input mode. +func DescribeInputMode(mode uint32) string { + return strings.Join(ListInputModeNames(mode), "|") +} diff --git a/vendor/github.com/erikgeiser/coninput/read.go b/vendor/github.com/erikgeiser/coninput/read.go new file mode 100644 index 00000000..b2dd82f1 --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/read.go @@ -0,0 +1,154 @@ +//go:build windows +// +build windows + +package coninput + +import ( + "fmt" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var ( + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + procReadConsoleInputW = modkernel32.NewProc("ReadConsoleInputW") + procPeekConsoleInputW = modkernel32.NewProc("PeekConsoleInputW") + procGetNumberOfConsoleInputEvents = modkernel32.NewProc("GetNumberOfConsoleInputEvents") + procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer") +) + +// NewStdinHandle is a shortcut for windows.GetStdHandle(windows.STD_INPUT_HANDLE). +func NewStdinHandle() (windows.Handle, error) { + return windows.GetStdHandle(windows.STD_INPUT_HANDLE) +} + +// WinReadConsoleInput is a thin wrapper around the Windows console API function +// ReadConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). In most +// cases it is more practical to either use ReadConsoleInput or +// ReadNConsoleInputs. +func WinReadConsoleInput(consoleInput windows.Handle, buffer *InputRecord, + length uint32, numberOfEventsRead *uint32) error { + r, _, e := syscall.Syscall6(procReadConsoleInputW.Addr(), 4, + uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length), + uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0) + if r == 0 { + return error(e) + } + + return nil +} + +// ReadNConsoleInputs is a wrapper around ReadConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/readconsoleinput) that +// automates the event buffer allocation in oder to provide io.Reader-like +// sematics. maxEvents must be greater than zero. +func ReadNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) { + if maxEvents == 0 { + return nil, fmt.Errorf("maxEvents cannot be zero") + } + + var inputRecords = make([]InputRecord, maxEvents) + n, err := ReadConsoleInput(console, inputRecords) + + return inputRecords[:n], err +} + +// ReadConsoleInput provides an ideomatic interface to the Windows console API +// function ReadConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/readconsoleinput). The size +// of inputRecords must be greater than zero. +func ReadConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) { + if len(inputRecords) == 0 { + return 0, fmt.Errorf("size of input record buffer cannot be zero") + } + + var read uint32 + err := WinReadConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read) + + return read, err +} + +// WinPeekConsoleInput is a thin wrapper around the Windows console API function +// PeekConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). In most +// cases it is more practical to either use PeekConsoleInput or +// PeekNConsoleInputs. +func WinPeekConsoleInput(consoleInput windows.Handle, buffer *InputRecord, + length uint32, numberOfEventsRead *uint32) error { + r, _, e := syscall.Syscall6(procPeekConsoleInputW.Addr(), 4, + uintptr(consoleInput), uintptr(unsafe.Pointer(buffer)), uintptr(length), + uintptr(unsafe.Pointer(numberOfEventsRead)), 0, 0) + if r == 0 { + return error(e) + } + + return nil + +} + +// PeekNConsoleInputs is a wrapper around PeekConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput) that +// automates the event buffer allocation in oder to provide io.Reader-like +// sematics. maxEvents must be greater than zero. +func PeekNConsoleInputs(console windows.Handle, maxEvents uint32) ([]InputRecord, error) { + if maxEvents == 0 { + return nil, fmt.Errorf("maxEvents cannot be zero") + } + + var inputRecords = make([]InputRecord, maxEvents) + n, err := PeekConsoleInput(console, inputRecords) + + return inputRecords[:n], err +} + +// PeekConsoleInput provides an ideomatic interface to the Windows console API +// function PeekConsoleInput (see +// https://docs.microsoft.com/en-us/windows/console/peekconsoleinput). The size +// of inputRecords must be greater than zero. +func PeekConsoleInput(console windows.Handle, inputRecords []InputRecord) (uint32, error) { + if len(inputRecords) == 0 { + return 0, fmt.Errorf("size of input record buffer cannot be zero") + } + + var read uint32 + + err := WinPeekConsoleInput(console, &inputRecords[0], uint32(len(inputRecords)), &read) + + return read, err +} + +// WinGetNumberOfConsoleInputEvents provides an ideomatic interface to the +// Windows console API function GetNumberOfConsoleInputEvents (see +// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents). +func WinGetNumberOfConsoleInputEvents(consoleInput windows.Handle, numberOfEvents *uint32) error { + r, _, e := syscall.Syscall6(procGetNumberOfConsoleInputEvents.Addr(), 2, + uintptr(consoleInput), uintptr(unsafe.Pointer(numberOfEvents)), 0, + 0, 0, 0) + if r == 0 { + return error(e) + } + + return nil +} + +// GetNumberOfConsoleInputEvents provides an ideomatic interface to the Windows +// console API function GetNumberOfConsoleInputEvents (see +// https://docs.microsoft.com/en-us/windows/console/getnumberofconsoleinputevents). +func GetNumberOfConsoleInputEvents(console windows.Handle) (uint32, error) { + var nEvents uint32 + err := WinGetNumberOfConsoleInputEvents(console, &nEvents) + + return nEvents, err +} + +func FlushConsoleInputBuffer(consoleInput windows.Handle) error { + r, _, e := syscall.Syscall(procFlushConsoleInputBuffer.Addr(), 1, uintptr(consoleInput), 0, 0) + if r == 0 { + return error(e) + } + + return nil +} diff --git a/vendor/github.com/erikgeiser/coninput/records.go b/vendor/github.com/erikgeiser/coninput/records.go new file mode 100644 index 00000000..cccf7fbf --- /dev/null +++ b/vendor/github.com/erikgeiser/coninput/records.go @@ -0,0 +1,486 @@ +package coninput + +import ( + "encoding/binary" + "fmt" + "strconv" + "strings" +) + +const ( + maxEventSize = 16 + wordPaddingBytes = 2 +) + +// EventType denots the type of an event +type EventType uint16 + +// EventUnion is the union data type that contains the data for any event. +type EventUnion [maxEventSize]byte + +// InputRecord corresponds to the INPUT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +type InputRecord struct { + // EventType specifies the type of event that helt in Event. + EventType EventType + + // Padding of the 16-bit EventType to a whole 32-bit dword. + _ [wordPaddingBytes]byte + + // Event holds the actual event data. Use Unrap to access it as its + // respective event type. + Event EventUnion +} + +// String implements fmt.Stringer for InputRecord. +func (ir InputRecord) String() string { + return ir.Unwrap().String() +} + +// Unwrap parses the event data into an EventRecord of the respective event +// type. The data in the returned EventRecord does not contain any references to +// the passed InputRecord. +func (ir InputRecord) Unwrap() EventRecord { + switch ir.EventType { + case FocusEventType: + return FocusEventRecord{SetFocus: ir.Event[0] > 0} + case KeyEventType: + return KeyEventRecord{ + KeyDown: binary.LittleEndian.Uint32(ir.Event[0:4]) > 0, + RepeatCount: binary.LittleEndian.Uint16(ir.Event[4:6]), + VirtualKeyCode: VirtualKeyCode(binary.LittleEndian.Uint16(ir.Event[6:8])), + VirtualScanCode: VirtualKeyCode(binary.LittleEndian.Uint16(ir.Event[8:10])), + Char: rune(binary.LittleEndian.Uint16(ir.Event[10:12])), + ControlKeyState: ControlKeyState(binary.LittleEndian.Uint32(ir.Event[12:16])), + } + case MouseEventType: + m := MouseEventRecord{ + MousePositon: Coord{ + X: binary.LittleEndian.Uint16(ir.Event[0:2]), + Y: binary.LittleEndian.Uint16(ir.Event[2:4]), + }, + ButtonState: ButtonState(binary.LittleEndian.Uint32(ir.Event[4:8])), + ControlKeyState: ControlKeyState(binary.LittleEndian.Uint32(ir.Event[8:12])), + EventFlags: EventFlags(binary.LittleEndian.Uint32(ir.Event[12:16])), + } + + if (m.EventFlags&MOUSE_WHEELED > 0) || (m.EventFlags&MOUSE_HWHEELED > 0) { + if int16(highWord(uint32(m.ButtonState))) > 0 { + m.WheelDirection = 1 + } else { + m.WheelDirection = -1 + } + } + + return m + case WindowBufferSizeEventType: + return WindowBufferSizeEventRecord{ + Size: Coord{ + X: binary.LittleEndian.Uint16(ir.Event[0:2]), + Y: binary.LittleEndian.Uint16(ir.Event[2:4]), + }, + } + case MenuEventType: + return MenuEventRecord{ + CommandID: binary.LittleEndian.Uint32(ir.Event[0:4]), + } + default: + return &UnknownEvent{InputRecord: ir} + } +} + +// EventRecord represents one of the following event types: +// TypeFocusEventRecord, TypeKeyEventRecord, TypeMouseEventRecord, +// TypeWindowBufferSizeEvent, TypeMenuEventRecord and UnknownEvent. +type EventRecord interface { + Type() string + fmt.Stringer +} + +// FocusEventType is the event type for a FocusEventRecord (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +const FocusEventType EventType = 0x0010 + +// FocusEventRecord represent the FOCUS_EVENT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/focus-event-record-str). +// These events are used internally by the Windows console API and should be +// ignored. +type FocusEventRecord struct { + // SetFocus is reserved and should not be used. + SetFocus bool +} + +// Ensure that FocusEventRecord satisfies EventRecord interface. +var _ EventRecord = FocusEventRecord{} + +// Type ensures that FocusEventRecord satisfies EventRecord interface. +func (e FocusEventRecord) Type() string { return "FocusEvent" } + +// String ensures that FocusEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e FocusEventRecord) String() string { return fmt.Sprintf("%s[%v]", e.Type(), e.SetFocus) } + +// KeyEventType is the event type for a KeyEventRecord (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +const KeyEventType EventType = 0x0001 + +// KeyEventRecord represent the KEY_EVENT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/key-event-record-str). +type KeyEventRecord struct { + // KeyDown specified whether the key is pressed or released. + KeyDown bool + + // RepeatCount indicates that a key is being held down. For example, when a + // key is held down, five events with RepeatCount equal to 1 may be + // generated, one event with RepeatCount equal to 5, or multiple events + // with RepeatCount greater than or equal to 1. + RepeatCount uint16 + + // VirtualKeyCode identifies the given key in a device-independent manner + // (see + // https://docs.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes). + VirtualKeyCode VirtualKeyCode + + // VirtualScanCode represents the device-dependent value generated by the + // keyboard hardware. + VirtualScanCode VirtualKeyCode + + // Char is the character that corresponds to the pressed key. Char can be + // zero for some keys. + Char rune + + //ControlKeyState holds the state of the control keys. + ControlKeyState ControlKeyState +} + +// Ensure that KeyEventRecord satisfies EventRecord interface. +var _ EventRecord = KeyEventRecord{} + +// Type ensures that KeyEventRecord satisfies EventRecord interface. +func (e KeyEventRecord) Type() string { return "KeyEvent" } + +// String ensures that KeyEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e KeyEventRecord) String() string { + infos := []string{} + + repeat := "" + if e.RepeatCount > 1 { + repeat = "x" + strconv.Itoa(int(e.RepeatCount)) + } + + infos = append(infos, fmt.Sprintf("%q%s", e.Char, repeat)) + + direction := "up" + if e.KeyDown { + direction = "down" + } + + infos = append(infos, direction) + + if e.ControlKeyState != NO_CONTROL_KEY { + infos = append(infos, e.ControlKeyState.String()) + } + + infos = append(infos, fmt.Sprintf("KeyCode: %d", e.VirtualKeyCode)) + infos = append(infos, fmt.Sprintf("ScanCode: %d", e.VirtualScanCode)) + + return fmt.Sprintf("%s[%s]", e.Type(), strings.Join(infos, ", ")) +} + +// MenuEventType is the event type for a MenuEventRecord (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +const MenuEventType EventType = 0x0008 + +// MenuEventRecord represent the MENU_EVENT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/menu-event-record-str). +// These events are deprecated by the Windows console API and should be ignored. +type MenuEventRecord struct { + CommandID uint32 +} + +// Ensure that MenuEventRecord satisfies EventRecord interface. +var _ EventRecord = MenuEventRecord{} + +// Type ensures that MenuEventRecord satisfies EventRecord interface. +func (e MenuEventRecord) Type() string { return "MenuEvent" } + +// String ensures that MenuEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e MenuEventRecord) String() string { return fmt.Sprintf("MenuEvent[%d]", e.CommandID) } + +// MouseEventType is the event type for a MouseEventRecord (see +// https://docs.microsoft.com/en-us/windows/console/input-record-str). +const MouseEventType EventType = 0x0002 + +// MouseEventRecord represent the MOUSE_EVENT_RECORD structure from the Windows +// console API (see +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). +type MouseEventRecord struct { + // MousePosition contains the location of the cursor, in terms of the + // console screen buffer's character-cell coordinates. + MousePositon Coord + + // ButtonState holds the status of the mouse buttons. + ButtonState ButtonState + + // ControlKeyState holds the state of the control keys. + ControlKeyState ControlKeyState + + // EventFlags specify tge type of mouse event. + EventFlags EventFlags + + // WheelDirection specified the direction in which the mouse wheel is + // spinning when EventFlags contains MOUSE_HWHEELED or MOUSE_WHEELED. When + // the event flags specify MOUSE_WHEELED it is 1 if the wheel rotated + // forward (away from the user) or -1 when it rotates backwards. When + // MOUSE_HWHEELED is specified it is 1 when the wheel rotates right and -1 + // when it rotates left. When the EventFlags do not indicate a mouse wheel + // event it is 0. + WheelDirection int +} + +// Ensure that MouseEventRecord satisfies EventRecord interface. +var _ EventRecord = MouseEventRecord{} + +func (e MouseEventRecord) WheelDirectionName() string { + if e.EventFlags&MOUSE_WHEELED > 0 { + if e.WheelDirection > 0 { + return "Forward" + } + + return "Backward" + } else if e.EventFlags&MOUSE_HWHEELED > 0 { + if e.WheelDirection > 0 { + return "Right" + } + + return "Left" + } + + return "" +} + +// Type ensures that MouseEventRecord satisfies EventRecord interface. +func (e MouseEventRecord) Type() string { return "MouseEvent" } + +// String ensures that MouseEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e MouseEventRecord) String() string { + infos := []string{e.MousePositon.String()} + + if e.ButtonState&0xFF != 0 { + infos = append(infos, e.ButtonState.String()) + } + + eventDescription := e.EventFlags.String() + + wheelDirection := e.WheelDirectionName() + if wheelDirection != "" { + eventDescription += "(" + wheelDirection + ")" + } + + infos = append(infos, eventDescription) + + if e.ControlKeyState != NO_CONTROL_KEY { + infos = append(infos, e.ControlKeyState.String()) + } + + return fmt.Sprintf("%s[%s]", e.Type(), strings.Join(infos, ", ")) +} + +// WindowBufferSizeEventType is the event type for a WindowBufferSizeEventRecord +// (see https://docs.microsoft.com/en-us/windows/console/input-record-str). +const WindowBufferSizeEventType EventType = 0x0004 + +// WindowBufferSizeEventRecord represent the WINDOW_BUFFER_SIZE_RECORD structure +// from the Windows console API (see +// https://docs.microsoft.com/en-us/windows/console/window-buffer-size-record-str). +type WindowBufferSizeEventRecord struct { + // Size contains the size of the console screen buffer, in character cell columns and rows. + Size Coord +} + +// Ensure that WindowBufferSizeEventRecord satisfies EventRecord interface. +var _ EventRecord = WindowBufferSizeEventRecord{} + +// Type ensures that WindowBufferSizeEventRecord satisfies EventRecord interface. +func (e WindowBufferSizeEventRecord) Type() string { return "WindowBufferSizeEvent" } + +// String ensures that WindowBufferSizeEventRecord satisfies EventRecord and fmt.Stringer +// interfaces. +func (e WindowBufferSizeEventRecord) String() string { + return fmt.Sprintf("WindowBufferSizeEvent[%s]", e.Size) +} + +// UnknownEvent is generated when the event type does not match one of the +// following types: TypeFocusEventRecord, TypeKeyEventRecord, +// TypeMouseEventRecord, TypeWindowBufferSizeEvent, TypeMenuEventRecord and +// UnknownEvent. +type UnknownEvent struct { + InputRecord +} + +// Ensure that UnknownEvent satisfies EventRecord interface. +var _ EventRecord = UnknownEvent{} + +// Type ensures that UnknownEvent satisfies EventRecord interface. +func (e UnknownEvent) Type() string { return "UnknownEvent" } + +// String ensures that UnknownEvent satisfies EventRecord and fmt.Stringer +// interfaces. +func (e UnknownEvent) String() string { + return fmt.Sprintf("%s[Type: %d, Data: %v]", e.Type(), e.InputRecord.EventType, e.InputRecord.Event[:]) +} + +// Coord represent the COORD structure from the Windows +// console API (see https://docs.microsoft.com/en-us/windows/console/coord-str). +type Coord struct { + // X is the horizontal coordinate or column value. The units depend on the function call. + X uint16 + // Y is the vertical coordinate or row value. The units depend on the function call. + Y uint16 +} + +// String ensures that Coord satisfies the fmt.Stringer interface. +func (c Coord) String() string { + return fmt.Sprintf("(%d, %d)", c.X, c.Y) +} + +// ButtonState holds the state of the mouse buttons (see +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). +type ButtonState uint32 + +func (bs ButtonState) Contains(state ButtonState) bool { + return bs&state > 0 +} + +// String ensures that ButtonState satisfies the fmt.Stringer interface. +func (bs ButtonState) String() string { + switch { + case bs&FROM_LEFT_1ST_BUTTON_PRESSED > 0: + return "Left" + case bs&FROM_LEFT_2ND_BUTTON_PRESSED > 0: + return "2" + case bs&FROM_LEFT_3RD_BUTTON_PRESSED > 0: + return "3" + case bs&FROM_LEFT_4TH_BUTTON_PRESSED > 0: + return "4" + case bs&RIGHTMOST_BUTTON_PRESSED > 0: + return "Right" + case bs&0xFF == 0: + return "No Button" + default: + return fmt.Sprintf("Unknown(%d)", bs) + } +} + +func (bs ButtonState) IsReleased() bool { + return bs&0xff > 0 +} + +// Valid values for ButtonState. +const ( + FROM_LEFT_1ST_BUTTON_PRESSED ButtonState = 0x0001 + RIGHTMOST_BUTTON_PRESSED ButtonState = 0x0002 + FROM_LEFT_2ND_BUTTON_PRESSED ButtonState = 0x0004 + FROM_LEFT_3RD_BUTTON_PRESSED ButtonState = 0x0008 + FROM_LEFT_4TH_BUTTON_PRESSED ButtonState = 0x0010 +) + +// ControlKeyState holds the state of the control keys for key and mouse events +// (see https://docs.microsoft.com/en-us/windows/console/key-event-record-str +// and https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). +type ControlKeyState uint32 + +func (cks ControlKeyState) Contains(state ControlKeyState) bool { + return cks&state > 0 +} + +// Valid values for ControlKeyState. +const ( + CAPSLOCK_ON ControlKeyState = 0x0080 + ENHANCED_KEY ControlKeyState = 0x0100 + LEFT_ALT_PRESSED ControlKeyState = 0x0002 + LEFT_CTRL_PRESSED ControlKeyState = 0x0008 + NUMLOCK_ON ControlKeyState = 0x0020 + RIGHT_ALT_PRESSED ControlKeyState = 0x0001 + RIGHT_CTRL_PRESSED ControlKeyState = 0x0004 + SCROLLLOCK_ON ControlKeyState = 0x0040 + SHIFT_PRESSED ControlKeyState = 0x0010 + NO_CONTROL_KEY ControlKeyState = 0x0000 +) + +// String ensures that ControlKeyState satisfies the fmt.Stringer interface. +func (cks ControlKeyState) String() string { + controlKeys := []string{} + + switch { + case cks&CAPSLOCK_ON > 0: + controlKeys = append(controlKeys, "CapsLock") + case cks&ENHANCED_KEY > 0: + controlKeys = append(controlKeys, "Enhanced") + case cks&LEFT_ALT_PRESSED > 0: + controlKeys = append(controlKeys, "Alt") + case cks&LEFT_CTRL_PRESSED > 0: + controlKeys = append(controlKeys, "CTRL") + case cks&NUMLOCK_ON > 0: + controlKeys = append(controlKeys, "NumLock") + case cks&RIGHT_ALT_PRESSED > 0: + controlKeys = append(controlKeys, "RightAlt") + case cks&RIGHT_CTRL_PRESSED > 0: + controlKeys = append(controlKeys, "RightCTRL") + case cks&SCROLLLOCK_ON > 0: + controlKeys = append(controlKeys, "ScrollLock") + case cks&SHIFT_PRESSED > 0: + controlKeys = append(controlKeys, "Shift") + case cks == NO_CONTROL_KEY: + default: + return fmt.Sprintf("Unknown(%d)", cks) + } + + return strings.Join(controlKeys, ",") +} + +// EventFlags specifies the type of a mouse event (see +// https://docs.microsoft.com/en-us/windows/console/mouse-event-record-str). +type EventFlags uint32 + +// String ensures that EventFlags satisfies the fmt.Stringer interface. +func (ef EventFlags) String() string { + switch { + case ef&DOUBLE_CLICK > 0: + return "DoubleClick" + case ef&MOUSE_WHEELED > 0: + return "Wheeled" + case ef&MOUSE_MOVED > 0: + return "Moved" + case ef&MOUSE_HWHEELED > 0: + return "HWheeld" + case ef == CLICK: + return "Click" + default: + return fmt.Sprintf("Unknown(%d)", ef) + } +} + +func (ef EventFlags) Contains(flag EventFlags) bool { + return ef&flag > 0 +} + +// Valid values for EventFlags. +const ( + CLICK EventFlags = 0x0000 + MOUSE_MOVED EventFlags = 0x0001 + DOUBLE_CLICK EventFlags = 0x0002 + MOUSE_WHEELED EventFlags = 0x0004 + MOUSE_HWHEELED EventFlags = 0x0008 +) + +func highWord(data uint32) uint16 { + return uint16((data & 0xFFFF0000) >> 16) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/.gitignore b/vendor/github.com/lucasb-eyer/go-colorful/.gitignore new file mode 100644 index 00000000..0aa2c922 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/.gitignore @@ -0,0 +1,101 @@ +# Created by https://www.toptal.com/developers/gitignore/api/code,go,linux,macos,windows +# Edit at https://www.toptal.com/developers/gitignore?templates=code,go,linux,macos,windows + +### Code ### +.vscode/* +!.vscode/tasks.json +!.vscode/launch.json +*.code-workspace + +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +### Go Patch ### +/vendor/ +/Godeps/ + +### Linux ### +*~ + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Windows ### +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# End of https://www.toptal.com/developers/gitignore/api/code,go,linux,macos,windows diff --git a/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md b/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md new file mode 100644 index 00000000..84f9c7b2 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/CHANGELOG.md @@ -0,0 +1,42 @@ +# Changelog +All notable changes to this project will be documented in this file. + +This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +The format of this file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +but only releases after v1.0.3 properly adhere to it. + + +## [1.2.0] - 2021-01-27 +### Added +- HSLuv and HPLuv color spaces (#41, #51) +- CIE LCh(uv) color space, called `LuvLCh` in code (#51) +- JSON and envconfig serialization support for `HexColor` (#42) +- `DistanceLinearRGB` (#53) + +### Fixed +- RGB to/from XYZ conversion is more accurate (#51) +- A bug in `XYZToLuvWhiteRef` that only applied to very small values was fixed (#51) +- `BlendHCL` output is clamped so that it's not invalid (#46) +- Properly documented `DistanceCIE76` (#40) +- Some small godoc fixes + + +## [1.0.3] - 2019-11-11 +- Remove SQLMock dependency + + +## [1.0.2] - 2019-04-07 +- Fixes SQLMock dependency + + +## [1.0.1] - 2019-03-24 +- Adds support for Go Modules + + +## [1.0.0] - 2018-05-26 +- API Breaking change in `MakeColor`: instead of `panic`ing when alpha is zero, it now returns a secondary, boolean return value indicating success. See [the color.Color interface](#the-colorcolor-interface) section and [this FAQ entry](#q-why-would-makecolor-ever-fail) for details. + + +## [0.9.0] - 2018-05-26 +- Initial version number after having ignored versioning for a long time :) diff --git a/vendor/github.com/lucasb-eyer/go-colorful/LICENSE b/vendor/github.com/lucasb-eyer/go-colorful/LICENSE new file mode 100644 index 00000000..4e402a00 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/LICENSE @@ -0,0 +1,7 @@ +Copyright (c) 2013 Lucas Beyer + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/lucasb-eyer/go-colorful/README.md b/vendor/github.com/lucasb-eyer/go-colorful/README.md new file mode 100644 index 00000000..8b9bd499 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/README.md @@ -0,0 +1,482 @@ +go-colorful +=========== + +[![go reportcard](https://goreportcard.com/badge/github.com/lucasb-eyer/go-colorful)](https://goreportcard.com/report/github.com/lucasb-eyer/go-colorful) + +A library for playing with colors in Go. Supports Go 1.13 onwards. + +Why? +==== +I love games. I make games. I love detail and I get lost in detail. +One such detail popped up during the development of [Memory Which Does Not Suck](https://github.com/lucasb-eyer/mwdns/), +when we wanted the server to assign the players random colors. Sometimes +two players got very similar colors, which bugged me. The very same evening, +[I want hue](http://tools.medialab.sciences-po.fr/iwanthue/) was the top post +on HackerNews' frontpage and showed me how to Do It Right™. Last but not +least, there was no library for handling color spaces available in go. Colorful +does just that and implements Go's `color.Color` interface. + +What? +===== +Go-Colorful stores colors in RGB and provides methods from converting these to various color-spaces. Currently supported colorspaces are: + +- **RGB:** All three of Red, Green and Blue in [0..1]. +- **HSL:** Hue in [0..360], Saturation and Luminance in [0..1]. For legacy reasons; please forget that it exists. +- **HSV:** Hue in [0..360], Saturation and Value in [0..1]. You're better off using HCL, see below. +- **Hex RGB:** The "internet" color format, as in #FF00FF. +- **Linear RGB:** See [gamma correct rendering](http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/). +- **CIE-XYZ:** CIE's standard color space, almost in [0..1]. +- **CIE-xyY:** encodes chromacity in x and y and luminance in Y, all in [0..1] +- **CIE-L\*a\*b\*:** A *perceptually uniform* color space, i.e. distances are meaningful. L\* in [0..1] and a\*, b\* almost in [-1..1]. +- **CIE-L\*u\*v\*:** Very similar to CIE-L\*a\*b\*, there is [no consensus](http://en.wikipedia.org/wiki/CIELUV#Historical_background) on which one is "better". +- **CIE-L\*C\*h° (HCL):** This is generally the [most useful](http://vis4.net/blog/posts/avoid-equidistant-hsv-colors/) one; CIE-L\*a\*b\* space in polar coordinates, i.e. a *better* HSV. H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*a\*b\*. +- **CIE LCh(uv):** Called `LuvLCh` in code, this is a cylindrical transformation of the CIE-L\*u\*v\* color space. Like HCL above: H° is in [0..360], C\* almost in [-1..1] and L\* as in CIE-L\*u\*v\*. +- **HSLuv:** The better alternative to HSL, see [here](https://www.hsluv.org/) and [here](https://www.kuon.ch/post/2020-03-08-hsluv/). Hue in [0..360], Saturation and Luminance in [0..1]. +- **HPLuv:** A variant of HSLuv. The color space is smoother, but only pastel colors can be included. Because the valid colors are limited, it's easy to get invalid Saturation values way above 1.0, indicating the color can't be represented in HPLuv beccause it's not pastel. + +For the colorspaces where it makes sense (XYZ, Lab, Luv, HCl), the +[D65](http://en.wikipedia.org/wiki/Illuminant_D65) is used as reference white +by default but methods for using your own reference white are provided. + +A coordinate being *almost in* a range means that generally it is, but for very +bright colors and depending on the reference white, it might overflow this +range slightly. For example, C\* of #0000ff is 1.338. + +Unit-tests are provided. + +Nice, but what's it useful for? +------------------------------- + +- Converting color spaces. Some people like to do that. +- Blending (interpolating) between colors in a "natural" look by using the right colorspace. +- Generating random colors under some constraints (e.g. colors of the same shade, or shades of one color.) +- Generating gorgeous random palettes with distinct colors of a same temperature. + +What not (yet)? +=============== +There are a few features which are currently missing and might be useful. +I just haven't implemented them yet because I didn't have the need for it. +Pull requests welcome. + +- Sorting colors (potentially using above mentioned distances) + +So which colorspace should I use? +================================= +It depends on what you want to do. I think the folks from *I want hue* are +on-spot when they say that RGB fits to how *screens produce* color, CIE L\*a\*b\* +fits how *humans perceive* color and HCL fits how *humans think* colors. + +Whenever you'd use HSV, rather go for CIE-L\*C\*h°. for fixed lightness L\* and +chroma C\* values, the hue angle h° rotates through colors of the same +perceived brightness and intensity. + +How? +==== + +### Installing +Installing the library is as easy as + +```bash +$ go get github.com/lucasb-eyer/go-colorful +``` + +The package can then be used through an + +```go +import "github.com/lucasb-eyer/go-colorful" +``` + +### Basic usage + +Create a beautiful blue color using different source space: + +```go +// Any of the following should be the same +c := colorful.Color{0.313725, 0.478431, 0.721569} +c, err := colorful.Hex("#517AB8") +if err != nil { + log.Fatal(err) +} +c = colorful.Hsv(216.0, 0.56, 0.722) +c = colorful.Xyz(0.189165, 0.190837, 0.480248) +c = colorful.Xyy(0.219895, 0.221839, 0.190837) +c = colorful.Lab(0.507850, 0.040585,-0.370945) +c = colorful.Luv(0.507849,-0.194172,-0.567924) +c = colorful.Hcl(276.2440, 0.373160, 0.507849) +fmt.Printf("RGB values: %v, %v, %v", c.R, c.G, c.B) +``` + +And then converting this color back into various color spaces: + +```go +hex := c.Hex() +h, s, v := c.Hsv() +x, y, z := c.Xyz() +x, y, Y := c.Xyy() +l, a, b := c.Lab() +l, u, v := c.Luv() +h, c, l := c.Hcl() +``` + +Note that, because of Go's unfortunate choice of requiring an initial uppercase, +the name of the functions relating to the xyY space are just off. If you have +any good suggestion, please open an issue. (I don't consider XyY good.) + +### The `color.Color` interface +Because a `colorful.Color` implements Go's `color.Color` interface (found in the +`image/color` package), it can be used anywhere that expects a `color.Color`. + +Furthermore, you can convert anything that implements the `color.Color` interface +into a `colorful.Color` using the `MakeColor` function: + +```go +c, ok := colorful.MakeColor(color.Gray16{12345}) +``` + +**Caveat:** Be aware that this latter conversion (using `MakeColor`) hits a +corner-case when alpha is exactly zero. Because `color.Color` uses pre-multiplied +alpha colors, this means the RGB values are lost (set to 0) and it's impossible +to recover them. In such a case `MakeColor` will return `false` as its second value. + +### Comparing colors +In the RGB color space, the Euclidian distance between colors *doesn't* correspond +to visual/perceptual distance. This means that two pairs of colors which have the +same distance in RGB space can look much further apart. This is fixed by the +CIE-L\*a\*b\*, CIE-L\*u\*v\* and CIE-L\*C\*h° color spaces. +Thus you should only compare colors in any of these space. +(Note that the distance in CIE-L\*a\*b\* and CIE-L\*C\*h° are the same, since it's the same space but in cylindrical coordinates) + +![Color distance comparison](doc/colordist/colordist.png) + +The two colors shown on the top look much more different than the two shown on +the bottom. Still, in RGB space, their distance is the same. +Here is a little example program which shows the distances between the top two +and bottom two colors in RGB, CIE-L\*a\*b\* and CIE-L\*u\*v\* space. You can find it in `doc/colordist/colordist.go`. + +```go +package main + +import "fmt" +import "github.com/lucasb-eyer/go-colorful" + +func main() { + c1a := colorful.Color{150.0 / 255.0, 10.0 / 255.0, 150.0 / 255.0} + c1b := colorful.Color{53.0 / 255.0, 10.0 / 255.0, 150.0 / 255.0} + c2a := colorful.Color{10.0 / 255.0, 150.0 / 255.0, 50.0 / 255.0} + c2b := colorful.Color{99.9 / 255.0, 150.0 / 255.0, 10.0 / 255.0} + + fmt.Printf("DistanceRgb: c1: %v\tand c2: %v\n", c1a.DistanceRgb(c1b), c2a.DistanceRgb(c2b)) + fmt.Printf("DistanceLab: c1: %v\tand c2: %v\n", c1a.DistanceLab(c1b), c2a.DistanceLab(c2b)) + fmt.Printf("DistanceLuv: c1: %v\tand c2: %v\n", c1a.DistanceLuv(c1b), c2a.DistanceLuv(c2b)) + fmt.Printf("DistanceCIE76: c1: %v\tand c2: %v\n", c1a.DistanceCIE76(c1b), c2a.DistanceCIE76(c2b)) + fmt.Printf("DistanceCIE94: c1: %v\tand c2: %v\n", c1a.DistanceCIE94(c1b), c2a.DistanceCIE94(c2b)) + fmt.Printf("DistanceCIEDE2000: c1: %v\tand c2: %v\n", c1a.DistanceCIEDE2000(c1b), c2a.DistanceCIEDE2000(c2b)) +} +``` + +Running the above program shows that you should always prefer any of the CIE distances: + +```bash +$ go run colordist.go +DistanceRgb: c1: 0.3803921568627451 and c2: 0.3858713931171159 +DistanceLab: c1: 0.32048458312798056 and c2: 0.24397151758565272 +DistanceLuv: c1: 0.5134369614199698 and c2: 0.2568692839860636 +DistanceCIE76: c1: 0.32048458312798056 and c2: 0.24397151758565272 +DistanceCIE94: c1: 0.19799168128511324 and c2: 0.12207136371167401 +DistanceCIEDE2000: c1: 0.17274551120971166 and c2: 0.10665210031428465 +``` + +It also shows that `DistanceLab` is more formally known as `DistanceCIE76` and +has been superseded by the slightly more accurate, but much more expensive +`DistanceCIE94` and `DistanceCIEDE2000`. + +Note that `AlmostEqualRgb` is provided mainly for (unit-)testing purposes. Use +it only if you really know what you're doing. It will eat your cat. + +### Blending colors +Blending is highly connected to distance, since it basically "walks through" the +colorspace thus, if the colorspace maps distances well, the walk is "smooth". + +Colorful comes with blending functions in RGB, HSV and any of the LAB spaces. +Of course, you'd rather want to use the blending functions of the LAB spaces since +these spaces map distances well but, just in case, here is an example showing +you how the blendings (`#fdffcc` to `#242a42`) are done in the various spaces: + +![Blending colors in different spaces.](doc/colorblend/colorblend.png) + +What you see is that HSV is really bad: it adds some green, which is not present +in the original colors at all! RGB is much better, but it stays light a little +too long. LUV and LAB both hit the right lightness but LAB has a little more +color. HCL works in the same vein as HSV (both cylindrical interpolations) but +it does it right in that there is no green appearing and the lighthness changes +in a linear manner. + +While this seems all good, you need to know one thing: When interpolating in any +of the CIE color spaces, you might get invalid RGB colors! This is important if +the starting and ending colors are user-input or random. An example of where this +happens is when blending between `#eeef61` and `#1e3140`: + +![Invalid RGB colors may crop up when blending in CIE spaces.](doc/colorblend/invalid.png) + +You can test whether a color is a valid RGB color by calling the `IsValid` method +and indeed, calling IsValid will return false for the redish colors on the bottom. +One way to "fix" this is to get a valid color close to the invalid one by calling +`Clamped`, which always returns a nearby valid color. Doing this, we get the +following result, which is satisfactory: + +![Fixing invalid RGB colors by clamping them to the valid range.](doc/colorblend/clamped.png) + +The following is the code creating the above three images; it can be found in `doc/colorblend/colorblend.go` + +```go +package main + +import "fmt" +import "github.com/lucasb-eyer/go-colorful" +import "image" +import "image/draw" +import "image/png" +import "os" + +func main() { + blocks := 10 + blockw := 40 + img := image.NewRGBA(image.Rect(0,0,blocks*blockw,200)) + + c1, _ := colorful.Hex("#fdffcc") + c2, _ := colorful.Hex("#242a42") + + // Use these colors to get invalid RGB in the gradient. + //c1, _ := colorful.Hex("#EEEF61") + //c2, _ := colorful.Hex("#1E3140") + + for i := 0 ; i < blocks ; i++ { + draw.Draw(img, image.Rect(i*blockw, 0,(i+1)*blockw, 40), &image.Uniform{c1.BlendHsv(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src) + draw.Draw(img, image.Rect(i*blockw, 40,(i+1)*blockw, 80), &image.Uniform{c1.BlendLuv(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src) + draw.Draw(img, image.Rect(i*blockw, 80,(i+1)*blockw,120), &image.Uniform{c1.BlendRgb(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src) + draw.Draw(img, image.Rect(i*blockw,120,(i+1)*blockw,160), &image.Uniform{c1.BlendLab(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src) + draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1))}, image.Point{}, draw.Src) + + // This can be used to "fix" invalid colors in the gradient. + //draw.Draw(img, image.Rect(i*blockw,160,(i+1)*blockw,200), &image.Uniform{c1.BlendHcl(c2, float64(i)/float64(blocks-1)).Clamped()}, image.Point{}, draw.Src) + } + + toimg, err := os.Create("colorblend.png") + if err != nil { + fmt.Printf("Error: %v", err) + return + } + defer toimg.Close() + + png.Encode(toimg, img) +} +``` + +#### Generating color gradients +A very common reason to blend colors is creating gradients. There is an example +program in [doc/gradientgen.go](doc/gradientgen/gradientgen.go); it doesn't use any API +which hasn't been used in the previous example code, so I won't bother pasting +the code in here. Just look at that gorgeous gradient it generated in HCL space: + +!["Spectral" colorbrewer gradient in HCL space.](doc/gradientgen/gradientgen.png) + +### Getting random colors +It is sometimes necessary to generate random colors. You could simply do this +on your own by generating colors with random values. By restricting the random +values to a range smaller than [0..1] and using a space such as CIE-H\*C\*l° or +HSV, you can generate both random shades of a color or random colors of a +lightness: + +```go +random_blue := colorful.Hcl(180.0+rand.Float64()*50.0, 0.2+rand.Float64()*0.8, 0.3+rand.Float64()*0.7) +random_dark := colorful.Hcl(rand.Float64()*360.0, rand.Float64(), rand.Float64()*0.4) +random_light := colorful.Hcl(rand.Float64()*360.0, rand.Float64(), 0.6+rand.Float64()*0.4) +``` + +Since getting random "warm" and "happy" colors is quite a common task, there +are some helper functions: + +```go +colorful.WarmColor() +colorful.HappyColor() +colorful.FastWarmColor() +colorful.FastHappyColor() +``` + +The ones prefixed by `Fast` are faster but less coherent since they use the HSV +space as opposed to the regular ones which use CIE-L\*C\*h° space. The +following picture shows the warm colors in the top two rows and happy colors +in the bottom two rows. Within these, the first is the regular one and the +second is the fast one. + +![Warm, fast warm, happy and fast happy random colors, respectively.](doc/colorgens/colorgens.png) + +Don't forget to initialize the random seed! You can see the code used for +generating this picture in `doc/colorgens/colorgens.go`. + +### Getting random palettes +As soon as you need to generate more than one random color, you probably want +them to be distinguishible. Playing against an opponent which has almost the +same blue as I do is not fun. This is where random palettes can help. + +These palettes are generated using an algorithm which ensures that all colors +on the palette are as distinguishible as possible. Again, there is a `Fast` +method which works in HSV and is less perceptually uniform and a non-`Fast` +method which works in CIE spaces. For more theory on `SoftPalette`, check out +[I want hue](http://tools.medialab.sciences-po.fr/iwanthue/theory.php). Yet +again, there is a `Happy` and a `Warm` version, which do what you expect, but +now there is an additional `Soft` version, which is more configurable: you can +give a constraint on the color space in order to get colors within a certain *feel*. + +Let's start with the simple methods first, all they take is the amount of +colors to generate, which could, for example, be the player count. They return +an array of `colorful.Color` objects: + +```go +pal1, err1 := colorful.WarmPalette(10) +pal2 := colorful.FastWarmPalette(10) +pal3, err3 := colorful.HappyPalette(10) +pal4 := colorful.FastHappyPalette(10) +pal5, err5 := colorful.SoftPalette(10) +``` + +Note that the non-fast methods *may* fail if you ask for way too many colors. +Let's move on to the advanced one, namely `SoftPaletteEx`. Besides the color +count, this function takes a `SoftPaletteSettings` object as argument. The +interesting part here is its `CheckColor` member, which is a boolean function +taking three floating points as arguments: `l`, `a` and `b`. This function +should return `true` for colors which lie within the region you want and `false` +otherwise. The other members are `Iteration`, which should be within [5..100] +where higher means slower but more exact palette, and `ManySamples` which you +should set to `true` in case your `CheckColor` constraint rejects a large part +of the color space. + +For example, to create a palette of 10 brownish colors, you'd call it like this: + +```go +func isbrowny(l, a, b float64) bool { + h, c, L := colorful.LabToHcl(l, a, b) + return 10.0 < h && h < 50.0 && 0.1 < c && c < 0.5 && L < 0.5 +} +// Since the above function is pretty restrictive, we set ManySamples to true. +brownies := colorful.SoftPaletteEx(10, colorful.SoftPaletteSettings{isbrowny, 50, true}) +``` + +The following picture shows the palettes generated by all of these methods +(sourcecode in `doc/palettegens/palettegens.go`), in the order they were presented, i.e. +from top to bottom: `Warm`, `FastWarm`, `Happy`, `FastHappy`, `Soft`, +`SoftEx(isbrowny)`. All of them contain some randomness, so YMMV. + +![All example palettes](doc/palettegens/palettegens.png) + +Again, the code used for generating the above image is available as [doc/palettegens/palettegens.go](https://github.com/lucasb-eyer/go-colorful/blob/master/doc/palettegens/palettegens.go). + +### Sorting colors +TODO: Sort using dist fn. + +### Using linear RGB for computations +There are two methods for transforming RGB<->Linear RGB: a fast and almost precise one, +and a slow and precise one. + +```go +r, g, b := colorful.Hex("#FF0000").FastLinearRgb() +``` + +TODO: describe some more. + +### Want to use some other reference point? + +```go +c := colorful.LabWhiteRef(0.507850, 0.040585,-0.370945, colorful.D50) +l, a, b := c.LabWhiteRef(colorful.D50) +``` + +### Reading and writing colors from databases + +The type `HexColor` makes it easy to store colors as strings in a database. It +implements the [https://godoc.org/database/sql#Scanner](database/sql.Scanner) +and [database/sql/driver.Value](https://godoc.org/database/sql/driver.Value) +interfaces which provide automatic type conversion. + +Example: + +```go +var hc HexColor +_, err := db.QueryRow("SELECT '#ff0000';").Scan(&hc) +// hc == HexColor{R: 1, G: 0, B: 0}; err == nil +``` + +FAQ +=== + +### Q: I get all f!@#ed up values! Your library sucks! +A: You probably provided values in the wrong range. For example, RGB values are +expected to reside between 0 and 1, *not* between 0 and 255. Normalize your colors. + +### Q: Lab/Luv/HCl seem broken! Your library sucks! +They look like this: + + + +A: You're likely trying to generate and display colors that can't be represented by RGB, +and thus monitors. When you're trying to convert, say, `HCL(190.0, 1.0, 1.0).RGB255()`, +you're asking for RGB values of `(-2105.254 300.680 286.185)`, which clearly don't exist, +and the `RGB255` function just casts these numbers to `uint8`, creating wrap-around and +what looks like a completely broken gradient. What you want to do, is either use more +reasonable values of colors which actually exist in RGB, or just `Clamp()` the resulting +color to its nearest existing one, living with the consequences: +`HCL(190.0, 1.0, 1.0).Clamp().RGB255()`. It will look something like this: + + + +[Here's an issue going in-depth about this](https://github.com/lucasb-eyer/go-colorful/issues/14), +as well as [my answer](https://github.com/lucasb-eyer/go-colorful/issues/14#issuecomment-324205385), +both with code and pretty pictures. Also note that this was somewhat covered above in the +["Blending colors" section](https://github.com/lucasb-eyer/go-colorful#blending-colors). + +### Q: In a tight loop, conversion to Lab/Luv/HCl/... are slooooow! +A: Yes, they are. +This library aims for correctness, readability, and modularity; it wasn't written with speed in mind. +A large part of the slowness comes from these conversions going through `LinearRgb` which uses powers. +I implemented a fast approximation to `LinearRgb` called `FastLinearRgb` by using Taylor approximations. +The approximation is roughly 5x faster and precise up to roughly 0.5%, +the major caveat being that if the input values are outside the range 0-1, accuracy drops dramatically. +You can use these in your conversions as follows: + +```go +col := // Get your color somehow +l, a, b := XyzToLab(LinearRgbToXyz(col.LinearRgb())) +``` + +If you need faster versions of `Distance*` and `Blend*` that make use of this fast approximation, +feel free to implement them and open a pull-request, I'll happily accept. + +The derivation of these functions can be followed in [this Jupyter notebook](doc/LinearRGB Approximations.ipynb). +Here's the main figure showing the approximation quality: + +![approximation quality](doc/approx-quality.png) + +More speed could be gained by using SIMD instructions in many places. +You can also get more speed for specific conversions by approximating the full conversion function, +but that is outside the scope of this library. +Thanks to [@ZirconiumX](https://github.com/ZirconiumX) for starting this investigation, +see [issue #18](https://github.com/lucasb-eyer/go-colorful/issues/18) for details. + +### Q: Why would `MakeColor` ever fail!? +A: `MakeColor` fails when the alpha channel is zero. In that case, the +conversion is undefined. See [issue 21](https://github.com/lucasb-eyer/go-colorful/issues/21) +as well as the short caveat note in the ["The `color.Color` interface"](README.md#the-colorcolor-interface) +section above. + +Who? +==== + +This library was developed by Lucas Beyer with contributions from +Bastien Dejean (@baskerville), Phil Kulak (@pkulak) and Christian Muehlhaeuser (@muesli). + +It is now maintained by makeworld (@makeworld-the-better-one). + + +## License + +This repo is under the MIT license, see [LICENSE](LICENSE) for details. diff --git a/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go b/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go new file mode 100644 index 00000000..2e2e49e1 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/colorgens.go @@ -0,0 +1,55 @@ +// Various ways to generate single random colors + +package colorful + +import ( + "math/rand" +) + +// Creates a random dark, "warm" color through a restricted HSV space. +func FastWarmColor() Color { + return Hsv( + rand.Float64()*360.0, + 0.5+rand.Float64()*0.3, + 0.3+rand.Float64()*0.3) +} + +// Creates a random dark, "warm" color through restricted HCL space. +// This is slower than FastWarmColor but will likely give you colors which have +// the same "warmness" if you run it many times. +func WarmColor() (c Color) { + for c = randomWarm(); !c.IsValid(); c = randomWarm() { + } + return +} + +func randomWarm() Color { + return Hcl( + rand.Float64()*360.0, + 0.1+rand.Float64()*0.3, + 0.2+rand.Float64()*0.3) +} + +// Creates a random bright, "pimpy" color through a restricted HSV space. +func FastHappyColor() Color { + return Hsv( + rand.Float64()*360.0, + 0.7+rand.Float64()*0.3, + 0.6+rand.Float64()*0.3) +} + +// Creates a random bright, "pimpy" color through restricted HCL space. +// This is slower than FastHappyColor but will likely give you colors which +// have the same "brightness" if you run it many times. +func HappyColor() (c Color) { + for c = randomPimp(); !c.IsValid(); c = randomPimp() { + } + return +} + +func randomPimp() Color { + return Hcl( + rand.Float64()*360.0, + 0.5+rand.Float64()*0.3, + 0.5+rand.Float64()*0.3) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/colors.go b/vendor/github.com/lucasb-eyer/go-colorful/colors.go new file mode 100644 index 00000000..0d5bffe5 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/colors.go @@ -0,0 +1,979 @@ +// The colorful package provides all kinds of functions for working with colors. +package colorful + +import ( + "fmt" + "image/color" + "math" +) + +// A color is stored internally using sRGB (standard RGB) values in the range 0-1 +type Color struct { + R, G, B float64 +} + +// Implement the Go color.Color interface. +func (col Color) RGBA() (r, g, b, a uint32) { + r = uint32(col.R*65535.0 + 0.5) + g = uint32(col.G*65535.0 + 0.5) + b = uint32(col.B*65535.0 + 0.5) + a = 0xFFFF + return +} + +// Constructs a colorful.Color from something implementing color.Color +func MakeColor(col color.Color) (Color, bool) { + r, g, b, a := col.RGBA() + if a == 0 { + return Color{0, 0, 0}, false + } + + // Since color.Color is alpha pre-multiplied, we need to divide the + // RGB values by alpha again in order to get back the original RGB. + r *= 0xffff + r /= a + g *= 0xffff + g /= a + b *= 0xffff + b /= a + + return Color{float64(r) / 65535.0, float64(g) / 65535.0, float64(b) / 65535.0}, true +} + +// Might come in handy sometimes to reduce boilerplate code. +func (col Color) RGB255() (r, g, b uint8) { + r = uint8(col.R*255.0 + 0.5) + g = uint8(col.G*255.0 + 0.5) + b = uint8(col.B*255.0 + 0.5) + return +} + +// Used to simplify HSLuv testing. +func (col Color) values() (float64, float64, float64) { + return col.R, col.G, col.B +} + +// This is the tolerance used when comparing colors using AlmostEqualRgb. +const Delta = 1.0 / 255.0 + +// This is the default reference white point. +var D65 = [3]float64{0.95047, 1.00000, 1.08883} + +// And another one. +var D50 = [3]float64{0.96422, 1.00000, 0.82521} + +// Checks whether the color exists in RGB space, i.e. all values are in [0..1] +func (c Color) IsValid() bool { + return 0.0 <= c.R && c.R <= 1.0 && + 0.0 <= c.G && c.G <= 1.0 && + 0.0 <= c.B && c.B <= 1.0 +} + +// clamp01 clamps from 0 to 1. +func clamp01(v float64) float64 { + return math.Max(0.0, math.Min(v, 1.0)) +} + +// Returns Clamps the color into valid range, clamping each value to [0..1] +// If the color is valid already, this is a no-op. +func (c Color) Clamped() Color { + return Color{clamp01(c.R), clamp01(c.G), clamp01(c.B)} +} + +func sq(v float64) float64 { + return v * v +} + +func cub(v float64) float64 { + return v * v * v +} + +// DistanceRgb computes the distance between two colors in RGB space. +// This is not a good measure! Rather do it in Lab space. +func (c1 Color) DistanceRgb(c2 Color) float64 { + return math.Sqrt(sq(c1.R-c2.R) + sq(c1.G-c2.G) + sq(c1.B-c2.B)) +} + +// DistanceLinearRGB computes the distance between two colors in linear RGB +// space. This is not useful for measuring how humans perceive color, but +// might be useful for other things, like dithering. +func (c1 Color) DistanceLinearRGB(c2 Color) float64 { + r1, g1, b1 := c1.LinearRgb() + r2, g2, b2 := c2.LinearRgb() + return math.Sqrt(sq(r1-r2) + sq(g1-g2) + sq(b1-b2)) +} + +// Check for equality between colors within the tolerance Delta (1/255). +func (c1 Color) AlmostEqualRgb(c2 Color) bool { + return math.Abs(c1.R-c2.R)+ + math.Abs(c1.G-c2.G)+ + math.Abs(c1.B-c2.B) < 3.0*Delta +} + +// You don't really want to use this, do you? Go for BlendLab, BlendLuv or BlendHcl. +func (c1 Color) BlendRgb(c2 Color, t float64) Color { + return Color{c1.R + t*(c2.R-c1.R), + c1.G + t*(c2.G-c1.G), + c1.B + t*(c2.B-c1.B)} +} + +// Utility used by Hxx color-spaces for interpolating between two angles in [0,360]. +func interp_angle(a0, a1, t float64) float64 { + // Based on the answer here: http://stackoverflow.com/a/14498790/2366315 + // With potential proof that it works here: http://math.stackexchange.com/a/2144499 + delta := math.Mod(math.Mod(a1-a0, 360.0)+540, 360.0) - 180.0 + return math.Mod(a0+t*delta+360.0, 360.0) +} + +/// HSV /// +/////////// +// From http://en.wikipedia.org/wiki/HSL_and_HSV +// Note that h is in [0..360] and s,v in [0..1] + +// Hsv returns the Hue [0..360], Saturation and Value [0..1] of the color. +func (col Color) Hsv() (h, s, v float64) { + min := math.Min(math.Min(col.R, col.G), col.B) + v = math.Max(math.Max(col.R, col.G), col.B) + C := v - min + + s = 0.0 + if v != 0.0 { + s = C / v + } + + h = 0.0 // We use 0 instead of undefined as in wp. + if min != v { + if v == col.R { + h = math.Mod((col.G-col.B)/C, 6.0) + } + if v == col.G { + h = (col.B-col.R)/C + 2.0 + } + if v == col.B { + h = (col.R-col.G)/C + 4.0 + } + h *= 60.0 + if h < 0.0 { + h += 360.0 + } + } + return +} + +// Hsv creates a new Color given a Hue in [0..360], a Saturation and a Value in [0..1] +func Hsv(H, S, V float64) Color { + Hp := H / 60.0 + C := V * S + X := C * (1.0 - math.Abs(math.Mod(Hp, 2.0)-1.0)) + + m := V - C + r, g, b := 0.0, 0.0, 0.0 + + switch { + case 0.0 <= Hp && Hp < 1.0: + r = C + g = X + case 1.0 <= Hp && Hp < 2.0: + r = X + g = C + case 2.0 <= Hp && Hp < 3.0: + g = C + b = X + case 3.0 <= Hp && Hp < 4.0: + g = X + b = C + case 4.0 <= Hp && Hp < 5.0: + r = X + b = C + case 5.0 <= Hp && Hp < 6.0: + r = C + b = X + } + + return Color{m + r, m + g, m + b} +} + +// You don't really want to use this, do you? Go for BlendLab, BlendLuv or BlendHcl. +func (c1 Color) BlendHsv(c2 Color, t float64) Color { + h1, s1, v1 := c1.Hsv() + h2, s2, v2 := c2.Hsv() + + // We know that h are both in [0..360] + return Hsv(interp_angle(h1, h2, t), s1+t*(s2-s1), v1+t*(v2-v1)) +} + +/// HSL /// +/////////// + +// Hsl returns the Hue [0..360], Saturation [0..1], and Luminance (lightness) [0..1] of the color. +func (col Color) Hsl() (h, s, l float64) { + min := math.Min(math.Min(col.R, col.G), col.B) + max := math.Max(math.Max(col.R, col.G), col.B) + + l = (max + min) / 2 + + if min == max { + s = 0 + h = 0 + } else { + if l < 0.5 { + s = (max - min) / (max + min) + } else { + s = (max - min) / (2.0 - max - min) + } + + if max == col.R { + h = (col.G - col.B) / (max - min) + } else if max == col.G { + h = 2.0 + (col.B-col.R)/(max-min) + } else { + h = 4.0 + (col.R-col.G)/(max-min) + } + + h *= 60 + + if h < 0 { + h += 360 + } + } + + return +} + +// Hsl creates a new Color given a Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1] +func Hsl(h, s, l float64) Color { + if s == 0 { + return Color{l, l, l} + } + + var r, g, b float64 + var t1 float64 + var t2 float64 + var tr float64 + var tg float64 + var tb float64 + + if l < 0.5 { + t1 = l * (1.0 + s) + } else { + t1 = l + s - l*s + } + + t2 = 2*l - t1 + h /= 360 + tr = h + 1.0/3.0 + tg = h + tb = h - 1.0/3.0 + + if tr < 0 { + tr++ + } + if tr > 1 { + tr-- + } + if tg < 0 { + tg++ + } + if tg > 1 { + tg-- + } + if tb < 0 { + tb++ + } + if tb > 1 { + tb-- + } + + // Red + if 6*tr < 1 { + r = t2 + (t1-t2)*6*tr + } else if 2*tr < 1 { + r = t1 + } else if 3*tr < 2 { + r = t2 + (t1-t2)*(2.0/3.0-tr)*6 + } else { + r = t2 + } + + // Green + if 6*tg < 1 { + g = t2 + (t1-t2)*6*tg + } else if 2*tg < 1 { + g = t1 + } else if 3*tg < 2 { + g = t2 + (t1-t2)*(2.0/3.0-tg)*6 + } else { + g = t2 + } + + // Blue + if 6*tb < 1 { + b = t2 + (t1-t2)*6*tb + } else if 2*tb < 1 { + b = t1 + } else if 3*tb < 2 { + b = t2 + (t1-t2)*(2.0/3.0-tb)*6 + } else { + b = t2 + } + + return Color{r, g, b} +} + +/// Hex /// +/////////// + +// Hex returns the hex "html" representation of the color, as in #ff0080. +func (col Color) Hex() string { + // Add 0.5 for rounding + return fmt.Sprintf("#%02x%02x%02x", uint8(col.R*255.0+0.5), uint8(col.G*255.0+0.5), uint8(col.B*255.0+0.5)) +} + +// Hex parses a "html" hex color-string, either in the 3 "#f0c" or 6 "#ff1034" digits form. +func Hex(scol string) (Color, error) { + format := "#%02x%02x%02x" + factor := 1.0 / 255.0 + if len(scol) == 4 { + format = "#%1x%1x%1x" + factor = 1.0 / 15.0 + } + + var r, g, b uint8 + n, err := fmt.Sscanf(scol, format, &r, &g, &b) + if err != nil { + return Color{}, err + } + if n != 3 { + return Color{}, fmt.Errorf("color: %v is not a hex-color", scol) + } + + return Color{float64(r) * factor, float64(g) * factor, float64(b) * factor}, nil +} + +/// Linear /// +////////////// +// http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/ +// http://www.brucelindbloom.com/Eqn_RGB_to_XYZ.html + +func linearize(v float64) float64 { + if v <= 0.04045 { + return v / 12.92 + } + return math.Pow((v+0.055)/1.055, 2.4) +} + +// LinearRgb converts the color into the linear RGB space (see http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/). +func (col Color) LinearRgb() (r, g, b float64) { + r = linearize(col.R) + g = linearize(col.G) + b = linearize(col.B) + return +} + +// A much faster and still quite precise linearization using a 6th-order Taylor approximation. +// See the accompanying Jupyter notebook for derivation of the constants. +func linearize_fast(v float64) float64 { + v1 := v - 0.5 + v2 := v1 * v1 + v3 := v2 * v1 + v4 := v2 * v2 + //v5 := v3*v2 + return -0.248750514614486 + 0.925583310193438*v + 1.16740237321695*v2 + 0.280457026598666*v3 - 0.0757991963780179*v4 //+ 0.0437040411548932*v5 +} + +// FastLinearRgb is much faster than and almost as accurate as LinearRgb. +// BUT it is important to NOTE that they only produce good results for valid colors r,g,b in [0,1]. +func (col Color) FastLinearRgb() (r, g, b float64) { + r = linearize_fast(col.R) + g = linearize_fast(col.G) + b = linearize_fast(col.B) + return +} + +func delinearize(v float64) float64 { + if v <= 0.0031308 { + return 12.92 * v + } + return 1.055*math.Pow(v, 1.0/2.4) - 0.055 +} + +// LinearRgb creates an sRGB color out of the given linear RGB color (see http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/). +func LinearRgb(r, g, b float64) Color { + return Color{delinearize(r), delinearize(g), delinearize(b)} +} + +func delinearize_fast(v float64) float64 { + // This function (fractional root) is much harder to linearize, so we need to split. + if v > 0.2 { + v1 := v - 0.6 + v2 := v1 * v1 + v3 := v2 * v1 + v4 := v2 * v2 + v5 := v3 * v2 + return 0.442430344268235 + 0.592178981271708*v - 0.287864782562636*v2 + 0.253214392068985*v3 - 0.272557158129811*v4 + 0.325554383321718*v5 + } else if v > 0.03 { + v1 := v - 0.115 + v2 := v1 * v1 + v3 := v2 * v1 + v4 := v2 * v2 + v5 := v3 * v2 + return 0.194915592891669 + 1.55227076330229*v - 3.93691860257828*v2 + 18.0679839248761*v3 - 101.468750302746*v4 + 632.341487393927*v5 + } else { + v1 := v - 0.015 + v2 := v1 * v1 + v3 := v2 * v1 + v4 := v2 * v2 + v5 := v3 * v2 + // You can clearly see from the involved constants that the low-end is highly nonlinear. + return 0.0519565234928877 + 5.09316778537561*v - 99.0338180489702*v2 + 3484.52322764895*v3 - 150028.083412663*v4 + 7168008.42971613*v5 + } +} + +// FastLinearRgb is much faster than and almost as accurate as LinearRgb. +// BUT it is important to NOTE that they only produce good results for valid inputs r,g,b in [0,1]. +func FastLinearRgb(r, g, b float64) Color { + return Color{delinearize_fast(r), delinearize_fast(g), delinearize_fast(b)} +} + +// XyzToLinearRgb converts from CIE XYZ-space to Linear RGB space. +func XyzToLinearRgb(x, y, z float64) (r, g, b float64) { + r = 3.2409699419045214*x - 1.5373831775700935*y - 0.49861076029300328*z + g = -0.96924363628087983*x + 1.8759675015077207*y + 0.041555057407175613*z + b = 0.055630079696993609*x - 0.20397695888897657*y + 1.0569715142428786*z + return +} + +func LinearRgbToXyz(r, g, b float64) (x, y, z float64) { + x = 0.41239079926595948*r + 0.35758433938387796*g + 0.18048078840183429*b + y = 0.21263900587151036*r + 0.71516867876775593*g + 0.072192315360733715*b + z = 0.019330818715591851*r + 0.11919477979462599*g + 0.95053215224966058*b + return +} + +/// XYZ /// +/////////// +// http://www.sjbrown.co.uk/2004/05/14/gamma-correct-rendering/ + +func (col Color) Xyz() (x, y, z float64) { + return LinearRgbToXyz(col.LinearRgb()) +} + +func Xyz(x, y, z float64) Color { + return LinearRgb(XyzToLinearRgb(x, y, z)) +} + +/// xyY /// +/////////// +// http://www.brucelindbloom.com/Eqn_XYZ_to_xyY.html + +// Well, the name is bad, since it's xyY but Golang needs me to start with a +// capital letter to make the method public. +func XyzToXyy(X, Y, Z float64) (x, y, Yout float64) { + return XyzToXyyWhiteRef(X, Y, Z, D65) +} + +func XyzToXyyWhiteRef(X, Y, Z float64, wref [3]float64) (x, y, Yout float64) { + Yout = Y + N := X + Y + Z + if math.Abs(N) < 1e-14 { + // When we have black, Bruce Lindbloom recommends to use + // the reference white's chromacity for x and y. + x = wref[0] / (wref[0] + wref[1] + wref[2]) + y = wref[1] / (wref[0] + wref[1] + wref[2]) + } else { + x = X / N + y = Y / N + } + return +} + +func XyyToXyz(x, y, Y float64) (X, Yout, Z float64) { + Yout = Y + + if -1e-14 < y && y < 1e-14 { + X = 0.0 + Z = 0.0 + } else { + X = Y / y * x + Z = Y / y * (1.0 - x - y) + } + + return +} + +// Converts the given color to CIE xyY space using D65 as reference white. +// (Note that the reference white is only used for black input.) +// x, y and Y are in [0..1] +func (col Color) Xyy() (x, y, Y float64) { + return XyzToXyy(col.Xyz()) +} + +// Converts the given color to CIE xyY space, taking into account +// a given reference white. (i.e. the monitor's white) +// (Note that the reference white is only used for black input.) +// x, y and Y are in [0..1] +func (col Color) XyyWhiteRef(wref [3]float64) (x, y, Y float64) { + X, Y2, Z := col.Xyz() + return XyzToXyyWhiteRef(X, Y2, Z, wref) +} + +// Generates a color by using data given in CIE xyY space. +// x, y and Y are in [0..1] +func Xyy(x, y, Y float64) Color { + return Xyz(XyyToXyz(x, y, Y)) +} + +/// L*a*b* /// +////////////// +// http://en.wikipedia.org/wiki/Lab_color_space#CIELAB-CIEXYZ_conversions +// For L*a*b*, we need to L*a*b*<->XYZ->RGB and the first one is device dependent. + +func lab_f(t float64) float64 { + if t > 6.0/29.0*6.0/29.0*6.0/29.0 { + return math.Cbrt(t) + } + return t/3.0*29.0/6.0*29.0/6.0 + 4.0/29.0 +} + +func XyzToLab(x, y, z float64) (l, a, b float64) { + // Use D65 white as reference point by default. + // http://www.fredmiranda.com/forum/topic/1035332 + // http://en.wikipedia.org/wiki/Standard_illuminant + return XyzToLabWhiteRef(x, y, z, D65) +} + +func XyzToLabWhiteRef(x, y, z float64, wref [3]float64) (l, a, b float64) { + fy := lab_f(y / wref[1]) + l = 1.16*fy - 0.16 + a = 5.0 * (lab_f(x/wref[0]) - fy) + b = 2.0 * (fy - lab_f(z/wref[2])) + return +} + +func lab_finv(t float64) float64 { + if t > 6.0/29.0 { + return t * t * t + } + return 3.0 * 6.0 / 29.0 * 6.0 / 29.0 * (t - 4.0/29.0) +} + +func LabToXyz(l, a, b float64) (x, y, z float64) { + // D65 white (see above). + return LabToXyzWhiteRef(l, a, b, D65) +} + +func LabToXyzWhiteRef(l, a, b float64, wref [3]float64) (x, y, z float64) { + l2 := (l + 0.16) / 1.16 + x = wref[0] * lab_finv(l2+a/5.0) + y = wref[1] * lab_finv(l2) + z = wref[2] * lab_finv(l2-b/2.0) + return +} + +// Converts the given color to CIE L*a*b* space using D65 as reference white. +func (col Color) Lab() (l, a, b float64) { + return XyzToLab(col.Xyz()) +} + +// Converts the given color to CIE L*a*b* space, taking into account +// a given reference white. (i.e. the monitor's white) +func (col Color) LabWhiteRef(wref [3]float64) (l, a, b float64) { + x, y, z := col.Xyz() + return XyzToLabWhiteRef(x, y, z, wref) +} + +// Generates a color by using data given in CIE L*a*b* space using D65 as reference white. +// WARNING: many combinations of `l`, `a`, and `b` values do not have corresponding +// valid RGB values, check the FAQ in the README if you're unsure. +func Lab(l, a, b float64) Color { + return Xyz(LabToXyz(l, a, b)) +} + +// Generates a color by using data given in CIE L*a*b* space, taking +// into account a given reference white. (i.e. the monitor's white) +func LabWhiteRef(l, a, b float64, wref [3]float64) Color { + return Xyz(LabToXyzWhiteRef(l, a, b, wref)) +} + +// DistanceLab is a good measure of visual similarity between two colors! +// A result of 0 would mean identical colors, while a result of 1 or higher +// means the colors differ a lot. +func (c1 Color) DistanceLab(c2 Color) float64 { + l1, a1, b1 := c1.Lab() + l2, a2, b2 := c2.Lab() + return math.Sqrt(sq(l1-l2) + sq(a1-a2) + sq(b1-b2)) +} + +// DistanceCIE76 is the same as DistanceLab. +func (c1 Color) DistanceCIE76(c2 Color) float64 { + return c1.DistanceLab(c2) +} + +// Uses the CIE94 formula to calculate color distance. More accurate than +// DistanceLab, but also more work. +func (cl Color) DistanceCIE94(cr Color) float64 { + l1, a1, b1 := cl.Lab() + l2, a2, b2 := cr.Lab() + + // NOTE: Since all those formulas expect L,a,b values 100x larger than we + // have them in this library, we either need to adjust all constants + // in the formula, or convert the ranges of L,a,b before, and then + // scale the distances down again. The latter is less error-prone. + l1, a1, b1 = l1*100.0, a1*100.0, b1*100.0 + l2, a2, b2 = l2*100.0, a2*100.0, b2*100.0 + + kl := 1.0 // 2.0 for textiles + kc := 1.0 + kh := 1.0 + k1 := 0.045 // 0.048 for textiles + k2 := 0.015 // 0.014 for textiles. + + deltaL := l1 - l2 + c1 := math.Sqrt(sq(a1) + sq(b1)) + c2 := math.Sqrt(sq(a2) + sq(b2)) + deltaCab := c1 - c2 + + // Not taking Sqrt here for stability, and it's unnecessary. + deltaHab2 := sq(a1-a2) + sq(b1-b2) - sq(deltaCab) + sl := 1.0 + sc := 1.0 + k1*c1 + sh := 1.0 + k2*c1 + + vL2 := sq(deltaL / (kl * sl)) + vC2 := sq(deltaCab / (kc * sc)) + vH2 := deltaHab2 / sq(kh*sh) + + return math.Sqrt(vL2+vC2+vH2) * 0.01 // See above. +} + +// DistanceCIEDE2000 uses the Delta E 2000 formula to calculate color +// distance. It is more expensive but more accurate than both DistanceLab +// and DistanceCIE94. +func (cl Color) DistanceCIEDE2000(cr Color) float64 { + return cl.DistanceCIEDE2000klch(cr, 1.0, 1.0, 1.0) +} + +// DistanceCIEDE2000klch uses the Delta E 2000 formula with custom values +// for the weighting factors kL, kC, and kH. +func (cl Color) DistanceCIEDE2000klch(cr Color, kl, kc, kh float64) float64 { + l1, a1, b1 := cl.Lab() + l2, a2, b2 := cr.Lab() + + // As with CIE94, we scale up the ranges of L,a,b beforehand and scale + // them down again afterwards. + l1, a1, b1 = l1*100.0, a1*100.0, b1*100.0 + l2, a2, b2 = l2*100.0, a2*100.0, b2*100.0 + + cab1 := math.Sqrt(sq(a1) + sq(b1)) + cab2 := math.Sqrt(sq(a2) + sq(b2)) + cabmean := (cab1 + cab2) / 2 + + g := 0.5 * (1 - math.Sqrt(math.Pow(cabmean, 7)/(math.Pow(cabmean, 7)+math.Pow(25, 7)))) + ap1 := (1 + g) * a1 + ap2 := (1 + g) * a2 + cp1 := math.Sqrt(sq(ap1) + sq(b1)) + cp2 := math.Sqrt(sq(ap2) + sq(b2)) + + hp1 := 0.0 + if b1 != ap1 || ap1 != 0 { + hp1 = math.Atan2(b1, ap1) + if hp1 < 0 { + hp1 += math.Pi * 2 + } + hp1 *= 180 / math.Pi + } + hp2 := 0.0 + if b2 != ap2 || ap2 != 0 { + hp2 = math.Atan2(b2, ap2) + if hp2 < 0 { + hp2 += math.Pi * 2 + } + hp2 *= 180 / math.Pi + } + + deltaLp := l2 - l1 + deltaCp := cp2 - cp1 + dhp := 0.0 + cpProduct := cp1 * cp2 + if cpProduct != 0 { + dhp = hp2 - hp1 + if dhp > 180 { + dhp -= 360 + } else if dhp < -180 { + dhp += 360 + } + } + deltaHp := 2 * math.Sqrt(cpProduct) * math.Sin(dhp/2*math.Pi/180) + + lpmean := (l1 + l2) / 2 + cpmean := (cp1 + cp2) / 2 + hpmean := hp1 + hp2 + if cpProduct != 0 { + hpmean /= 2 + if math.Abs(hp1-hp2) > 180 { + if hp1+hp2 < 360 { + hpmean += 180 + } else { + hpmean -= 180 + } + } + } + + t := 1 - 0.17*math.Cos((hpmean-30)*math.Pi/180) + 0.24*math.Cos(2*hpmean*math.Pi/180) + 0.32*math.Cos((3*hpmean+6)*math.Pi/180) - 0.2*math.Cos((4*hpmean-63)*math.Pi/180) + deltaTheta := 30 * math.Exp(-sq((hpmean-275)/25)) + rc := 2 * math.Sqrt(math.Pow(cpmean, 7)/(math.Pow(cpmean, 7)+math.Pow(25, 7))) + sl := 1 + (0.015*sq(lpmean-50))/math.Sqrt(20+sq(lpmean-50)) + sc := 1 + 0.045*cpmean + sh := 1 + 0.015*cpmean*t + rt := -math.Sin(2*deltaTheta*math.Pi/180) * rc + + return math.Sqrt(sq(deltaLp/(kl*sl))+sq(deltaCp/(kc*sc))+sq(deltaHp/(kh*sh))+rt*(deltaCp/(kc*sc))*(deltaHp/(kh*sh))) * 0.01 +} + +// BlendLab blends two colors in the L*a*b* color-space, which should result in a smoother blend. +// t == 0 results in c1, t == 1 results in c2 +func (c1 Color) BlendLab(c2 Color, t float64) Color { + l1, a1, b1 := c1.Lab() + l2, a2, b2 := c2.Lab() + return Lab(l1+t*(l2-l1), + a1+t*(a2-a1), + b1+t*(b2-b1)) +} + +/// L*u*v* /// +////////////// +// http://en.wikipedia.org/wiki/CIELUV#XYZ_.E2.86.92_CIELUV_and_CIELUV_.E2.86.92_XYZ_conversions +// For L*u*v*, we need to L*u*v*<->XYZ<->RGB and the first one is device dependent. + +func XyzToLuv(x, y, z float64) (l, a, b float64) { + // Use D65 white as reference point by default. + // http://www.fredmiranda.com/forum/topic/1035332 + // http://en.wikipedia.org/wiki/Standard_illuminant + return XyzToLuvWhiteRef(x, y, z, D65) +} + +func XyzToLuvWhiteRef(x, y, z float64, wref [3]float64) (l, u, v float64) { + if y/wref[1] <= 6.0/29.0*6.0/29.0*6.0/29.0 { + l = y / wref[1] * (29.0 / 3.0 * 29.0 / 3.0 * 29.0 / 3.0) / 100.0 + } else { + l = 1.16*math.Cbrt(y/wref[1]) - 0.16 + } + ubis, vbis := xyz_to_uv(x, y, z) + un, vn := xyz_to_uv(wref[0], wref[1], wref[2]) + u = 13.0 * l * (ubis - un) + v = 13.0 * l * (vbis - vn) + return +} + +// For this part, we do as R's graphics.hcl does, not as wikipedia does. +// Or is it the same? +func xyz_to_uv(x, y, z float64) (u, v float64) { + denom := x + 15.0*y + 3.0*z + if denom == 0.0 { + u, v = 0.0, 0.0 + } else { + u = 4.0 * x / denom + v = 9.0 * y / denom + } + return +} + +func LuvToXyz(l, u, v float64) (x, y, z float64) { + // D65 white (see above). + return LuvToXyzWhiteRef(l, u, v, D65) +} + +func LuvToXyzWhiteRef(l, u, v float64, wref [3]float64) (x, y, z float64) { + //y = wref[1] * lab_finv((l + 0.16) / 1.16) + if l <= 0.08 { + y = wref[1] * l * 100.0 * 3.0 / 29.0 * 3.0 / 29.0 * 3.0 / 29.0 + } else { + y = wref[1] * cub((l+0.16)/1.16) + } + un, vn := xyz_to_uv(wref[0], wref[1], wref[2]) + if l != 0.0 { + ubis := u/(13.0*l) + un + vbis := v/(13.0*l) + vn + x = y * 9.0 * ubis / (4.0 * vbis) + z = y * (12.0 - 3.0*ubis - 20.0*vbis) / (4.0 * vbis) + } else { + x, y = 0.0, 0.0 + } + return +} + +// Converts the given color to CIE L*u*v* space using D65 as reference white. +// L* is in [0..1] and both u* and v* are in about [-1..1] +func (col Color) Luv() (l, u, v float64) { + return XyzToLuv(col.Xyz()) +} + +// Converts the given color to CIE L*u*v* space, taking into account +// a given reference white. (i.e. the monitor's white) +// L* is in [0..1] and both u* and v* are in about [-1..1] +func (col Color) LuvWhiteRef(wref [3]float64) (l, u, v float64) { + x, y, z := col.Xyz() + return XyzToLuvWhiteRef(x, y, z, wref) +} + +// Generates a color by using data given in CIE L*u*v* space using D65 as reference white. +// L* is in [0..1] and both u* and v* are in about [-1..1] +// WARNING: many combinations of `l`, `u`, and `v` values do not have corresponding +// valid RGB values, check the FAQ in the README if you're unsure. +func Luv(l, u, v float64) Color { + return Xyz(LuvToXyz(l, u, v)) +} + +// Generates a color by using data given in CIE L*u*v* space, taking +// into account a given reference white. (i.e. the monitor's white) +// L* is in [0..1] and both u* and v* are in about [-1..1] +func LuvWhiteRef(l, u, v float64, wref [3]float64) Color { + return Xyz(LuvToXyzWhiteRef(l, u, v, wref)) +} + +// DistanceLuv is a good measure of visual similarity between two colors! +// A result of 0 would mean identical colors, while a result of 1 or higher +// means the colors differ a lot. +func (c1 Color) DistanceLuv(c2 Color) float64 { + l1, u1, v1 := c1.Luv() + l2, u2, v2 := c2.Luv() + return math.Sqrt(sq(l1-l2) + sq(u1-u2) + sq(v1-v2)) +} + +// BlendLuv blends two colors in the CIE-L*u*v* color-space, which should result in a smoother blend. +// t == 0 results in c1, t == 1 results in c2 +func (c1 Color) BlendLuv(c2 Color, t float64) Color { + l1, u1, v1 := c1.Luv() + l2, u2, v2 := c2.Luv() + return Luv(l1+t*(l2-l1), + u1+t*(u2-u1), + v1+t*(v2-v1)) +} + +/// HCL /// +/////////// +// HCL is nothing else than L*a*b* in cylindrical coordinates! +// (this was wrong on English wikipedia, I fixed it, let's hope the fix stays.) +// But it is widely popular since it is a "correct HSV" +// http://www.hunterlab.com/appnotes/an09_96a.pdf + +// Converts the given color to HCL space using D65 as reference white. +// H values are in [0..360], C and L values are in [0..1] although C can overshoot 1.0 +func (col Color) Hcl() (h, c, l float64) { + return col.HclWhiteRef(D65) +} + +func LabToHcl(L, a, b float64) (h, c, l float64) { + // Oops, floating point workaround necessary if a ~= b and both are very small (i.e. almost zero). + if math.Abs(b-a) > 1e-4 && math.Abs(a) > 1e-4 { + h = math.Mod(57.29577951308232087721*math.Atan2(b, a)+360.0, 360.0) // Rad2Deg + } else { + h = 0.0 + } + c = math.Sqrt(sq(a) + sq(b)) + l = L + return +} + +// Converts the given color to HCL space, taking into account +// a given reference white. (i.e. the monitor's white) +// H values are in [0..360], C and L values are in [0..1] +func (col Color) HclWhiteRef(wref [3]float64) (h, c, l float64) { + L, a, b := col.LabWhiteRef(wref) + return LabToHcl(L, a, b) +} + +// Generates a color by using data given in HCL space using D65 as reference white. +// H values are in [0..360], C and L values are in [0..1] +// WARNING: many combinations of `h`, `c`, and `l` values do not have corresponding +// valid RGB values, check the FAQ in the README if you're unsure. +func Hcl(h, c, l float64) Color { + return HclWhiteRef(h, c, l, D65) +} + +func HclToLab(h, c, l float64) (L, a, b float64) { + H := 0.01745329251994329576 * h // Deg2Rad + a = c * math.Cos(H) + b = c * math.Sin(H) + L = l + return +} + +// Generates a color by using data given in HCL space, taking +// into account a given reference white. (i.e. the monitor's white) +// H values are in [0..360], C and L values are in [0..1] +func HclWhiteRef(h, c, l float64, wref [3]float64) Color { + L, a, b := HclToLab(h, c, l) + return LabWhiteRef(L, a, b, wref) +} + +// BlendHcl blends two colors in the CIE-L*C*h° color-space, which should result in a smoother blend. +// t == 0 results in c1, t == 1 results in c2 +func (col1 Color) BlendHcl(col2 Color, t float64) Color { + h1, c1, l1 := col1.Hcl() + h2, c2, l2 := col2.Hcl() + + // We know that h are both in [0..360] + return Hcl(interp_angle(h1, h2, t), c1+t*(c2-c1), l1+t*(l2-l1)).Clamped() +} + +// LuvLch + +// Converts the given color to LuvLCh space using D65 as reference white. +// h values are in [0..360], C and L values are in [0..1] although C can overshoot 1.0 +func (col Color) LuvLCh() (l, c, h float64) { + return col.LuvLChWhiteRef(D65) +} + +func LuvToLuvLCh(L, u, v float64) (l, c, h float64) { + // Oops, floating point workaround necessary if u ~= v and both are very small (i.e. almost zero). + if math.Abs(v-u) > 1e-4 && math.Abs(u) > 1e-4 { + h = math.Mod(57.29577951308232087721*math.Atan2(v, u)+360.0, 360.0) // Rad2Deg + } else { + h = 0.0 + } + l = L + c = math.Sqrt(sq(u) + sq(v)) + return +} + +// Converts the given color to LuvLCh space, taking into account +// a given reference white. (i.e. the monitor's white) +// h values are in [0..360], c and l values are in [0..1] +func (col Color) LuvLChWhiteRef(wref [3]float64) (l, c, h float64) { + return LuvToLuvLCh(col.LuvWhiteRef(wref)) +} + +// Generates a color by using data given in LuvLCh space using D65 as reference white. +// h values are in [0..360], C and L values are in [0..1] +// WARNING: many combinations of `l`, `c`, and `h` values do not have corresponding +// valid RGB values, check the FAQ in the README if you're unsure. +func LuvLCh(l, c, h float64) Color { + return LuvLChWhiteRef(l, c, h, D65) +} + +func LuvLChToLuv(l, c, h float64) (L, u, v float64) { + H := 0.01745329251994329576 * h // Deg2Rad + u = c * math.Cos(H) + v = c * math.Sin(H) + L = l + return +} + +// Generates a color by using data given in LuvLCh space, taking +// into account a given reference white. (i.e. the monitor's white) +// h values are in [0..360], C and L values are in [0..1] +func LuvLChWhiteRef(l, c, h float64, wref [3]float64) Color { + L, u, v := LuvLChToLuv(l, c, h) + return LuvWhiteRef(L, u, v, wref) +} + +// BlendLuvLCh blends two colors in the cylindrical CIELUV color space. +// t == 0 results in c1, t == 1 results in c2 +func (col1 Color) BlendLuvLCh(col2 Color, t float64) Color { + l1, c1, h1 := col1.LuvLCh() + l2, c2, h2 := col2.LuvLCh() + + // We know that h are both in [0..360] + return LuvLCh(l1+t*(l2-l1), c1+t*(c2-c1), interp_angle(h1, h2, t)) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go new file mode 100644 index 00000000..bb66dfa4 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/happy_palettegen.go @@ -0,0 +1,25 @@ +package colorful + +import ( + "math/rand" +) + +// Uses the HSV color space to generate colors with similar S,V but distributed +// evenly along their Hue. This is fast but not always pretty. +// If you've got time to spare, use Lab (the non-fast below). +func FastHappyPalette(colorsCount int) (colors []Color) { + colors = make([]Color, colorsCount) + + for i := 0; i < colorsCount; i++ { + colors[i] = Hsv(float64(i)*(360.0/float64(colorsCount)), 0.8+rand.Float64()*0.2, 0.65+rand.Float64()*0.2) + } + return +} + +func HappyPalette(colorsCount int) ([]Color, error) { + pimpy := func(l, a, b float64) bool { + _, c, _ := LabToHcl(l, a, b) + return 0.3 <= c && 0.4 <= l && l <= 0.8 + } + return SoftPaletteEx(colorsCount, SoftPaletteSettings{pimpy, 50, true}) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go b/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go new file mode 100644 index 00000000..76f31d8f --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/hexcolor.go @@ -0,0 +1,67 @@ +package colorful + +import ( + "database/sql/driver" + "encoding/json" + "fmt" + "reflect" +) + +// A HexColor is a Color stored as a hex string "#rrggbb". It implements the +// database/sql.Scanner, database/sql/driver.Value, +// encoding/json.Unmarshaler and encoding/json.Marshaler interfaces. +type HexColor Color + +type errUnsupportedType struct { + got interface{} + want reflect.Type +} + +func (hc *HexColor) Scan(value interface{}) error { + s, ok := value.(string) + if !ok { + return errUnsupportedType{got: reflect.TypeOf(value), want: reflect.TypeOf("")} + } + c, err := Hex(s) + if err != nil { + return err + } + *hc = HexColor(c) + return nil +} + +func (hc *HexColor) Value() (driver.Value, error) { + return Color(*hc).Hex(), nil +} + +func (e errUnsupportedType) Error() string { + return fmt.Sprintf("unsupported type: got %v, want a %s", e.got, e.want) +} + +func (hc *HexColor) UnmarshalJSON(data []byte) error { + var hexCode string + if err := json.Unmarshal(data, &hexCode); err != nil { + return err + } + + var col, err = Hex(hexCode) + if err != nil { + return err + } + *hc = HexColor(col) + return nil +} + +func (hc HexColor) MarshalJSON() ([]byte, error) { + return json.Marshal(Color(hc).Hex()) +} + +// Decode - deserialize function for https://github.com/kelseyhightower/envconfig +func (hc *HexColor) Decode(hexCode string) error { + var col, err = Hex(hexCode) + if err != nil { + return err + } + *hc = HexColor(col) + return nil +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/hsluv-snapshot-rev4.json b/vendor/github.com/lucasb-eyer/go-colorful/hsluv-snapshot-rev4.json new file mode 100644 index 00000000..16354abf --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/hsluv-snapshot-rev4.json @@ -0,0 +1 @@ +{"#11ee00":{"lch":[82.5213119008325577,127.202882727266427,127.478988192005161],"luv":[82.5213119008325577,-77.3991947082883627,100.945222931227221],"rgb":[0.0666666666666666657,0.933333333333333348,0],"xyz":[0.308043578886299796,0.612655858810891907,0.102019012460713238],"hpluv":[127.478988192005161,308.195222762673438,82.5213119008325577],"hsluv":[127.478988192005161,100.000000000002416,82.5213119008325577]},"#11ee11":{"lch":[82.5429986110943759,126.352581314528209,127.715012949240403],"luv":[82.5429986110943759,-77.2942129186682,99.9528861720763473],"rgb":[0.0666666666666666657,0.933333333333333348,0.0666666666666666657],"xyz":[0.3090552443859369,0.613060525010746815,0.107347117425468874],"hpluv":[127.715012949240403,306.573296560288782,82.5429986110943759],"hsluv":[127.715012949240403,98.9038130800949205,82.5429986110943759]},"#11ee22":{"lch":[82.5831747617793184,124.791738379333623,128.158354445562821],"luv":[82.5831747617793184,-77.1009570540098,98.1245147202868253],"rgb":[0.0666666666666666657,0.933333333333333348,0.133333333333333331],"xyz":[0.310930602524413957,0.613810668266137616,0.117224003621448067],"hpluv":[128.158354445562821,303.59085997924285,82.5831747617793184],"hsluv":[128.158354445562821,98.9085620232469864,82.5831747617793184]},"#11ee33":{"lch":[82.6492529720821381,122.265269823008623,128.905098358231896],"luv":[82.6492529720821381,-76.7865393115689301,95.1452762119380537],"rgb":[0.0666666666666666657,0.933333333333333348,0.2],"xyz":[0.314018353256871663,0.615045768559120742,0.133486157479059203],"hpluv":[128.905098358231896,298.749143147736106,82.6492529720821381],"hsluv":[128.905098358231896,98.916292078887,82.6492529720821381]},"#11ee44":{"lch":[82.7444986901015511,118.712635154498344,130.021230388522838],"luv":[82.7444986901015511,-76.3407023620842,90.9108734321077],"rgb":[0.0666666666666666657,0.933333333333333348,0.266666666666666663],"xyz":[0.318476348501090578,0.616828966656808308,0.156964932431945842],"hpluv":[130.021230388522838,291.911386756693616,82.7444986901015511],"hsluv":[130.021230388522838,98.9272612770947148,82.7444986901015511]},"#11ee55":{"lch":[82.8716000285422894,114.135934527262179,131.587310643629934],"luv":[82.8716000285422894,-75.758934185545,85.3674144008224],"rgb":[0.0666666666666666657,0.933333333333333348,0.333333333333333315],"xyz":[0.324438762540452563,0.619213932272553058,0.188366979705919757],"hpluv":[131.587310643629934,283.052591495130912,82.8716000285422894],"hsluv":[131.587310643629934,98.941589727101146,82.8716000285422894]},"#11ee66":{"lch":[83.0328193013522622,108.602333046050703,133.707640253052432],"luv":[83.0328193013522622,-75.0419109433949103,78.5059128028513697],"rgb":[0.0666666666666666657,0.933333333333333348,0.4],"xyz":[0.332023758313960748,0.622247930581956377,0.228314624113063719],"hpluv":[133.707640253052432,272.269449526145593,83.0328193013522622],"hsluv":[133.707640253052432,98.9592735060659,83.0328193013522622]},"#11ee77":{"lch":[83.2300736177455747,102.250357200027821,136.520544097163679],"luv":[83.2300736177455747,-74.1950209885278866,70.3579022430685228],"rgb":[0.0666666666666666657,0.933333333333333348,0.466666666666666674],"xyz":[0.341337771334162654,0.625973535790037228,0.277368426019461656],"hpluv":[136.520544097163679,259.803949175129901,83.2300736177455747],"hsluv":[136.520544097163679,98.9801962733070155,83.2300736177455747]},"#11ee88":{"lch":[83.4649827070576151,95.3003261118453651,140.209511574476238],"luv":[83.4649827070576151,-73.2277962837693082,60.990507527375577],"rgb":[0.0666666666666666657,0.933333333333333348,0.533333333333333326],"xyz":[0.352478188436106454,0.63042970263081477,0.336041289423033795],"hpluv":[140.209511574476238,246.084644167270028,83.4649827070576151],"hsluv":[140.209511574476238,99.0041428894333109,83.4649827070576151]},"#11ee99":{"lch":[83.7388997377875626,88.07037792773761,145.011549795441141],"luv":[83.7388997377875626,-72.1532115864445416,50.5005497603372433],"rgb":[0.0666666666666666657,0.933333333333333348,0.6],"xyz":[0.365535152545179209,0.635652488274444,0.404807967064151675],"hpluv":[145.011549795441141,231.793725377578141,83.7388997377875626],"hsluv":[145.011549795441141,99.0308160530368582,83.7388997377875626]},"#11eeaa":{"lch":[84.0529327571252907,80.9984265129003802,151.210882439188083],"luv":[84.0529327571252907,-70.9868724309634729,39.0078074241021824],"rgb":[0.0666666666666666657,0.933333333333333348,0.66666666666666663],"xyz":[0.38059284551043171,0.641675565460545,0.484111816681150331],"hpluv":[151.210882439188083,217.967504021816438,84.0529327571252907],"hsluv":[151.210882439188083,99.0598554997167895,84.0529327571252907]},"#11eebb":{"lch":[84.4079608499599914,74.6634505604909435,159.089705667287262],"luv":[84.4079608499599914,-69.7461428935043273,26.6478216947980826],"rgb":[0.0666666666666666657,0.933333333333333348,0.733333333333333282],"xyz":[0.397730437617768384,0.648530602303479808,0.574369801779792],"hpluv":[159.089705667287262,206.122134265545043,84.4079608499599914],"hsluv":[159.089705667287262,99.0908585861444209,84.4079608499599914]},"#11eecc":{"lch":[84.8046473826435,69.7804076798411,168.790807110150524],"luv":[84.8046473826435,-68.449275126866155,13.5647348138992196],"rgb":[0.0666666666666666657,0.933333333333333348,0.8],"xyz":[0.417022813061490139,0.656247552480968666,0.675976312450062178],"hpluv":[168.790807110150524,198.342538571842852,84.8046473826435],"hsluv":[168.790807110150524,99.123400814408285,84.8046473826435]},"#11eedd":{"lch":[85.2434517572140749,67.1146678094459,180.081412911690762],"luv":[85.2434517572140749,-67.114600056421537,-0.0953647673755886743],"rgb":[0.0666666666666666657,0.933333333333333348,0.866666666666666696],"xyz":[0.438541138612123627,0.664854882701222172,0.789306160350068176],"hpluv":[180.081412911690762,197.173954094180345,85.2434517572140749],"hsluv":[180.081412911690762,99.1570549081779546,85.2434517572140749]},"#11eeee":{"lch":[85.7246405502341275,67.2734484234975,192.17705063006116],"luv":[85.7246405502341275,-65.759826803247222,-14.1902093570146306],"rgb":[0.0666666666666666657,0.933333333333333348,0.933333333333333348],"xyz":[0.462353318878298392,0.674379754807692189,0.914716976418591399],"hpluv":[192.17705063006116,205.138082793863816,85.7246405502341275],"hsluv":[192.17705063006116,99.1914073274009098,85.7246405502341275]},"#11eeff":{"lch":[86.2482985645723517,70.4606934075819282,203.935071880927921],"luv":[86.2482985645723517,-64.401481656171029,-28.585983907627277],"rgb":[0.0666666666666666657,0.933333333333333348,1],"xyz":[0.488524367288129757,0.684848174171624913,1.05255116471037335],"hpluv":[203.935071880927921,224.026806300523,86.2482985645723517],"hsluv":[203.935071880927921,99.9999999999942304,86.2482985645723517]},"#11ff00":{"lch":[87.7931168603164,135.408535196841626,127.513270797457935],"luv":[87.7931168603164,-82.4563732780469,107.407718111808407],"rgb":[0.0666666666666666657,1,0],"xyz":[0.359895951315973628,0.716360603670241,0.119303136603937349],"hpluv":[127.513270797457935,491.310985978769054,87.7931168603164],"hsluv":[127.513270797457935,100.000000000002373,87.7931168603164]},"#11ff11":{"lch":[87.8126571401035108,134.634318462908169,127.715012949240432],"luv":[87.8126571401035108,-82.3604359259359313,106.50426424355777],"rgb":[0.0666666666666666657,1,0.0666666666666666657],"xyz":[0.360907616815610732,0.716765269870095922,0.124631241568692985],"hpluv":[127.715012949240432,489.364334505449051,87.8126571401035108],"hsluv":[127.715012949240432,99.999999999991914,87.8126571401035108]},"#11ff22":{"lch":[87.848860165327963,133.211117719966126,128.093229681784152],"luv":[87.848860165327963,-82.1836510367646,104.838205757586152],"rgb":[0.0666666666666666657,1,0.133333333333333331],"xyz":[0.362782974954087789,0.717515413125486723,0.134508127764672164],"hpluv":[128.093229681784152,485.7796458877379,87.848860165327963],"hsluv":[128.093229681784152,99.9999999999918572,87.848860165327963]},"#11ff33":{"lch":[87.9084130007832698,130.901693692038833,128.728166832562891],"luv":[87.9084130007832698,-81.8955348861488659,102.119414300885666],"rgb":[0.0666666666666666657,1,0.2],"xyz":[0.365870725686545495,0.71875051341846985,0.150770281622283314],"hpluv":[128.728166832562891,479.945632467831388,87.9084130007832698],"hsluv":[128.728166832562891,99.9999999999919567,87.9084130007832698]},"#11ff44":{"lch":[87.9942732352876,127.641489512823171,129.672386074694657],"luv":[87.9942732352876,-81.4859348177847806,98.2465891108891185],"rgb":[0.0666666666666666657,1,0.266666666666666663],"xyz":[0.37032872093076441,0.720533711516157416,0.174249056575169953],"hpluv":[129.672386074694657,471.674193406224788,87.9942732352876],"hsluv":[129.672386074694657,99.9999999999918856,87.9942732352876]},"#11ff55":{"lch":[88.1088871723243727,123.41738800901625,130.987994113812931],"luv":[88.1088871723243727,-80.9495722978130772,93.1612494966077662],"rgb":[0.0666666666666666657,1,0.333333333333333315],"xyz":[0.376291134970126395,0.722918677131902165,0.205651103849143868],"hpluv":[130.987994113812931,460.897243009671797,88.1088871723243727],"hsluv":[130.987994113812931,99.9999999999917,88.1088871723243727]},"#11ff66":{"lch":[88.2543278429396,118.268592142924746,132.753132104158254],"luv":[88.2543278429396,-80.2855559529031382,86.8429006471038],"rgb":[0.0666666666666666657,1,0.4],"xyz":[0.38387613074363458,0.725952675441305484,0.24559874825628783],"hpluv":[132.753132104158254,447.675525940365219,88.2543278429396],"hsluv":[132.753132104158254,99.9999999999916724,88.2543278429396]},"#11ff77":{"lch":[88.4323687925046613,112.290518027227137,135.069051083024959],"luv":[88.4323687925046613,-79.4970211443964558,79.3056370505300521],"rgb":[0.0666666666666666657,1,0.466666666666666674],"xyz":[0.393190143763836486,0.729678280649386335,0.294652550162685767],"hpluv":[135.069051083024959,432.222948715922314,88.4323687925046613],"hsluv":[135.069051083024959,99.999999999991644,88.4323687925046613]},"#11ff88":{"lch":[88.6445280109338825,105.641380676940045,138.068036362648229],"luv":[88.6445280109338825,-78.5907289650887577,70.5946076698930369],"rgb":[0.0666666666666666657,1,0.533333333333333326],"xyz":[0.404330560865780286,0.734134447490163877,0.353325413566257907],"hpluv":[138.068036362648229,414.95023459347243,88.6445280109338825],"hsluv":[138.068036362648229,99.9999999999915,88.6445280109338825]},"#11ff99":{"lch":[88.8920961876840465,98.552301258979881,141.921030988541872],"luv":[88.8920961876840465,-77.5765731609304225,60.7818342932124338],"rgb":[0.0666666666666666657,1,0.6],"xyz":[0.417387524974853,0.73935723313379309,0.422092091207375786],"hpluv":[141.921030988541872,396.537381185702543,88.8920961876840465],"hsluv":[141.921030988541872,99.9999999999913456,88.8920961876840465]},"#11ffaa":{"lch":[89.1761561490339147,91.3418654410923523,146.840553381528281],"luv":[89.1761561490339147,-76.4669946123218,49.9613362233014158],"rgb":[0.0666666666666666657,1,0.66666666666666663],"xyz":[0.432445217940105542,0.745380310319894157,0.501395940824374442],"hpluv":[146.840553381528281,378.048392077141443,89.1761561490339147],"hsluv":[146.840553381528281,99.9999999999913,89.1761561490339147]},"#11ffbb":{"lch":[89.4975971674113,84.4340589142561413,153.067388238784645],"luv":[89.4975971674113,-75.2763296710648859,38.2437510711127],"rgb":[0.0666666666666666657,1,0.733333333333333282],"xyz":[0.449582810047442216,0.752235347162828916,0.591653925923016133],"hpluv":[153.067388238784645,361.099415032935838,89.4975971674113],"hsluv":[153.067388238784645,99.9999999999909335,89.4975971674113]},"#11ffcc":{"lch":[89.8571262823018628,78.3714319324892159,160.817799258328876],"luv":[89.8571262823018628,-74.0201316086282901,25.7507564896672143],"rgb":[0.0666666666666666657,1,0.8],"xyz":[0.468875185491163915,0.759952297340317773,0.693260436593286289],"hpluv":[160.817799258328876,348.067615225706845,89.8571262823018628],"hsluv":[160.817799258328876,99.999999999991,89.8571262823018628]},"#11ffdd":{"lch":[90.2552779380141317,73.7997451229305,170.162013498752287],"luv":[90.2552779380141317,-72.7145076797264238,12.6096293801408788],"rgb":[0.0666666666666666657,1,0.866666666666666696],"xyz":[0.490393511041797514,0.768559627560571279,0.806590284493292287],"hpluv":[170.162013498752287,342.256686666565315,90.2552779380141317],"hsluv":[170.162013498752287,99.999999999990834,90.2552779380141317]},"#11ffee":{"lch":[90.6924227584195819,71.3832589696730793,180.844217403257659],"luv":[90.6924227584195819,-71.3755103944163665,-1.05174952720347981],"rgb":[0.0666666666666666657,1,0.933333333333333348],"xyz":[0.514205691307972224,0.778084499667041296,0.93200110056181551],"hpluv":[180.844217403257659,347.82122947809512,90.6924227584195819],"hsluv":[180.844217403257659,99.9999999999901803,90.6924227584195819]},"#11ffff":{"lch":[91.1687759776689859,71.6302608322469467,192.17705063006116],"luv":[91.1687759776689859,-70.0186129384549361,-15.1092061032524665],"rgb":[0.0666666666666666657,1,1],"xyz":[0.540376739717803645,0.788552919030974,1.06983528885359735],"hpluv":[192.17705063006116,369.258709956275879,91.1687759776689859],"hsluv":[192.17705063006116,99.9999999999898108,91.1687759776689859]},"#00aa00":{"lch":[60.5587499434736287,93.727653253516209,127.71501294924046],"luv":[60.5587499434736287,-57.3364240886418415,74.1445038903004559],"rgb":[0,0.66666666666666663,0],"xyz":[0.143740958848290495,0.287481917696585,0.0479136529494288144],"hpluv":[127.71501294924046,196.394882900214554,60.5587499434736287],"hsluv":[127.71501294924046,100.000000000002359,60.5587499434736287]},"#00aa11":{"lch":[60.5946550577951939,92.4075267438518182,128.220974416403209],"luv":[60.5946550577951939,-57.1721703645967665,72.5981675713458543],"rgb":[0,0.66666666666666663,0.0666666666666666657],"xyz":[0.144752624347927628,0.28788658389643984,0.0532417579141844441],"hpluv":[128.220974416403209,193.513984665985475,60.5946550577951939],"hsluv":[128.220974416403209,99.9999999999907772,60.5946550577951939]},"#00aa22":{"lch":[60.661124672570665,90.0113827545795715,129.185497299711983],"luv":[60.661124672570665,-56.8721735728637725,69.7682226983709199],"rgb":[0,0.66666666666666663,0.133333333333333331],"xyz":[0.146627982486404629,0.288636727151830641,0.0631186441101636436],"hpluv":[129.185497299711983,188.289586599726533,60.661124672570665],"hsluv":[129.185497299711983,99.9999999999908624,60.661124672570665]},"#00aa33":{"lch":[60.7703154938824355,86.2098857925288513,130.852037745481823],"luv":[60.7703154938824355,-56.3905639077229353,65.2092685937350751],"rgb":[0,0.66666666666666663,0.2],"xyz":[0.14971573321886239,0.289871827444813768,0.0793807979677747799],"hpluv":[130.852037745481823,180.013429236819462,60.7703154938824355],"hsluv":[130.852037745481823,99.9999999999908,60.7703154938824355]},"#00aa44":{"lch":[60.9274158721733841,81.0355822964375108,133.441426631804489],"luv":[60.9274158721733841,-55.7210928860807044,58.8381288426430444],"rgb":[0,0.66666666666666663,0.266666666666666663],"xyz":[0.15417372846308125,0.291655025542501334,0.102859572920661418],"hpluv":[133.441426631804489,168.77274926729055,60.9274158721733841],"hsluv":[133.441426631804489,99.9999999999908908,60.9274158721733841]},"#00aa55":{"lch":[61.1365343944832915,74.6960845180523592,137.272019015051796],"luv":[61.1365343944832915,-54.8704978500827636,50.6826746335676717],"rgb":[0,0.66666666666666663,0.333333333333333315],"xyz":[0.160136142502443235,0.294039991158246194,0.134261620194635334],"hpluv":[137.272019015051796,155.037353806827582,61.1365343944832915],"hsluv":[137.272019015051796,99.9999999999910614,61.1365343944832915]},"#00aa66":{"lch":[61.4009335299549264,67.6053275851037512,142.80970662058607],"luv":[61.4009335299549264,-53.8565898531593703,40.8649978254956139],"rgb":[0,0.66666666666666663,0.4],"xyz":[0.16772113827595142,0.297073989467649513,0.174209264601779296],"hpluv":[142.80970662058607,139.715720243970395,61.4009335299549264],"hsluv":[142.80970662058607,99.9999999999911893,61.4009335299549264]},"#00aa77":{"lch":[61.7231520087844814,60.4394033477847188,150.696962972825474],"luv":[61.7231520087844814,-52.7057786154446859,29.5807771631501382],"rgb":[0,0.66666666666666663,0.466666666666666674],"xyz":[0.177035151296153326,0.300799594675730309,0.223263066508177205],"hpluv":[150.696962972825474,124.254291935777843,61.7231520087844814],"hsluv":[150.696962972825474,99.9999999999911893,61.7231520087844814]},"#00aa88":{"lch":[62.1050795642419615,54.2095218153359397,161.640221068188367],"luv":[62.1050795642419615,-51.4501140589855126,17.0750700954568337],"rgb":[0,0.66666666666666663,0.533333333333333326],"xyz":[0.188175568398097182,0.305255761516507906,0.281935929911749372],"hpluv":[161.640221068188367,110.761232665855573,62.1050795642419615],"hsluv":[161.640221068188367,99.9999999999911466,62.1050795642419615]},"#00aa99":{"lch":[62.5480102999456307,50.2545412813378576,175.872445658321794],"luv":[62.5480102999456307,-50.1241952468173793,3.61717711159146882],"rgb":[0,0.66666666666666663,0.6],"xyz":[0.201232532507169881,0.310478547160137064,0.350702607552867307],"hpluv":[175.872445658321794,101.95326553071466,62.5480102999456307],"hsluv":[175.872445658321794,99.9999999999913314,62.5480102999456307]},"#00aaaa":{"lch":[63.0526871437625829,49.8847230087107931,192.17705063006116],"luv":[63.0526871437625829,-48.762339705407328,-10.5223484123201398],"rgb":[0,0.66666666666666663,0.66666666666666663],"xyz":[0.216290225472422437,0.316501624346238186,0.430006457169865852],"hpluv":[192.17705063006116,100.392967527320806,63.0526871437625829],"hsluv":[192.17705063006116,99.9999999999914451,63.0526871437625829]},"#00aabb":{"lch":[63.6193436646561565,53.6276681768737,207.895374658889665],"luv":[63.6193436646561565,-47.3963155750249143,-25.0901587081772526],"rgb":[0,0.66666666666666663,0.733333333333333282],"xyz":[0.233427817579759056,0.323356661189172945,0.520264442268507654],"hpluv":[207.895374658889665,106.964349821245364,63.6193436646561565],"hsluv":[207.895374658889665,99.9999999999916,63.6193436646561565]},"#00aacc":{"lch":[64.2477463386430259,60.9097449106327886,220.878520684721707],"luv":[64.2477463386430259,-46.0537892020538,-39.8628338833449],"rgb":[0,0.66666666666666663,0.8],"xyz":[0.25272019302348081,0.331073611366661746,0.62187095293877781],"hpluv":[220.878520684721707,120.300715116377788,64.2477463386430259],"hsluv":[220.878520684721707,99.9999999999916298,64.2477463386430259]},"#00aadd":{"lch":[64.9372385342214926,70.6418801813473465,230.685034316882962],"luv":[64.9372385342214926,-44.7574928469198525,-54.6538385624811625],"rgb":[0,0.66666666666666663,0.866666666666666696],"xyz":[0.274238518574114354,0.339680941586915253,0.735200800838783808],"hpluv":[230.685034316882962,138.04089297290011,64.9372385342214926],"hsluv":[230.685034316882962,99.9999999999918145,64.9372385342214926]},"#00aaee":{"lch":[65.6867863979168618,81.8478503674051,237.87423205753521],"luv":[65.6867863979168618,-43.5250094774703129,-69.3155405356638283],"rgb":[0,0.66666666666666663,0.933333333333333348],"xyz":[0.298050698840289119,0.34920581369338527,0.860611616907307],"hpluv":[237.87423205753521,158.11336767521891,65.6867863979168618],"hsluv":[237.87423205753521,99.999999999991843,65.6867863979168618]},"#00aaff":{"lch":[66.4950261675888,93.8462134827344,243.161780722675303],"luv":[66.4950261675888,-42.369016683119284,-83.7375555551541],"rgb":[0,0.66666666666666663,1],"xyz":[0.324221747250120484,0.359674233057318,0.998445805199088876],"hpluv":[243.161780722675303,179.088178632175044,66.4950261675888],"hsluv":[243.161780722675303,99.9999999999982805,66.4950261675888]},"#00bb00":{"lch":[66.1662429166961772,102.406451239047826,127.71501294924046],"luv":[66.1662429166961772,-62.6455428450044352,81.0099822060849135],"rgb":[0,0.733333333333333282,0],"xyz":[0.177695456756889275,0.355390913513783546,0.0592318189189614333],"hpluv":[127.71501294924046,196.39488290021464,66.1662429166961772],"hsluv":[127.71501294924046,100.000000000002373,66.1662429166961772]},"#00bb11":{"lch":[66.1974173108447559,101.237205455569821,128.123527834983577],"luv":[66.1974173108447559,-62.4996967519340956,79.6414444518024425],"rgb":[0,0.733333333333333282,0.0666666666666666657],"xyz":[0.178707122256526407,0.355795579713638399,0.064559923883717063],"hpluv":[128.123527834983577,194.061073356438868,66.1974173108447559],"hsluv":[128.123527834983577,99.9999999999909335,66.1974173108447559]},"#00bb22":{"lch":[66.2551438620851911,99.1062916374383747,128.898124119483072],"luv":[66.2551438620851911,-62.232564676438038,77.1308299962987718],"rgb":[0,0.733333333333333282,0.133333333333333331],"xyz":[0.180582480395003409,0.3565457229690292,0.0744368100796962556],"hpluv":[128.898124119483072,189.810813804630897,66.2551438620851911],"hsluv":[128.898124119483072,99.9999999999908624,66.2551438620851911]},"#00bb33":{"lch":[66.3500136661217255,95.7008075372637137,130.224174268563928],"luv":[66.3500136661217255,-61.8016571104716235,73.0698278476423155],"rgb":[0,0.733333333333333282,0.2],"xyz":[0.18367023112746117,0.357780823262012326,0.0906989639373074],"hpluv":[130.224174268563928,183.02647365261987,66.3500136661217255],"hsluv":[130.224174268563928,99.9999999999909335,66.3500136661217255]},"#00bb44":{"lch":[66.4865992404304,91.0092453899789859,132.255785626190885],"luv":[66.4865992404304,-61.1983980271068,67.3605138443080875],"rgb":[0,0.733333333333333282,0.266666666666666663],"xyz":[0.18812822637168003,0.359564021359699892,0.114177738890194044],"hpluv":[132.255785626190885,173.696361176634838,66.4865992404304],"hsluv":[132.255785626190885,99.9999999999909619,66.4865992404304]},"#00bb55":{"lch":[66.6685736373934219,85.1496193371524,135.204737263674588],"luv":[66.6685736373934219,-60.4246386982598,59.9943389949978751],"rgb":[0,0.733333333333333282,0.333333333333333315],"xyz":[0.194090640411042015,0.361948986975444753,0.145579786164167946],"hpluv":[135.204737263674588,162.069343805127659,66.6685736373934219],"hsluv":[135.204737263674588,99.9999999999909477,66.6685736373934219]},"#00bb66":{"lch":[66.8989180170192412,78.3861452968700689,139.371990675590268],"luv":[66.8989180170192412,-59.4914065933894,51.0407711152765629],"rgb":[0,0.733333333333333282,0.4],"xyz":[0.2016756361845502,0.364982985284848072,0.185527430571311908],"hpluv":[139.371990675590268,148.682392510907704,66.8989180170192412],"hsluv":[139.371990675590268,99.9999999999911182,66.8989180170192412]},"#00bb77":{"lch":[67.1800303821267448,71.1598447269708316,145.178146497089472],"luv":[67.1800303821267448,-58.4173559625633061,40.6341731047866617],"rgb":[0,0.733333333333333282,0.466666666666666674],"xyz":[0.210989649204752105,0.368708590492928867,0.234581232477709817],"hpluv":[145.178146497089472,134.410786503463328,67.1800303821267448],"hsluv":[145.178146497089472,99.9999999999910898,67.1800303821267448]},"#00bb88":{"lch":[67.5137905946342,64.1363411600919,153.159702568813543],"luv":[67.5137905946342,-57.2268359754185525,28.9578918715820954],"rgb":[0,0.733333333333333282,0.533333333333333326],"xyz":[0.222130066306695961,0.373164757333706465,0.293254095881282],"hpluv":[153.159702568813543,120.545503395456095,67.5137905946342],"hsluv":[153.159702568813543,99.9999999999911608,67.5137905946342]},"#00bb99":{"lch":[67.9016044714860811,58.2533417764790187,163.826150797364875],"luv":[67.9016044714860811,-55.9477282230567141,16.2266304205851419],"rgb":[0,0.733333333333333282,0.6],"xyz":[0.235187030415768661,0.378387542977335622,0.362020773522399919],"hpluv":[163.826150797364875,108.862958898475256,67.9016044714860811],"hsluv":[163.826150797364875,99.9999999999912461,67.9016044714860811]},"#00bbaa":{"lch":[68.3444379186728384,54.6744668749029543,177.202021912208522],"luv":[68.3444379186728384,-54.6092872876890922,2.66890801368250408],"rgb":[0,0.733333333333333282,0.66666666666666663],"xyz":[0.250244723381021217,0.384410620163436745,0.44132462313939852],"hpluv":[177.202021912208522,101.512776720033713,68.3444379186728384],"hsluv":[177.202021912208522,99.9999999999913598,68.3444379186728384]},"#00bbbb":{"lch":[68.8428468315880338,54.4656619866929645,192.177050630061132],"luv":[68.8428468315880338,-53.2402096652165113,-11.4886209116881091],"rgb":[0,0.733333333333333282,0.733333333333333282],"xyz":[0.267382315488357836,0.391265657006371503,0.531582608238040266],"hpluv":[192.177050630061132,100.392967527320806,68.8428468315880338],"hsluv":[192.177050630061132,99.9999999999914451,68.8428468315880338]},"#00bbcc":{"lch":[69.3970058395379397,58.0340346662075675,206.653495587531239],"luv":[69.3970058395379397,-51.8670935918889384,-26.0337047299998297],"rgb":[0,0.733333333333333282,0.8],"xyz":[0.28667469093207959,0.398982607183860305,0.633189118908310422],"hpluv":[206.653495587531239,106.116119046155191,69.3970058395379397],"hsluv":[206.653495587531239,99.9999999999915161,69.3970058395379397]},"#00bbdd":{"lch":[70.0067374807312461,64.9183055759271923,218.91244904401708],"luv":[70.0067374807312461,-50.5133677649133119,-40.7772740125682844],"rgb":[0,0.733333333333333282,0.866666666666666696],"xyz":[0.308193016482713134,0.407589937404113811,0.74651896680831642],"hpluv":[218.91244904401708,117.670246608059514,70.0067374807312461],"hsluv":[218.91244904401708,99.999999999991644,70.0067374807312461]},"#00bbee":{"lch":[70.6715424904064236,74.2108860535778,228.474155043258463],"luv":[70.6715424904064236,-49.1986871961444336,-55.5584807840624819],"rgb":[0,0.733333333333333282,0.933333333333333348],"xyz":[0.332005196748887843,0.417114809510583828,0.871929782876839643],"hpluv":[228.474155043258463,133.248513578578667,70.6715424904064236],"hsluv":[228.474155043258463,99.9999999999918288,70.6715424904064236]},"#00bbff":{"lch":[71.3906313155650167,85.0452269855302,235.688960914523477],"luv":[71.3906313155650167,-47.9387359102869155,-70.246481992653],"rgb":[0,0.733333333333333282,1],"xyz":[0.358176245158719264,0.427583228874516552,1.00976397116862149],"hpluv":[235.688960914523477,151.163886263776277,71.3906313155650167],"hsluv":[235.688960914523477,99.9999999999978,71.3906313155650167]},"#00cc00":{"lch":[71.6795694698327139,110.939506494120423,127.71501294924046],"luv":[71.6795694698327139,-67.8655057683618566,87.7601688009055181],"rgb":[0,0.8,0],"xyz":[0.215919200066506195,0.431838400133018441,0.0719730666888333814],"hpluv":[127.71501294924046,196.394882900214611,71.6795694698327139],"hsluv":[127.71501294924046,100.000000000002359,71.6795694698327139]},"#00cc11":{"lch":[71.7069484470386698,109.895339051400697,128.05073784188761],"luv":[71.7069484470386698,-67.7349868616780668,86.5387606802328548],"rgb":[0,0.8,0.0666666666666666657],"xyz":[0.216930865566143327,0.432243066332873294,0.0773011716535890181],"hpluv":[128.05073784188761,194.472124503698296,71.7069484470386698],"hsluv":[128.05073784188761,99.9999999999908766,71.7069484470386698]},"#00cc22":{"lch":[71.7576566073484,107.986601617430239,128.68476606632143],"luv":[71.7576566073484,-67.4954197535952289,84.2939763041676287],"rgb":[0,0.8,0.133333333333333331],"xyz":[0.218806223704620328,0.432993209588264094,0.0871780578495682107],"hpluv":[128.68476606632143,190.959361108477,71.7576566073484],"hsluv":[128.68476606632143,99.9999999999909193,71.7576566073484]},"#00cc33":{"lch":[71.8410194320707,104.91966800737103,129.762682813168567],"luv":[71.8410194320707,-67.1075822658835364,80.6517770244687853],"rgb":[0,0.8,0.2],"xyz":[0.22189397443707809,0.434228309881247221,0.103440211707179347],"hpluv":[129.762682813168567,185.320621425294917,71.8410194320707],"hsluv":[129.762682813168567,99.9999999999909761,71.8410194320707]},"#00cc44":{"lch":[71.9610975929873717,100.65733905537941,131.396818004218431],"luv":[71.9610975929873717,-66.561699323308261,75.5078809721416491],"rgb":[0,0.8,0.266666666666666663],"xyz":[0.226351969681296949,0.436011507978934787,0.126918986660065986],"hpluv":[131.396818004218431,177.495355343216744,71.9610975929873717],"hsluv":[131.396818004218431,99.9999999999909903,71.9610975929873717]},"#00cc55":{"lch":[72.1211872877728837,95.2615727691762828,133.734892870047815],"luv":[72.1211872877728837,-65.8564749898269639,68.8308938513177],"rgb":[0,0.8,0.333333333333333315],"xyz":[0.232314383720658935,0.438396473594679648,0.158321033934039901],"hpluv":[133.734892870047815,167.607792551030144,72.1211872877728837],"hsluv":[133.734892870047815,99.999999999991033,72.1211872877728837]},"#00cc66":{"lch":[72.3240060759138,88.9026050634798821,136.980115521422647],"luv":[72.3240060759138,-64.9982032665013207,60.6539921126355495],"rgb":[0,0.8,0.4],"xyz":[0.23989937949416712,0.441430471904082966,0.198268678341183863],"hpluv":[136.980115521422647,155.980870440536961,72.3240060759138],"hsluv":[136.980115521422647,99.9999999999910614,72.3240060759138]},"#00cc77":{"lch":[72.5717906268391459,81.8763194870781206,141.413175407098493],"luv":[72.5717906268391459,-63.9997644777707464,51.066249515114805],"rgb":[0,0.8,0.466666666666666674],"xyz":[0.249213392514369025,0.445156077112163762,0.247322480247581772],"hpluv":[141.413175407098493,143.162673336571032,72.5717906268391459],"hsluv":[141.413175407098493,99.9999999999910756,72.5717906268391459]},"#00cc88":{"lch":[72.8663546950801,74.6325704710961162,147.40707881161012],"luv":[72.8663546950801,-62.8793552775828672,40.2020802322297683],"rgb":[0,0.8,0.533333333333333326],"xyz":[0.260353809616312881,0.449612243952941359,0.305995343651153939],"hpluv":[147.40707881161012,129.969270924532168,72.8663546950801],"hsluv":[147.40707881161012,99.9999999999911608,72.8663546950801]},"#00cc99":{"lch":[73.2091273059676695,67.813783770663278,155.40051707617576],"luv":[73.2091273059676695,-61.6589956558222809,28.2290191825639418],"rgb":[0,0.8,0.6],"xyz":[0.273410773725385581,0.454835029596570517,0.374762021292271874],"hpluv":[155.40051707617576,117.541728748843539,73.2091273059676695],"hsluv":[155.40051707617576,99.9999999999911893,73.2091273059676695]},"#00ccaa":{"lch":[73.6011808048110368,62.2803364521242102,165.745935171574274],"luv":[73.6011808048110368,-60.3629393869259374,15.3347923742089414],"rgb":[0,0.8,0.66666666666666663],"xyz":[0.288468466690638137,0.460858106782671639,0.454065870909270419],"hpluv":[165.745935171574274,107.375573062224,73.6011808048110368],"hsluv":[165.745935171574274,99.9999999999912887,73.6011808048110368]},"#00ccbb":{"lch":[74.043253901593,59.041045922693165,178.335616576813749],"luv":[74.043253901593,-59.0161369965186395,1.7148404163965667],"rgb":[0,0.8,0.733333333333333282],"xyz":[0.305606058797974756,0.467713143625606398,0.544323856007912221],"hpluv":[178.335616576813749,101.183074845522739,74.043253901593],"hsluv":[178.335616576813749,99.9999999999913882,74.043253901593]},"#00cccc":{"lch":[74.5357725840108714,58.9696734274942429,192.177050630061132],"luv":[74.5357725840108714,-57.64288292201784,-12.4386668330598962],"rgb":[0,0.8,0.8],"xyz":[0.32489843424169651,0.4754300938030952,0.645930366678182377],"hpluv":[192.177050630061132,100.392967527320835,74.5357725840108714],"hsluv":[192.177050630061132,99.9999999999914877,74.5357725840108714]},"#00ccdd":{"lch":[75.0788705190671,62.3850861111967063,205.58971515357635],"luv":[75.0788705190671,-56.2657375800620656,-26.9456071312750254],"rgb":[0,0.8,0.866666666666666696],"xyz":[0.346416759792330053,0.484037424023348706,0.759260214578188375],"hpluv":[205.58971515357635,105.439266222061761,75.0788705190671],"hsluv":[205.58971515357635,99.9999999999915588,75.0788705190671]},"#00ccee":{"lch":[75.672409810316779,68.9113069897593,217.179575991302841],"luv":[75.672409810316779,-54.9047659259632326,-41.6441461630807765],"rgb":[0,0.8,0.933333333333333348],"xyz":[0.370228940058504818,0.493562296129818723,0.884671030646711598],"hpluv":[217.179575991302841,115.555933163518176,75.672409810316779],"hsluv":[217.179575991302841,99.9999999999916,75.672409810316779]},"#00ccff":{"lch":[76.3160024985922263,77.7871508482342193,226.46755023570978],"luv":[76.3160024985922263,-53.5770891110031471,-56.3944710009551713],"rgb":[0,0.8,1],"xyz":[0.396399988468336184,0.504030715493751447,1.02250521893849333],"hpluv":[226.46755023570978,131.600547876461974,76.3160024985922263],"hsluv":[226.46755023570978,99.9999999999969731,76.3160024985922263]},"#00dd00":{"lch":[77.1074905447145369,119.34037845513086,127.715012949240503],"luv":[77.1074905447145369,-73.004607631587163,94.4057900468603],"rgb":[0,0.866666666666666696,0],"xyz":[0.258553190613681372,0.51710638122737,0.0861843968712247],"hpluv":[127.715012949240503,210.385995725156505,77.1074905447145369],"hsluv":[127.715012949240503,100.000000000002203,77.1074905447145369]},"#00dd11":{"lch":[77.1317715771024268,118.40111864948102,127.995077421524911],"luv":[77.1317715771024268,-72.8869911141770359,93.3076171797906255],"rgb":[0,0.866666666666666696,0.0666666666666666657],"xyz":[0.259564856113318476,0.517511047427224868,0.0915125018359803366],"hpluv":[127.995077421524911,208.997725019578468,77.1317715771024268],"hsluv":[127.995077421524911,99.9999999999909193,77.1317715771024268]},"#00dd22":{"lch":[77.1767486793617081,116.680170458435171,128.522366120948305],"luv":[77.1767486793617081,-72.6707542705971434,91.2864921658838568],"rgb":[0,0.866666666666666696,0.133333333333333331],"xyz":[0.261440214251795533,0.518261190682615669,0.101389388031959529],"hpluv":[128.522366120948305,206.449864525990506,77.1767486793617081],"hsluv":[128.522366120948305,99.9999999999909335,77.1767486793617081]},"#00dd33":{"lch":[77.2507083817471312,113.903613467858165,129.414072915332611],"luv":[77.2507083817471312,-72.3197155087496668,87.9993858488157485],"rgb":[0,0.866666666666666696,0.2],"xyz":[0.264527964984253239,0.519496290975598796,0.117651541889570666],"hpluv":[129.414072915332611,202.327676795977681,77.2507083817471312],"hsluv":[129.414072915332611,99.9999999999909335,77.2507083817471312]},"#00dd44":{"lch":[77.3572825066044,110.019432359123073,130.755032484191332],"luv":[77.3572825066044,-71.8235777962907633,83.3405613681826907],"rgb":[0,0.866666666666666696,0.266666666666666663],"xyz":[0.268985960228472154,0.521279489073286362,0.141130316842457304],"hpluv":[130.755032484191332,196.537344059934071,77.3572825066044],"hsluv":[130.755032484191332,99.9999999999909193,77.3572825066044]},"#00dd55":{"lch":[77.499442461574418,105.05363654061,132.652443872197409],"luv":[77.499442461574418,-71.1790335676869717,77.2645567564888],"rgb":[0,0.866666666666666696,0.333333333333333315],"xyz":[0.274948374267834139,0.523664454689031111,0.172532364116431219],"hpluv":[132.652443872197409,189.094972829508237,77.499442461574418],"hsluv":[132.652443872197409,99.9999999999909477,77.499442461574418]},"#00dd66":{"lch":[77.6796666807438,99.1151742217995,135.249123061333165],"luv":[77.6796666807438,-70.3890792332532413,69.7796194150732276],"rgb":[0,0.866666666666666696,0.4],"xyz":[0.282533370041342324,0.52669845299843443,0.212480008523575181],"hpluv":[135.249123061333165,180.139247328423863,77.6796666807438],"hsluv":[135.249123061333165,99.9999999999909903,77.6796666807438]},"#00dd77":{"lch":[77.9000291762011301,92.4061998396230138,138.73841210181584],"luv":[77.9000291762011301,-69.4623356452591878,60.9416909472136155],"rgb":[0,0.866666666666666696,0.466666666666666674],"xyz":[0.29184738306154423,0.530424058206515281,0.26153381042997309],"hpluv":[138.73841210181584,169.957910917592017,77.9000291762011301],"hsluv":[138.73841210181584,99.9999999999910187,77.9000291762011301]},"#00dd88":{"lch":[78.1622519856154,85.2389230174627386,143.3784757437721],"luv":[78.1622519856154,-68.4122000424903,50.8472701580255091],"rgb":[0,0.866666666666666696,0.533333333333333326],"xyz":[0.30298780016348803,0.534880225047292823,0.320206673833545286],"hpluv":[143.3784757437721,159.033158409305884,78.1622519856154],"hsluv":[143.3784757437721,99.9999999999911608,78.1622519856154]},"#00dd99":{"lch":[78.4677391993035798,78.0607504013048583,149.494791226300919],"luv":[78.4677391993035798,-67.2558167964087801,39.6249398770864545],"rgb":[0,0.866666666666666696,0.6],"xyz":[0.316044764272560785,0.540103010690922,0.388973351474663165],"hpluv":[149.494791226300919,148.113090063328627,78.4677391993035798],"hsluv":[149.494791226300919,99.9999999999911466,78.4677391993035798]},"#00ddaa":{"lch":[78.8176011215583401,71.4835041270533225,157.438879868811341],"luv":[78.8176011215583401,-66.0129273361177,27.4259874352573583],"rgb":[0,0.866666666666666696,0.66666666666666663],"xyz":[0.331102457237813286,0.546126087877023103,0.468277201091661766],"hpluv":[157.438879868811341,138.307036304413771,78.8176011215583401],"hsluv":[157.438879868811341,99.9999999999912319,78.8176011215583401]},"#00ddbb":{"lch":[79.21267314937,66.2909050184163675,167.440816272526462],"luv":[79.21267314937,-64.7046905962200896,14.4148223370296193],"rgb":[0,0.866666666666666696,0.733333333333333282],"xyz":[0.34824004934514996,0.552981124719957862,0.558535186190303512],"hpluv":[167.440816272526462,131.160951364069831,79.21267314937],"hsluv":[167.440816272526462,99.9999999999912319,79.21267314937]},"#00ddcc":{"lch":[79.6535319864315738,63.3571261830985,179.312753048293331],"luv":[79.6535319864315738,-63.3525685364998381,0.759932897798095253],"rgb":[0,0.866666666666666696,0.8],"xyz":[0.367532424788871714,0.560698074897446719,0.660141696860573668],"hpluv":[179.312753048293331,128.577362979680402,79.6535319864315738],"hsluv":[179.312753048293331,99.9999999999913314,79.6535319864315738]},"#00dddd":{"lch":[80.1405107346531338,63.4039144225475795,192.177050630061245],"luv":[80.1405107346531338,-61.9773555359817649,-13.3739958452306631],"rgb":[0,0.866666666666666696,0.866666666666666696],"xyz":[0.389050750339505202,0.569305405117700225,0.773471544760579666],"hpluv":[192.177050630061245,132.399857962191078,80.1405107346531338],"hsluv":[192.177050630061245,99.9999999999915,80.1405107346531338]},"#00ddee":{"lch":[80.6737137665329,66.6843941199945078,204.668960845135786],"luv":[80.6737137665329,-60.59840405426975,-27.8323884211582282],"rgb":[0,0.866666666666666696,0.933333333333333348],"xyz":[0.412862930605679967,0.578830277224170242,0.898882360829102889],"hpluv":[204.668960845135786,143.769811077134563,80.6737137665329],"hsluv":[204.668960845135786,99.9999999999914735,80.6737137665329]},"#00ddff":{"lch":[81.2530318771427,72.8883394631876627,215.643856178856652],"luv":[81.2530318771427,-59.2330695533496296,-42.475328144570291],"rgb":[0,0.866666666666666696,1],"xyz":[0.439033979015511333,0.589298696588103,1.03671654912088473],"hpluv":[215.643856178856652,162.831862460855405,81.2530318771427],"hsluv":[215.643856178856652,99.9999999999960636,81.2530318771427]},"#00ee00":{"lch":[82.4573791946470749,127.620478503329409,127.715012949240503],"luv":[82.4573791946470749,-78.0698291684561241,100.955873068518613],"rgb":[0,0.933333333333333348,0],"xyz":[0.305731966954196188,0.611463933908400925,0.101910655651395884],"hpluv":[127.715012949240503,307.908475174189959,82.4573791946470749],"hsluv":[127.715012949240503,100.000000000002217,82.4573791946470749]},"#00ee11":{"lch":[82.4790940690076582,126.770138643430457,127.951660682688043],"luv":[82.4790940690076582,-77.963182339567652,99.9620440525398],"rgb":[0,0.933333333333333348,0.0666666666666666657],"xyz":[0.306743632453833293,0.611868600108255833,0.107238760616151521],"hpluv":[127.951660682688043,306.293921948395678,82.4790940690076582],"hsluv":[127.951660682688043,99.9999999999909193,82.4790940690076582]},"#00ee22":{"lch":[82.5193223464761729,125.209295581045268,128.396138884075839],"luv":[82.5193223464761729,-77.7668632323815814,98.1309466116455],"rgb":[0,0.933333333333333348,0.133333333333333331],"xyz":[0.308618990592310349,0.612618743363646634,0.117115646812130714],"hpluv":[128.396138884075839,303.325246698320768,82.5193223464761729],"hsluv":[128.396138884075839,99.9999999999907914,82.5193223464761729]},"#00ee33":{"lch":[82.5854861516441616,122.683025615083068,129.144698003447559],"luv":[82.5854861516441616,-77.4474668310457304,95.1473313105795881],"rgb":[0,0.933333333333333348,0.2],"xyz":[0.311706741324768055,0.613853843656629761,0.133377800669741864],"hpluv":[129.144698003447559,298.506449004286878,82.5854861516441616],"hsluv":[129.144698003447559,99.9999999999910187,82.5854861516441616]},"#00ee44":{"lch":[82.680854944152216,119.131104912681948,130.263308305441626],"luv":[82.680854944152216,-76.994580956063885,90.9068460629701889],"rgb":[0,0.933333333333333348,0.266666666666666663],"xyz":[0.31616473656898697,0.615637041754317327,0.156856575622628502],"hpluv":[130.263308305441626,291.702339981024693,82.680854944152216],"hsluv":[130.263308305441626,99.9999999999908624,82.680854944152216]},"#00ee55":{"lch":[82.8081199656530913,114.556122924925475,131.832385242542614],"luv":[82.8081199656530913,-76.4036333062175572,85.3556683366704192],"rgb":[0,0.933333333333333348,0.333333333333333315],"xyz":[0.322127150608348956,0.618022007370062076,0.18825862289660239],"hpluv":[131.832385242542614,282.889526663711365,82.8081199656530913],"hsluv":[131.832385242542614,99.9999999999908908,82.8081199656530913]},"#00ee66":{"lch":[82.9695459516691756,109.025909834785097,133.955863991345211],"luv":[82.9695459516691756,-75.6753248662734137,78.4849936082476347],"rgb":[0,0.933333333333333348,0.4],"xyz":[0.329712146381857141,0.621056005679465395,0.22820626730374638],"hpluv":[133.955863991345211,272.166364406401044,82.9695459516691756],"hsluv":[133.955863991345211,99.9999999999909193,82.9695459516691756]},"#00ee77":{"lch":[83.167051813506589,102.679799146220446,136.771308753659213],"luv":[83.167051813506589,-74.8151450958190338,70.3266323450776127],"rgb":[0,0.933333333333333348,0.466666666666666674],"xyz":[0.339026159402059046,0.624781610887546246,0.277260069210144289],"hpluv":[136.771308753659213,259.776444306911685,83.167051813506589],"hsluv":[136.771308753659213,99.9999999999910898,83.167051813506589]},"#00ee88":{"lch":[83.4022585136551839,95.7389522528198427,140.46074817536558],"luv":[83.4022585136551839,-73.8327925713246742,60.9480575538504],"rgb":[0,0.933333333333333348,0.533333333333333326],"xyz":[0.350166576504002847,0.629237777728323788,0.335932932613716428],"hpluv":[140.46074817536558,246.149488794882956,83.4022585136551839],"hsluv":[140.46074817536558,99.999999999991033,83.4022585136551839]},"#00ee99":{"lch":[83.6765199188301096,88.5221307628359142,145.258543938418427],"luv":[83.6765199188301096,-72.7414610621927,50.4464813176313],"rgb":[0,0.933333333333333348,0.6],"xyz":[0.363223540613075602,0.634460563371953,0.404699610254834363],"hpluv":[145.258543938418427,231.96752956627526,83.6765199188301096],"hsluv":[145.258543938418427,99.9999999999911,83.6765199188301096]},"#00eeaa":{"lch":[83.9909442670452364,81.4671227341597159,151.444498676017645],"luv":[83.9909442670452364,-71.557012704351564,38.9420854527837363],"rgb":[0,0.933333333333333348,0.66666666666666663],"xyz":[0.378281233578328102,0.640483640558054068,0.484003459871832964],"hpluv":[151.444498676017645,218.263507316576721,83.9909442670452364],"hsluv":[151.444498676017645,99.9999999999911893,83.9909442670452364]},"#00eebb":{"lch":[84.3464103530465366,75.1511025294100392,159.294479220170871],"luv":[84.3464103530465366,-70.2970903476626319,26.5707978811035801],"rgb":[0,0.933333333333333348,0.733333333333333282],"xyz":[0.395418825685664777,0.647338677400988827,0.57426144497047471],"hpluv":[159.294479220170871,206.543608310772072,84.3464103530465366],"hsluv":[159.294479220170871,99.9999999999912,84.3464103530465366]},"#00eecc":{"lch":[84.743580800257746,70.2844566194431195,168.945018717488722],"luv":[84.743580800257746,-68.9802322625990456,13.4771064879770393],"rgb":[0,0.933333333333333348,0.8],"xyz":[0.414711201129386531,0.655055627578477684,0.675867955640744866],"hpluv":[168.945018717488722,198.871854707918374,84.743580800257746],"hsluv":[168.945018717488722,99.9999999999913,84.743580800257746]},"#00eedd":{"lch":[85.1829138464002114,67.6253239558150625,180.163192871920216],"luv":[85.1829138464002114,-67.6250496492668418,-0.192613766721418916],"rgb":[0,0.933333333333333348,0.866666666666666696],"xyz":[0.43622952668002,0.66366295779873119,0.789197803540750864],"hpluv":[180.163192871920216,197.760624486431198,85.1829138464002114],"hsluv":[180.163192871920216,99.9999999999913882,85.1829138464002114]},"#00eeee":{"lch":[85.6646745174910507,67.7744082531008303,192.177050630061217],"luv":[85.6646745174910507,-66.2495152673009358,-14.2958784586901881],"rgb":[0,0.933333333333333348,0.933333333333333348],"xyz":[0.460041706946194784,0.673187829905201207,0.914608619609274087],"hpluv":[192.177050630061217,205.696714727687493,85.6646745174910507],"hsluv":[192.177050630061217,99.9999999999914309,85.6646745174910507]},"#00eeff":{"lch":[86.1889457184888,70.9350767712842867,203.864647638418489],"luv":[86.1889457184888,-64.8703943995767247,-28.6987290135183635],"rgb":[0,0.933333333333333348,1],"xyz":[0.486212755356026149,0.683656249269133931,1.05244280790105593],"hpluv":[203.864647638418489,224.453619733699583,86.1889457184888],"hsluv":[203.864647638418489,99.9999999999939888,86.1889457184888]},"#00ff00":{"lch":[87.7355191096597338,135.789531996666284,127.715012949240474],"luv":[87.7355191096597338,-83.0671197143942663,107.418111239344327],"rgb":[0,1,0],"xyz":[0.35758433938387,0.71516867876775,0.11919477979462],"hpluv":[127.715012949240474,490.145375063702204,87.7355191096597338],"hsluv":[127.715012949240474,100.000000000002217,87.7355191096597338]},"#00ff11":{"lch":[87.7550810882892165,135.01527678270574,127.917210072153054],"luv":[87.7550810882892165,-82.9698837721702915,106.513489059100834],"rgb":[0,1,0.0666666666666666657],"xyz":[0.358596004883507125,0.715573344967604941,0.124522884759375632],"hpluv":[127.917210072153054,488.208403570135204,87.7550810882892165],"hsluv":[127.917210072153054,99.9999999999917719,87.7550810882892165]},"#00ff22":{"lch":[87.7913242833811864,133.592052176160422,128.296258949772664],"luv":[87.7913242833811864,-82.7907071985999892,104.845291769319132],"rgb":[0,1,0.133333333333333331],"xyz":[0.360471363021984181,0.716323488222995741,0.134399770955354825],"hpluv":[128.296258949772664,484.641757887342919,87.7913242833811864],"hsluv":[128.296258949772664,99.9999999999919,87.7913242833811864]},"#00ff33":{"lch":[87.850943105558116,131.282721750620482,128.932531697131338],"luv":[87.850943105558116,-82.4986966230128616,102.123053644879462],"rgb":[0,1,0.2],"xyz":[0.363559113754441887,0.717558588515978868,0.150661924812965975],"hpluv":[128.932531697131338,478.837727878060548,87.850943105558116],"hsluv":[128.932531697131338,99.999999999991843,87.850943105558116]},"#00ff44":{"lch":[87.9368982766027756,128.022939247233296,129.878593634905172],"luv":[87.9368982766027756,-82.0835673214571528,98.245411848516369],"rgb":[0,1,0.266666666666666663],"xyz":[0.368017108998660802,0.719341786613666434,0.174140699765852613],"hpluv":[129.878593634905172,470.610169071279643,87.9368982766027756],"hsluv":[129.878593634905172,99.9999999999916724,87.9368982766027756]},"#00ff55":{"lch":[88.0516385770734189,123.799916713223595,131.196479790431113],"luv":[88.0516385770734189,-81.5399771501718362,93.1539129857171133],"rgb":[0,1,0.333333333333333315],"xyz":[0.373979523038022788,0.721726752229411184,0.205542747039826501],"hpluv":[131.196479790431113,459.892953467552729,88.0516385770734189],"hsluv":[131.196479790431113,99.9999999999917719,88.0516385770734189]},"#00ff66":{"lch":[88.197238997611,118.653311588493224,132.964137709394919],"luv":[88.197238997611,-80.8670327043222557,86.8281715373192498],"rgb":[0,1,0.4],"xyz":[0.381564518811531,0.724760750538814502,0.245490391446970491],"hpluv":[132.964137709394919,446.748834194207859,88.197238997611],"hsluv":[132.964137709394919,99.9999999999917719,88.197238997611]},"#00ff77":{"lch":[88.3754745956423164,112.679107800887323,135.2824164931273],"luv":[88.3754745956423164,-80.0679233099649537,79.2824633297525452],"rgb":[0,1,0.466666666666666674],"xyz":[0.390878531831732878,0.728486355746895353,0.2945441933533684],"hpluv":[135.2824164931273,431.3936933951166,88.3754745956423164],"hsluv":[135.2824164931273,99.9999999999915445,88.3754745956423164]},"#00ff88":{"lch":[88.587864465470858,106.036155512425779,138.2828406903445],"luv":[88.587864465470858,-79.1495135423216425,70.5621767086956311],"rgb":[0,1,0.533333333333333326],"xyz":[0.402018948933676679,0.732942522587672896,0.353217056756940539],"hpluv":[138.2828406903445,414.239888157084465,88.587864465470858],"hsluv":[138.2828406903445,99.9999999999914,88.587864465470858]},"#00ff99":{"lch":[88.8357000190422,98.9561663203651278,142.1349886621461],"luv":[88.8357000190422,-78.1218422027535695,60.739613298668921],"rgb":[0,1,0.6],"xyz":[0.415075913042749378,0.738165308231302109,0.421983734398058474],"hpluv":[142.1349886621461,395.967958147281365,88.8357000190422],"hsluv":[142.1349886621461,99.9999999999915303,88.8357000190422]},"#00ffaa":{"lch":[89.1200644426462674,91.7580340339716258,147.049061977519528],"luv":[89.1200644426462674,-76.997527549554917,49.9090929694682828],"rgb":[0,1,0.66666666666666663],"xyz":[0.430133606008001934,0.744188385417403175,0.501287584015057],"hpluv":[147.049061977519528,377.639750156066668,89.1200644426462674],"hsluv":[147.049061977519528,99.9999999999913,89.1200644426462674]},"#00ffbb":{"lch":[89.4418470234824241,84.8653215767476468,153.262243037154207],"luv":[89.4418470234824241,-75.791105608661141,38.1815546689964407],"rgb":[0,1,0.733333333333333282],"xyz":[0.447271198115338608,0.751043422260337934,0.591545569113698821],"hpluv":[153.262243037154207,360.863433446149145,89.4418470234824241],"hsluv":[153.262243037154207,99.9999999999912,89.4418470234824241]},"#00ffcc":{"lch":[89.801754487955634,78.8187300060100569,160.986090443114392],"luv":[89.801754487955634,-74.5183415032407197,25.6789598575702236],"rgb":[0,1,0.8],"xyz":[0.466563573559060307,0.758760372437826791,0.693152079783969],"hpluv":[160.986090443114392,347.997153451554084,89.801754487955634],"hsluv":[160.986090443114392,99.9999999999912461,89.801754487955634]},"#00ffdd":{"lch":[90.2003206582774339,74.260092310928,170.286849800478649],"luv":[90.2003206582774339,-73.1955569867131572,12.5288366352336915],"rgb":[0,1,0.866666666666666696],"xyz":[0.488081899109693906,0.767367702658080297,0.806481927683975],"hpluv":[170.286849800478649,342.308208972166483,90.2003206582774339],"hsluv":[170.286849800478649,99.9999999999913314,90.2003206582774339]},"#00ffee":{"lch":[90.6379152481429458,71.8480695265374294,180.909719109957],"luv":[90.6379152481429458,-71.8390133400929898,-1.14072652818200426],"rgb":[0,1,0.933333333333333348],"xyz":[0.511894079375868616,0.776892574764550314,0.931892743752498198],"hpluv":[180.909719109957,347.895283980605143,90.6379152481429458],"hsluv":[180.909719109957,99.999999999991374,90.6379152481429458]},"#00ffff":{"lch":[91.114752316705065,72.0862882649682,192.17705063006116],"luv":[91.114752316705065,-70.4643799638718207,-15.205397466925735],"rgb":[0,1,1],"xyz":[0.5380651277857,0.787360994128483,1.06972693204428],"hpluv":[192.17705063006116,369.190533917051368,91.114752316705065],"hsluv":[192.17705063006116,99.9999999999914877,91.114752316705065]},"#ff0000":{"lch":[53.23711559542933,179.038096923620287,12.1770506300617765],"luv":[53.23711559542933,175.009822162883836,37.7650936255616],"rgb":[1,0,0],"xyz":[0.41239079926595,0.21263900587151,0.019330818715591],"hpluv":[12.1770506300617765,426.746789183125202,53.23711559542933],"hsluv":[12.1770506300617765,100.000000000002203,53.23711559542933]},"#ff0011":{"lch":[53.2810087118185294,177.689248384364731,11.7592124156573554],"luv":[53.2810087118185294,173.960033822228979,36.2129206771479346],"rgb":[1,0,0.0666666666666666657],"xyz":[0.413402464765587119,0.213043672071364848,0.0246589236803466325],"hpluv":[11.7592124156573554,423.182830024727082,53.2810087118185294],"hsluv":[11.7592124156573554,99.9999999999986073,53.2810087118185294]},"#ff0022":{"lch":[53.362228057366309,175.255817292919801,10.9800713678561319],"luv":[53.362228057366309,172.047495148921342,33.3805468497921751],"rgb":[1,0,0.133333333333333331],"xyz":[0.415277822904064176,0.213793815326755676,0.0345358098763258251],"hpluv":[10.9800713678561319,416.75211680728853,53.362228057366309],"hsluv":[10.9800713678561319,99.9999999999986215,53.362228057366309]},"#ff0033":{"lch":[53.4955416476677499,171.43316235878109,9.68478250033725],"luv":[53.4955416476677499,168.989928530586468,28.8397852204116347],"rgb":[1,0,0.2],"xyz":[0.418365573636521881,0.215028915619738775,0.0507979637339369683],"hpluv":[9.68478250033725,406.646064741178918,53.4955416476677499],"hsluv":[9.68478250033725,99.9999999999986215,53.4955416476677499]},"#ff0044":{"lch":[53.6871179383659722,166.29954793496961,7.78930386328567259],"luv":[53.6871179383659722,164.765128442936401,22.5386799204815809],"rgb":[1,0,0.266666666666666663],"xyz":[0.422823568880740797,0.216812113717426369,0.0742767386868236],"hpluv":[7.78930386328567259,393.061316669856922,53.6871179383659722],"hsluv":[7.78930386328567259,99.9999999999987637,53.6871179383659722]},"#ff0055":{"lch":[53.9417095924386558,160.100368719231,5.2128969892355661],"luv":[53.9417095924386558,159.438189183864722,14.5461986032050437],"rgb":[1,0,0.333333333333333315],"xyz":[0.428785982920102782,0.219197079333171202,0.105678785960797522],"hpluv":[5.2128969892355661,376.623098544524225,53.9417095924386558],"hsluv":[5.2128969892355661,99.9999999999988,53.9417095924386558]},"#ff0066":{"lch":[54.2629295430466669,153.227313284557312,1.88082466234467849],"luv":[54.2629295430466669,153.144763004983872,5.02902580538230204],"rgb":[1,0,0.4],"xyz":[0.436370978693610967,0.222231077642574493,0.145626430367941484],"hpluv":[1.88082466234467849,358.321012364802243,54.2629295430466669],"hsluv":[1.88082466234467849,99.99999999999892,54.2629295430466669]},"#ff0077":{"lch":[54.6533978532017244,146.184101175375929,357.735148851436577],"luv":[54.6533978532017244,146.06990602550718,-5.77702260269427281],"rgb":[1,0,0.466666666666666674],"xyz":[0.445684991713812872,0.225956682850655316,0.194680232274339393],"hpluv":[357.735148851436577,339.408176675868503,54.6533978532017244],"hsluv":[357.735148851436577,99.9999999999990479,54.6533978532017244]},"#ff0088":{"lch":[55.1148373309560782,139.538803635294983,352.754628092234327],"luv":[55.1148373309560782,138.424605854630585,-17.5984719211521572],"rgb":[1,0,0.533333333333333326],"xyz":[0.456825408815756673,0.230412849691432914,0.253353095677911533],"hpluv":[352.754628092234327,321.26675874055752,55.1148373309560782],"hsluv":[352.754628092234327,99.9999999999991616,55.1148373309560782]},"#ff0099":{"lch":[55.6481496721619493,133.863929319774144,346.981903482220218],"luv":[55.6481496721619493,130.423488026195145,-30.1540269949209758],"rgb":[1,0,0.6],"xyz":[0.469882372924829372,0.235635635335062071,0.322119773319029468],"hpluv":[346.981903482220218,305.247535929832054,55.6481496721619493],"hsluv":[346.981903482220218,99.9999999999993463,55.6481496721619493]},"#ff00aa":{"lch":[56.2534865150640258,129.667114810270476,340.549180922221581],"luv":[56.2534865150640258,122.266710865918853,-43.1788383036143273],"rgb":[1,0,0.66666666666666663],"xyz":[0.484940065890081928,0.241658712521163166,0.401423622936028068],"hpluv":[340.549180922221581,292.495864077812769,56.2534865150640258],"hsluv":[340.549180922221581,99.9999999999994742,56.2534865150640258]},"#ff00bb":{"lch":[56.9303217870161689,127.321325924901956,333.685619315648239],"luv":[56.9303217870161689,114.127678427447606,-56.4410582115202928],"rgb":[1,0,0.733333333333333282],"xyz":[0.502077657997418547,0.248513749364097924,0.491681608034669815],"hpluv":[333.685619315648239,283.789838362024682,56.9303217870161689],"hsluv":[333.685619315648239,99.9999999999995879,56.9303217870161689]},"#ff00cc":{"lch":[57.6775275187384153,127.012826563172382,326.690520651062286],"luv":[57.6775275187384153,106.146716951325558,-69.7505024499586312],"rgb":[1,0,0.8],"xyz":[0.521370033441140301,0.256230699541586726,0.593288118704939915],"hpluv":[326.690520651062286,279.434659423159303,57.6775275187384153],"hsluv":[326.690520651062286,99.9999999999997726,57.6775275187384153]},"#ff00dd":{"lch":[58.4934529509690151,128.727977043064641,319.874434183361473],"luv":[58.4934529509690151,98.4297766537384149,-82.9606602040687],"rgb":[1,0,0.866666666666666696],"xyz":[0.542888358991773901,0.264838029761840288,0.706617966604945913],"hpluv":[319.874434183361473,279.257606739571429,58.4934529509690151],"hsluv":[319.874434183361473,99.9999999999999716,58.4934529509690151]},"#ff00ee":{"lch":[59.3760054748790367,132.286429048213932,313.494468670954461],"luv":[59.3760054748790367,91.0507046157626,-95.9659757377649214],"rgb":[1,0,0.933333333333333348],"xyz":[0.56670053925794861,0.274362901868310305,0.832028782673469136],"hpluv":[313.494468670954461,282.711609251625362,59.3760054748790367],"hsluv":[313.494468670954461,100.000000000000156,59.3760054748790367]},"#ff00ff":{"lch":[60.3227313545512942,137.405400537897037,307.715012949243601],"luv":[60.3227313545512942,84.0556019897527875,-108.696365491768773],"rgb":[1,0,1],"xyz":[0.59287158766778,0.284831321232243,0.969862970965251],"hpluv":[307.715012949243601,289.042783730483336,60.3227313545512942],"hsluv":[307.715012949243601,100.000000000000384,60.3227313545512942]},"#ff1100":{"lch":[53.6695097624616864,176.771562285449363,12.5954542867932275],"luv":[53.6695097624616864,172.517389506501019,38.5478345786208934],"rgb":[1,0.0666666666666666657,0],"xyz":[0.414395199526878422,0.216647806393366865,0.019998952135900451],"hpluv":[12.5954542867932275,417.949777534481484,53.6695097624616864],"hsluv":[12.5954542867932275,100.000000000002245,53.6695097624616864]},"#ff1111":{"lch":[53.7128602445647658,175.445128796306847,12.1770506300617765],"luv":[53.7128602445647658,171.497694164414924,37.0072170615611569],"rgb":[1,0.0666666666666666657,0.0666666666666666657],"xyz":[0.415406865026515526,0.217052472593221718,0.0253270571006560807],"hpluv":[12.1770506300617765,414.478837946685644,53.7128602445647658],"hsluv":[12.1770506300617765,99.9999999999986215,53.7128602445647658]},"#ff1122":{"lch":[53.7930781791116743,173.051572118951754,11.3967197916969329],"luv":[53.7930781791116743,169.639425839354459,34.1952016185739538],"rgb":[1,0.0666666666666666657,0.133333333333333331],"xyz":[0.417282223164992583,0.217802615848612546,0.0352039432966352803],"hpluv":[11.3967197916969329,408.214548988049671,53.7930781791116743],"hsluv":[11.3967197916969329,99.9999999999987,53.7930781791116743]},"#ff1133":{"lch":[53.9247555399676912,169.290109899416,10.0990648343251674],"luv":[53.9247555399676912,166.667136068812482,29.6851320424264138],"rgb":[1,0.0666666666666666657,0.2],"xyz":[0.420369973897450289,0.219037716141595645,0.0514660971542464235],"hpluv":[10.0990648343251674,398.366425235699353,53.9247555399676912],"hsluv":[10.0990648343251674,99.9999999999987,53.9247555399676912]},"#ff1144":{"lch":[54.1139966850166445,164.235972949617775,8.19925898659400154],"luv":[54.1139966850166445,162.55716522781,23.4226993279181244],"rgb":[1,0.0666666666666666657,0.266666666666666663],"xyz":[0.424827969141669204,0.220820914239283239,0.074944872107133062],"hpluv":[8.19925898659400154,385.121711929848118,54.1139966850166445],"hsluv":[8.19925898659400154,99.9999999999988489,54.1139966850166445]},"#ff1155":{"lch":[54.365514290002,158.12888296709221,5.61535385404219856],"luv":[54.365514290002,157.370056367003059,15.4728467796533362],"rgb":[1,0.0666666666666666657,0.333333333333333315],"xyz":[0.430790383181031189,0.223205879855028072,0.106346919381106964],"hpluv":[5.61535385404219856,369.085538340858477,54.365514290002],"hsluv":[5.61535385404219856,99.9999999999988916,54.365514290002]},"#ff1166":{"lch":[54.6829025612910442,151.353597545298243,2.27091305216541839],"luv":[54.6829025612910442,151.234730451097789,5.99731567352495443],"rgb":[1,0.0666666666666666657,0.4],"xyz":[0.438375378954539374,0.226239878164431363,0.146294563788250925],"hpluv":[2.27091305216541839,351.221033033747858,54.6829025612910442],"hsluv":[2.27091305216541839,99.999999999999,54.6829025612910442]},"#ff1177":{"lch":[55.0687823252034292,144.407362773795285,358.105880212246802],"luv":[55.0687823252034292,144.328460520523464,-4.77303960367160496],"rgb":[1,0.0666666666666666657,0.466666666666666674],"xyz":[0.44768939197474128,0.229965483372512186,0.195348365694648834],"hpluv":[358.105880212246802,332.753927221166919,55.0687823252034292],"hsluv":[358.105880212246802,99.9999999999990905,55.0687823252034292]},"#ff1188":{"lch":[55.5248949860500716,137.85386672349216,353.096828842063303],"luv":[55.5248949860500716,136.85452147125136,-16.5689023019976744],"rgb":[1,0.0666666666666666657,0.533333333333333326],"xyz":[0.45882980907668508,0.234421650213289784,0.254021229098221],"hpluv":[353.096828842063303,315.043506786171235,55.5248949860500716],"hsluv":[353.096828842063303,99.9999999999992,55.5248949860500716]},"#ff1199":{"lch":[56.0521767726019249,132.264360312052816,347.28491936957397],"luv":[56.0521767726019249,129.020794472918823,-29.1117777254046715],"rgb":[1,0.0666666666666666657,0.6],"xyz":[0.47188677318575778,0.239644435856918941,0.322787906739338937],"hpluv":[347.28491936957397,299.426117704125659,56.0521767726019249],"hsluv":[347.28491936957397,99.9999999999993605,56.0521767726019249]},"#ff11aa":{"lch":[56.6508275614924912,128.148315107741439,340.802676353967],"luv":[56.6508275614924912,121.022209124101792,-42.1380536294115586],"rgb":[1,0.0666666666666666657,0.66666666666666663],"xyz":[0.486944466151010336,0.245667513043020036,0.402091756356337537],"hpluv":[340.802676353967,287.042344439162662,56.6508275614924912],"hsluv":[340.802676353967,99.9999999999995168,56.6508275614924912]},"#ff11bb":{"lch":[57.3203806938084455,125.882364893771992,333.882217516525884],"luv":[57.3203806938084455,113.02864145467457,-55.4156656746030762],"rgb":[1,0.0666666666666666657,0.733333333333333282],"xyz":[0.504082058258347,0.252522549885954795,0.492349741454979284],"hpluv":[333.882217516525884,278.673167271969135,57.3203806938084455],"hsluv":[333.882217516525884,99.9999999999996163,57.3203806938084455]},"#ff11cc":{"lch":[58.0597760671947754,125.656277294901628,326.828156543045054],"luv":[58.0597760671947754,105.178488239830273,-68.7530772780178694],"rgb":[1,0.0666666666666666657,0.8],"xyz":[0.523374433702068709,0.260239500063443596,0.593956252125249384],"hpluv":[326.828156543045054,274.630115267561905,58.0597760671947754],"hsluv":[326.828156543045054,99.9999999999997868,58.0597760671947754]},"#ff11dd":{"lch":[58.8674364673636177,127.458097444326981,319.957026901825429],"luv":[58.8674364673636177,97.5770916499376568,-82.0016938195011846],"rgb":[1,0.0666666666666666657,0.866666666666666696],"xyz":[0.544892759252702308,0.268846830283697158,0.707286100025255382],"hpluv":[319.957026901825429,274.746161939823423,58.8674364673636177],"hsluv":[319.957026901825429,100.000000000000028,58.8674364673636177]},"#ff11ee":{"lch":[59.7413458233107519,131.106916258937218,313.5305052972667],"luv":[59.7413458233107519,90.2986667085849319,-95.0535337669245877],"rgb":[1,0.0666666666666666657,0.933333333333333348],"xyz":[0.568704939518877,0.278371702390167175,0.832696916093778605],"hpluv":[313.5305052972667,278.477381794919836,59.7413458233107519],"hsluv":[313.5305052972667,100.000000000000199,59.7413458233107519]},"#ff11ff":{"lch":[60.6791274610807534,136.317870534400242,307.715012949243601],"luv":[60.6791274610807534,83.3903225409976,-107.83606045076894],"rgb":[1,0.0666666666666666657,1],"xyz":[0.594875987928708438,0.288840121754099899,0.97053110438556045],"hpluv":[307.715012949243601,285.070838096226908,60.6791274610807534],"hsluv":[307.715012949243601,100.000000000000398,60.6791274610807534]},"#ff2200":{"lch":[54.4571507543770679,172.725520469573979,13.3786813235288875],"luv":[54.4571507543770679,168.038102184023103,39.9662562154253393],"rgb":[1,0.133333333333333331,0],"xyz":[0.418110823261646336,0.224079053862902833,0.0212374933808230602],"hpluv":[13.3786813235288875,402.476865089738737,54.4571507543770679],"hsluv":[13.3786813235288875,100.00000000000216,54.4571507543770679]},"#ff2211":{"lch":[54.4995382972682876,171.437527349711331,12.9593558016228254],"luv":[54.4995382972682876,167.070909686171433,38.446546274251638],"rgb":[1,0.133333333333333331,0.0666666666666666657],"xyz":[0.41912248876128344,0.224483720062757686,0.0265655983455786934],"hpluv":[12.9593558016228254,399.164948195999784,54.4995382972682876],"hsluv":[12.9593558016228254,99.999999999998721,54.4995382972682876]},"#ff2222":{"lch":[54.5779789595956117,169.112342257331477,12.1770506300617924],"luv":[54.5779789595956117,165.307392407273255,35.6714216042562171],"rgb":[1,0.133333333333333331,0.133333333333333331],"xyz":[0.420997846899760497,0.225233863318148514,0.036442484541557886],"hpluv":[12.1770506300617924,393.185217729465933,54.5779789595956117],"hsluv":[12.1770506300617924,99.9999999999987494,54.5779789595956117]},"#ff2233":{"lch":[54.7067518227456,165.455769736233549,10.8753803895539445],"luv":[54.7067518227456,162.484163442906947,31.2171166072114978],"rgb":[1,0.133333333333333331,0.2],"xyz":[0.424085597632218203,0.226468963611131613,0.0527046383991690293],"hpluv":[10.8753803895539445,383.778210348001721,54.7067518227456],"hsluv":[10.8753803895539445,99.9999999999987779,54.7067518227456]},"#ff2244":{"lch":[54.8918465894738148,160.537768894747074,8.96806115251763103],"luv":[54.8918465894738148,158.575257224785304,25.0252480066910863],"rgb":[1,0.133333333333333331,0.266666666666666663],"xyz":[0.428543592876437118,0.228252161708819207,0.0761834133520556678],"hpluv":[8.96806115251763103,371.115171122776133,54.8918465894738148],"hsluv":[8.96806115251763103,99.9999999999988347,54.8918465894738148]},"#ff2255":{"lch":[55.1379036013317432,154.588213330392733,6.3708707633682522],"luv":[55.1379036013317432,153.633547891150499,17.1536778289841081],"rgb":[1,0.133333333333333331,0.333333333333333315],"xyz":[0.434506006915799103,0.23063712732456404,0.107585460626029583],"hpluv":[6.3708707633682522,355.76683037739258,55.1379036013317432],"hsluv":[6.3708707633682522,99.9999999999989342,55.1379036013317432]},"#ff2266":{"lch":[55.4484819892530254,147.979820726080618,3.00414546296194196],"luv":[55.4484819892530254,147.776458796099433,7.75535736170059753],"rgb":[1,0.133333333333333331,0.4],"xyz":[0.442091002689307289,0.23367112563396733,0.147533105033173545],"hpluv":[3.00414546296194196,338.650844053811227,55.4484819892530254],"hsluv":[3.00414546296194196,99.9999999999990763,55.4484819892530254]},"#ff2277":{"lch":[55.8262016697843961,141.198613687408425,358.803757025958646],"luv":[55.8262016697843961,141.167840095073672,-2.94778393674187145],"rgb":[1,0.133333333333333331,0.466666666666666674],"xyz":[0.451405015709509194,0.237396730842048154,0.196586906939571454],"hpluv":[358.803757025958646,320.945787006908631,55.8262016697843961],"hsluv":[358.803757025958646,99.9999999999991616,55.8262016697843961]},"#ff2288":{"lch":[56.2728344602164299,134.800794021339357,353.742009538390391],"luv":[56.2728344602164299,133.997535770156077,-14.694028593592142],"rgb":[1,0.133333333333333331,0.533333333333333326],"xyz":[0.462545432811453,0.241852897682825752,0.255259770343143622],"hpluv":[353.742009538390391,303.971583410200083,56.2728344602164299],"hsluv":[353.742009538390391,99.9999999999992752,56.2728344602164299]},"#ff2299":{"lch":[56.7893750973531866,129.355771045476672,347.857065824102108],"luv":[56.7893750973531866,126.461550291410035,-27.2101415039127161],"rgb":[1,0.133333333333333331,0.6],"xyz":[0.47560239692052575,0.247075683326454909,0.324026447984261501],"hpluv":[347.857065824102108,289.040064659782502,56.7893750973531866],"hsluv":[347.857065824102108,99.9999999999994316,56.7893750973531866]},"#ff22aa":{"lch":[57.3761062638205743,125.376808270539939,341.281866819384959],"luv":[57.3761062638205743,118.745473604842076,-40.2350164715945766],"rgb":[1,0.133333333333333331,0.66666666666666663],"xyz":[0.49066008988577825,0.253098760512556031,0.403330297601260102],"hpluv":[341.281866819384959,277.284417349873706,57.3761062638205743],"hsluv":[341.281866819384959,99.999999999999531,57.3761062638205743]},"#ff22bb":{"lch":[58.0326640845464112,123.247659375493754,334.254064951888324],"luv":[58.0326640845464112,111.01274832153284,-53.5364852379920606],"rgb":[1,0.133333333333333331,0.733333333333333282],"xyz":[0.507797681993114924,0.25995379735549079,0.493588282699901848],"hpluv":[334.254064951888324,269.491764983662165,58.0326640845464112],"hsluv":[334.254064951888324,99.9999999999997726,58.0326640845464112]},"#ff22cc":{"lch":[58.7581065478829316,123.164795236141373,327.088444575119183],"luv":[58.7581065478829316,103.398114188518221,-66.9208246199849128],"rgb":[1,0.133333333333333331,0.8],"xyz":[0.527090057436836679,0.267670747532979592,0.595194793370172],"hpluv":[327.088444575119183,265.985598747154427,58.7581065478829316],"hsluv":[327.088444575119183,99.9999999999998721,58.7581065478829316]},"#ff22dd":{"lch":[59.550985046801415,125.119413407905796,320.113090366201448],"luv":[59.550985046801415,96.0055877759378,-80.2358693312108358],"rgb":[1,0.133333333333333331,0.866666666666666696],"xyz":[0.548608382987470167,0.276278077753233098,0.708524641270178],"hpluv":[320.113090366201448,266.609166102550091,59.550985046801415],"hsluv":[320.113090366201448,100.000000000000028,59.550985046801415]},"#ff22ee":{"lch":[60.4094179672163705,128.929416765847606,313.598505937960113],"luv":[60.4094179672163705,88.9098108664153273,-93.3693742041783281],"rgb":[1,0.133333333333333331,0.933333333333333348],"xyz":[0.572420563253645,0.285802949859703115,0.833935457338701225],"hpluv":[313.598505937960113,270.823716236275,60.4094179672163705],"hsluv":[313.598505937960113,100.000000000000227,60.4094179672163705]},"#ff22ff":{"lch":[61.3311646171935223,134.305840538380238,307.715012949243601],"luv":[61.3311646171935223,82.1594946996257249,-106.244417422389745],"rgb":[1,0.133333333333333331,1],"xyz":[0.598591611663476297,0.296271369223635839,0.97176964563048307],"hpluv":[307.715012949243601,277.877263991976,61.3311646171935223],"hsluv":[307.715012949243601,100.000000000000398,61.3311646171935223]},"#ff3300":{"lch":[55.7168894472394811,166.476173059961667,14.689559134518138],"luv":[55.7168894472394811,161.034729269155179,42.2153072463082495],"rgb":[1,0.2,0],"xyz":[0.424228545350657182,0.236314498040924637,0.0232767340771599419],"hpluv":[14.689559134518138,379.144314271077917,55.7168894472394811],"hsluv":[14.689559134518138,100.000000000002203,55.7168894472394811]},"#ff3311":{"lch":[55.7578022303213,165.243627812887922,14.2690908575150317],"luv":[55.7578022303213,160.145669888681539,40.7286256663500339],"rgb":[1,0.2,0.0666666666666666657],"xyz":[0.425240210850294287,0.236719164240779489,0.0286048390419155751],"hpluv":[14.2690908575150317,376.06108995847427,55.7578022303213],"hsluv":[14.2690908575150317,99.9999999999988,55.7578022303213]},"#ff3322":{"lch":[55.8335204651182835,163.01701714894287,13.4842232594842422],"luv":[55.8335204651182835,158.523316810386802,38.0119179675594552],"rgb":[1,0.2,0.133333333333333331],"xyz":[0.427115568988771344,0.237469307496170318,0.0384817252378947677],"hpluv":[13.4842232594842422,370.490653647292163,55.8335204651182835],"hsluv":[13.4842232594842422,99.9999999999987494,55.8335204651182835]},"#ff3333":{"lch":[55.9578428172660267,159.511521097175432,12.1770506300617853],"luv":[55.9578428172660267,155.922585303490365,33.6462888742638455],"rgb":[1,0.2,0.2],"xyz":[0.430203319721229049,0.238704407789153417,0.0547438790955059179],"hpluv":[12.1770506300617853,361.718248261175631,55.9578428172660267],"hsluv":[12.1770506300617853,99.9999999999988773,55.9578428172660267]},"#ff3344":{"lch":[56.1365811585215368,154.789240798906889,10.2588910791084782],"luv":[56.1365811585215368,152.31463646984821,27.5673826135157078],"rgb":[1,0.2,0.266666666666666663],"xyz":[0.434661314965447965,0.240487605886841,0.0782226540483925564],"hpluv":[10.2588910791084782,349.892100101075414,56.1365811585215368],"hsluv":[10.2588910791084782,99.9999999999989626,56.1365811585215368]},"#ff3355":{"lch":[56.3742616664660403,149.065442517766684,7.64169944339336649],"luv":[56.3742616664660403,147.741595680550319,19.8223878173745902],"rgb":[1,0.2,0.333333333333333315],"xyz":[0.44062372900480995,0.242872571502585843,0.109624701322366458],"hpluv":[7.64169944339336649,335.533149366899124,56.3742616664660403],"hsluv":[7.64169944339336649,99.9999999999990195,56.3742616664660403]},"#ff3366":{"lch":[56.674385203130754,142.694983818340035,4.24028319431916056],"luv":[56.674385203130754,142.304390380845462,10.550776523662277],"rgb":[1,0.2,0.4],"xyz":[0.448208724778318135,0.245906569811989134,0.14957234572951042],"hpluv":[4.24028319431916056,319.492902958598108,56.674385203130754],"hsluv":[4.24028319431916056,99.9999999999991758,56.674385203130754]},"#ff3377":{"lch":[57.0395646827704468,136.14730874514737,359.983392279567909],"luv":[57.0395646827704468,136.147303025702882,-0.0394635770517579934],"rgb":[1,0.2,0.466666666666666674],"xyz":[0.457522737798520041,0.249632175020069957,0.198626147635908329],"hpluv":[359.983392279567909,302.881107814185,57.0395646827704468],"hsluv":[359.983392279567909,99.9999999999992895,57.0395646827704468]},"#ff3388":{"lch":[57.4716120619286954,129.967879448766553,354.83565117969431],"luv":[57.4716120619286954,129.440287861866665,-11.6987848363070146],"rgb":[1,0.2,0.533333333333333326],"xyz":[0.468663154900463841,0.254088341860847555,0.257299011039480496],"hpluv":[354.83565117969431,286.960407533356261,57.4716120619286954],"hsluv":[354.83565117969431,99.9999999999993889,57.4716120619286954]},"#ff3399":{"lch":[57.9716047421228353,124.724336507791776,348.82951213288959],"luv":[57.9716047421228353,122.361442957788952,-24.1627273832372573],"rgb":[1,0.2,0.6],"xyz":[0.481720119009536596,0.259311127504476713,0.326065688680598431],"hpluv":[348.82951213288959,273.007894976207297,57.9716047421228353],"hsluv":[348.82951213288959,99.9999999999995737,57.9716047421228353]},"#ff33aa":{"lch":[58.5399451724763935,120.937271340322638,342.098036856126953],"luv":[58.5399451724763935,115.081956962752116,-37.174813797329108],"rgb":[1,0.2,0.66666666666666663],"xyz":[0.496777811974789096,0.265334204690577835,0.405369538297597032],"hpluv":[342.098036856126953,262.148381504719794,58.5399451724763935],"hsluv":[342.098036856126953,99.9999999999996732,58.5399451724763935]},"#ff33bb":{"lch":[59.1764201449825862,119.003132790944747,334.888094830460091],"luv":[59.1764201449825862,107.755032536641394,-50.5034511403585498],"rgb":[1,0.2,0.733333333333333282],"xyz":[0.513915404082125771,0.272189241533512594,0.495627523396238778],"hpluv":[334.888094830460091,255.181409444549388,59.1764201449825862],"hsluv":[334.888094830460091,99.9999999999998295,59.1764201449825862]},"#ff33cc":{"lch":[59.8802624584280494,119.13012657470172,327.532171012183937],"luv":[59.8802624584280494,100.509254029343069,-63.9521454852723039],"rgb":[1,0.2,0.8],"xyz":[0.533207779525847525,0.279906191711001395,0.597234034066508879],"hpluv":[327.532171012183937,252.451080902073329,59.8802624584280494],"hsluv":[327.532171012183937,100.000000000000043,59.8802624584280494]},"#ff33dd":{"lch":[60.650215463767978,121.314823858854638,320.378757122173454],"luv":[60.650215463767978,93.4460015542912146,-77.3636302238999747],"rgb":[1,0.2,0.866666666666666696],"xyz":[0.554726105076481,0.288513521931254902,0.710563881966514876],"hpluv":[320.378757122173454,253.817084039055629,60.650215463767978],"hsluv":[320.378757122173454,100.000000000000171,60.650215463767978]},"#ff33ee":{"lch":[61.484599762034378,125.372817174433621,313.71398784253438],"luv":[61.484599762034378,86.6400000332951805,-90.6192787462169775],"rgb":[1,0.2,0.933333333333333348],"xyz":[0.578538285342655723,0.298038394037724919,0.8359746980350381],"hpluv":[313.71398784253438,258.747618308410438,61.484599762034378],"hsluv":[313.71398784253438,100.000000000000242,61.484599762034378]},"#ff33ff":{"lch":[62.3813806681475,131.007738376122177,307.715012949243658],"luv":[62.3813806681475,80.141932350642,-103.635409940481253],"rgb":[1,0.2,1],"xyz":[0.604709333752487144,0.308506813401657642,0.97380888632682],"hpluv":[307.715012949243658,266.490230971107223,62.3813806681475],"hsluv":[307.715012949243658,100.000000000000597,62.3813806681475]},"#ff4400":{"lch":[57.461133143380664,158.273971604467,16.6278363926044079],"luv":[57.461133143380664,151.655533944896689,45.2907177172089845],"rgb":[1,0.266666666666666663,0],"xyz":[0.433061115833623222,0.253979639006856939,0.0262209242381485352],"hpluv":[16.6278363926044079,349.522099776260404,57.461133143380664],"hsluv":[16.6278363926044079,100.000000000002203,57.461133143380664]},"#ff4411":{"lch":[57.500127691013958,157.107055615985729,16.2066010587584444],"luv":[57.500127691013958,150.863862649088418,43.84885256105823],"rgb":[1,0.266666666666666663,0.0666666666666666657],"xyz":[0.434072781333260327,0.254384305206711792,0.031549029202904165],"hpluv":[16.2066010587584444,346.709871357654038,57.500127691013958],"hsluv":[16.2066010587584444,99.9999999999990195,57.500127691013958]},"#ff4422":{"lch":[57.5723039440668174,154.996970095022306,15.4196600073807488],"luv":[57.5723039440668174,149.417734299680745,41.2116660108183908],"rgb":[1,0.266666666666666663,0.133333333333333331],"xyz":[0.435948139471737384,0.255134448462102592,0.0414259153988833645],"hpluv":[15.4196600073807488,341.624434338608523,57.5723039440668174],"hsluv":[15.4196600073807488,99.9999999999990195,57.5723039440668174]},"#ff4433":{"lch":[57.6908335218327437,151.669616752661852,14.1071803519879388],"luv":[57.6908335218327437,147.095485225188412,36.9674298845038223],"rgb":[1,0.266666666666666663,0.2],"xyz":[0.439035890204195089,0.256369548755085719,0.0576880692564945077],"hpluv":[14.1071803519879388,333.603886972203838,57.6908335218327437],"hsluv":[14.1071803519879388,99.9999999999991189,57.6908335218327437]},"#ff4444":{"lch":[57.8612930010941682,147.177084719743902,12.177050630061812],"luv":[57.8612930010941682,143.865668066403089,31.0445457111261],"rgb":[1,0.266666666666666663,0.266666666666666663],"xyz":[0.443493885448414,0.258152746852773285,0.0811668442093811393],"hpluv":[12.177050630061812,322.76868159643891,57.8612930010941682],"hsluv":[12.177050630061812,99.9999999999991616,57.8612930010941682]},"#ff4455":{"lch":[58.088054010202,141.716285969530816,9.53556562214303405],"luv":[58.088054010202,139.758186425649882,23.4766913344092778],"rgb":[1,0.266666666666666663,0.333333333333333315],"xyz":[0.449456299487776,0.260537712468518146,0.112568891483355055],"hpluv":[9.53556562214303405,309.579547415252762,58.088054010202],"hsluv":[9.53556562214303405,99.9999999999992184,58.088054010202]},"#ff4466":{"lch":[58.3745334436288772,135.619673907166316,6.08910281061040859],"luv":[58.3745334436288772,134.854526247228307,14.3858507333331573],"rgb":[1,0.266666666666666663,0.4],"xyz":[0.457041295261284175,0.263571710777921464,0.152516535890499016],"hpluv":[6.08910281061040859,294.807548797669426,58.3745334436288772],"hsluv":[6.08910281061040859,99.9999999999992468,58.3745334436288772]},"#ff4477":{"lch":[58.7233249761193292,129.336052383116169,1.75519751784143763],"luv":[58.7233249761193292,129.275370036155351,3.96145782045869943],"rgb":[1,0.266666666666666663,0.466666666666666674],"xyz":[0.466355308281486081,0.26729731598600226,0.201570337796896926],"hpluv":[1.75519751784143763,279.478426792191101,58.7233249761193292],"hsluv":[1.75519751784143763,99.99999999999946,58.7233249761193292]},"#ff4488":{"lch":[59.1362810655005831,123.398173767481396,356.485857706034096],"luv":[59.1362810655005831,123.16614811103635,-7.56367957014252212],"rgb":[1,0.266666666666666663,0.533333333333333326],"xyz":[0.477495725383429881,0.271753482826779857,0.260243201200469065],"hpluv":[356.485857706034096,264.785408966002421,59.1362810655005831],"hsluv":[356.485857706034096,99.9999999999995595,59.1362810655005831]},"#ff4499":{"lch":[59.6145739069951901,118.37348532064955,350.303370213710309],"luv":[59.6145739069951901,116.682328099077466,-19.9378117238896806],"rgb":[1,0.266666666666666663,0.6],"xyz":[0.490552689492502636,0.276976268470409,0.329009878841587],"hpluv":[350.303370213710309,251.965637795338,59.6145739069951901],"hsluv":[350.303370213710309,99.9999999999997158,59.6145739069951901]},"#ff44aa":{"lch":[60.1587486598557177,114.795436800176844,343.339450530546515],"luv":[60.1587486598557177,109.976338996192666,-32.9119609129858475],"rgb":[1,0.266666666666666663,0.66666666666666663],"xyz":[0.505610382457755136,0.282999345656510137,0.408313728458585601],"hpluv":[343.339450530546515,242.139230170638513,60.1587486598557177],"hsluv":[343.339450530546515,99.9999999999997726,60.1587486598557177]},"#ff44bb":{"lch":[60.768775409955694,113.081121999454581,335.854341209703],"luv":[60.768775409955694,103.187483930843442,-46.2567110015126133],"rgb":[1,0.266666666666666663,0.733333333333333282],"xyz":[0.522747974565091811,0.289854382499444896,0.498571713557227347],"hpluv":[335.854341209703,236.128794952899398,60.768775409955694],"hsluv":[335.854341209703,99.9999999999999716,60.768775409955694]},"#ff44cc":{"lch":[61.4441027606342232,113.457557937670586,328.208302422827],"luv":[61.4441027606342232,96.4354118722023088,-59.7731443895883743],"rgb":[1,0.266666666666666663,0.8],"xyz":[0.542040350008813565,0.297571332676933697,0.600178224227497559],"hpluv":[328.208302422827,234.310931883055929,61.4441027606342232],"hsluv":[328.208302422827,100.000000000000128,61.4441027606342232]},"#ff44dd":{"lch":[62.1837139115479403,115.929787300919912,320.782684481283354],"luv":[62.1837139115479403,89.8170022013310358,-73.2981698216444357],"rgb":[1,0.266666666666666663,0.866666666666666696],"xyz":[0.563558675559447,0.306178662897187204,0.713508072127503556],"hpluv":[320.782684481283354,236.568931830040128,62.1837139115479403],"hsluv":[320.782684481283354,100.000000000000384,62.1837139115479403]},"#ff44ee":{"lch":[62.986184892514558,120.309477517885213,313.888915695758442],"luv":[62.986184892514558,83.4060394378513195,-86.7052649261745643],"rgb":[1,0.266666666666666663,0.933333333333333348],"xyz":[0.587370855825621874,0.315703535003657221,0.83891888819602678],"hpluv":[313.888915695758442,242.378371703623515,62.986184892514558],"hsluv":[313.888915695758442,100.000000000000512,62.986184892514558]},"#ff44ff":{"lch":[63.8497439492436,126.288239910703226,307.715012949243771],"luv":[63.8497439492436,77.2548530724802447,-99.9019880507531468],"rgb":[1,0.266666666666666663,1],"xyz":[0.613541904235453184,0.326171954367589945,0.976753076487808514],"hpluv":[307.715012949243771,250.982289693600563,63.8497439492436],"hsluv":[307.715012949243771,100.000000000000711,63.8497439492436]},"#ff5500":{"lch":[59.6718499915998279,148.630700843778015,19.3008598736449528],"luv":[59.6718499915998279,140.27705963161867,49.1266910591374923],"rgb":[1,0.333333333333333315,0],"xyz":[0.444874372547969188,0.277606152435549203,0.030158676476263746],"hpluv":[19.3008598736449528,316.066414507984518,59.6718499915998279],"hsluv":[19.3008598736449528,100.00000000000226,59.6718499915998279]},"#ff5511":{"lch":[59.7086010657385486,147.530698996531413,18.8803784611224046],"luv":[59.7086010657385486,139.59299153240957,47.7399608445355526],"rgb":[1,0.333333333333333315,0.0666666666666666657],"xyz":[0.445886038047606292,0.278010818635404056,0.0354867814410193758],"hpluv":[18.8803784611224046,313.53413530658878,59.7086010657385486],"hsluv":[18.8803784611224046,99.9999999999992184,59.7086010657385486]},"#ff5522":{"lch":[59.7766335415963255,145.539064184811622,18.0939597274483681],"luv":[59.7766335415963255,138.341936048844929,45.2009727113036],"rgb":[1,0.333333333333333315,0.133333333333333331],"xyz":[0.447761396186083349,0.278760961890794856,0.0453636676369985753],"hpluv":[18.0939597274483681,308.949467849715688,59.7766335415963255],"hsluv":[18.0939597274483681,99.9999999999993,59.7766335415963255]},"#ff5533":{"lch":[59.8883826376776085,142.391759670631302,16.7797766500676033],"luv":[59.8883826376776085,136.328925827546385,41.1076295206398825],"rgb":[1,0.333333333333333315,0.2],"xyz":[0.450849146918541055,0.279996062183778,0.0616258214946097185],"hpluv":[16.7797766500676033,301.704368813615531,59.8883826376776085],"hsluv":[16.7797766500676033,99.9999999999992752,59.8883826376776085]},"#ff5544":{"lch":[60.0491441299879654,138.129067713899872,14.841281480974498],"luv":[60.0491441299879654,133.520956258941027,35.3806951204903228],"rgb":[1,0.333333333333333315,0.266666666666666663],"xyz":[0.45530714216275997,0.281779260281465549,0.0851045964474963501],"hpluv":[14.841281480974498,291.888903616465711,60.0491441299879654],"hsluv":[14.841281480974498,99.9999999999994458,60.0491441299879654]},"#ff5555":{"lch":[60.2631003442631936,132.926854505406169,12.1770506300618191],"luv":[60.2631003442631936,129.936061471805857,28.0386978637829927],"rgb":[1,0.333333333333333315,0.333333333333333315],"xyz":[0.461269556202121955,0.28416422589721041,0.116506643721470265],"hpluv":[12.1770506300618191,279.898508055628838,60.2631003442631936],"hsluv":[12.1770506300618191,99.99999999999946,60.2631003442631936]},"#ff5566":{"lch":[60.5335583680784168,127.091978224389294,8.68145952340772098],"luv":[60.5335583680784168,125.635857711143842,19.1833830742614],"rgb":[1,0.333333333333333315,0.4],"xyz":[0.468854551975630141,0.287198224206613728,0.156454288128614227],"hpluv":[8.68145952340772098,266.416588145649541,60.5335583680784168],"hsluv":[8.68145952340772098,99.9999999999995737,60.5335583680784168]},"#ff5577":{"lch":[60.8630749033481351,121.049870295691591,4.25532383082281918],"luv":[60.8630749033481351,120.716171483201308,8.98203991541407],"rgb":[1,0.333333333333333315,0.466666666666666674],"xyz":[0.478168564995832046,0.290923829414694524,0.205508090035012136],"hpluv":[4.25532383082281918,252.376995060411161,60.8630749033481351],"hsluv":[4.25532383082281918,99.9999999999997158,60.8630749033481351]},"#ff5588":{"lch":[61.2535329118914404,115.319895978664789,358.830706871579594],"luv":[61.2535329118914404,115.295882188952703,-2.35328680810625102],"rgb":[1,0.333333333333333315,0.533333333333333326],"xyz":[0.489308982097775846,0.295379996255472121,0.264180953438584276],"hpluv":[358.830706871579594,238.897951612134108,61.2535329118914404],"hsluv":[358.830706871579594,99.9999999999997868,61.2535329118914404]},"#ff5599":{"lch":[61.7061969251912075,110.472562823261683,352.412124726619879],"luv":[61.7061969251912075,109.505210454219565,-14.5875296097928366],"rgb":[1,0.333333333333333315,0.6],"xyz":[0.502365946206848601,0.300602781899101279,0.332947631079702211],"hpluv":[352.412124726619879,227.177321581811952,61.7061969251912075],"hsluv":[352.412124726619879,99.9999999999998721,61.7061969251912075]},"#ff55aa":{"lch":[62.2217597266614177,107.062368992166355,345.125792918237266],"luv":[62.2217597266614177,103.474894783269619,-27.4826673342684735],"rgb":[1,0.333333333333333315,0.66666666666666663],"xyz":[0.517423639172101102,0.306625859085202401,0.412251480696700812],"hpluv":[345.125792918237266,218.340291577764589,62.2217597266614177],"hsluv":[345.125792918237266,100.000000000000071,62.2217597266614177]},"#ff55bb":{"lch":[62.8003867495987862,105.538663220643826,337.249357740418191],"luv":[62.8003867495987862,97.3274002701012,-40.8140489422941855],"rgb":[1,0.333333333333333315,0.733333333333333282],"xyz":[0.534561231279437776,0.31348089592813716,0.502509465795342614],"hpluv":[337.249357740418191,213.249782655969199,62.8003867495987862],"hsluv":[337.249357740418191,100.000000000000284,62.8003867495987862]},"#ff55cc":{"lch":[63.441761241476712,106.157882562261193,329.184616986090759],"luv":[63.441761241476712,91.1707664760994447,-54.3818661895983837],"rgb":[1,0.333333333333333315,0.8],"xyz":[0.553853606723159531,0.321197846105625961,0.60411597646561277],"hpluv":[329.184616986090759,212.332436268611161,63.441761241476712],"hsluv":[329.184616986090759,100.000000000000441,63.441761241476712]},"#ff55dd":{"lch":[64.1451313698934769,108.938462409011748,321.364198961949114],"luv":[64.1451313698934769,85.0951546537234549,-68.0176686346904518],"rgb":[1,0.333333333333333315,0.866666666666666696],"xyz":[0.575371932273793,0.329805176325879468,0.717445824365618767],"hpluv":[321.364198961949114,215.504760823814451,64.1451313698934769],"hsluv":[321.364198961949114,100.000000000000597,64.1451313698934769]},"#ff55ee":{"lch":[64.9093593252901258,113.686114680552976,314.13939983200612],"luv":[64.9093593252901258,79.1717442713053288,-81.5865649491316418],"rgb":[1,0.333333333333333315,0.933333333333333348],"xyz":[0.599184112539967728,0.339330048432349485,0.842856640434142],"hpluv":[314.13939983200612,222.248801840624651,64.9093593252901258],"hsluv":[314.13939983200612,100.000000000000753,64.9093593252901258]},"#ff55ff":{"lch":[65.7329718140353378,120.074032289562709,307.715012949243885],"luv":[65.7329718140353378,73.4534088756767147,-94.9861566483116633],"rgb":[1,0.333333333333333315,1],"xyz":[0.625355160949799149,0.349798467796282209,0.980690828725923724],"hpluv":[307.715012949243885,231.795582155087629,65.7329718140353378],"hsluv":[307.715012949243885,100.000000000000981,65.7329718140353378]},"#ff6600":{"lch":[62.3097916023938438,138.227046243322206,22.8239093069931798],"luv":[62.3097916023938438,127.404056867086908,53.6183047751569717],"rgb":[1,0.4,0],"xyz":[0.459902430253815608,0.307662267847242543,0.03516802904487909],"hpluv":[22.8239093069931798,281.498480884542573,62.3097916023938438],"hsluv":[22.8239093069931798,100.000000000002359,62.3097916023938438]},"#ff6611":{"lch":[62.344110015411573,137.186959502953613,22.4076195476895244],"luv":[62.344110015411573,126.828705913080029,52.2947532174930245],"rgb":[1,0.4,0.0666666666666666657],"xyz":[0.460914095753452713,0.308066934047097396,0.0404961340096347197],"hpluv":[22.4076195476895244,279.226561167599414,62.344110015411573],"hsluv":[22.4076195476895244,99.9999999999995737,62.344110015411573]},"#ff6622":{"lch":[62.4076477973658257,135.300699513710725,21.6278909170268392],"luv":[62.4076477973658257,125.775148313603225,49.8687412673566115],"rgb":[1,0.4,0.133333333333333331],"xyz":[0.46278945389192977,0.308817077302488197,0.0503730202056139192],"hpluv":[21.6278909170268392,275.106945224361368,62.4076477973658257],"hsluv":[21.6278909170268392,99.9999999999996163,62.4076477973658257]},"#ff6633":{"lch":[62.5120380635233346,132.311574345484274,20.3215228987586443],"luv":[62.5120380635233346,124.076309265494103,45.9502141979128851],"rgb":[1,0.4,0.2],"xyz":[0.465877204624387475,0.310052177595471323,0.0666351740632250555],"hpluv":[20.3215228987586443,268.579898420339646,62.5120380635233346],"hsluv":[20.3215228987586443,99.9999999999995879,62.5120380635233346]},"#ff6644":{"lch":[62.6622654373265675,128.246261163642686,18.3868048135947362],"luv":[62.6622654373265675,121.699120282046835,40.4527826611364603],"rgb":[1,0.4,0.266666666666666663],"xyz":[0.470335199868606391,0.311835375693158889,0.0901139490161117],"hpluv":[18.3868048135947362,259.703586528718,62.6622654373265675],"hsluv":[18.3868048135947362,99.9999999999997726,62.6622654373265675]},"#ff6655":{"lch":[62.8622967709428764,123.257362768531593,15.7125644918265355],"luv":[62.8622967709428764,118.651528823693667,33.3795174388964284],"rgb":[1,0.4,0.333333333333333315],"xyz":[0.476297613907968376,0.31422034130890375,0.121515996290085609],"hpluv":[15.7125644918265355,248.806632458920831,62.8622967709428764],"hsluv":[15.7125644918265355,99.9999999999997158,62.8622967709428764]},"#ff6666":{"lch":[63.1153061541487119,117.623502253606588,12.1770506300618742],"luv":[63.1153061541487119,114.97702760078576,24.8107115273291683],"rgb":[1,0.4,0.4],"xyz":[0.483882609681476561,0.317254339618307069,0.161463640697229571],"hpluv":[12.1770506300618742,236.482353971627703,63.1153061541487119],"hsluv":[12.1770506300618742,99.9999999999999,63.1153061541487119]},"#ff6677":{"lch":[63.4237926928396121,111.744324598031497,7.65713975886231157],"luv":[63.4237926928396121,110.747917341816802,14.8893547314965815],"rgb":[1,0.4,0.466666666666666674],"xyz":[0.493196622701678467,0.320979944826387864,0.21051744260362748],"hpluv":[7.65713975886231157,223.569519019308729,63.4237926928396121],"hsluv":[7.65713975886231157,100.000000000000071,63.4237926928396121]},"#ff6688":{"lch":[63.7896518301749751,106.125321016318935,2.05404070639815961],"luv":[63.7896518301749751,106.057131857198982,3.80375380925921824],"rgb":[1,0.4,0.533333333333333326],"xyz":[0.504337039803622322,0.325436111667165462,0.26919030600719962],"hpluv":[2.05404070639815961,211.109662635719985,63.7896518301749751],"hsluv":[2.05404070639815961,100.000000000000128,63.7896518301749751]},"#ff6699":{"lch":[64.2142253202301276,101.344202045456129,355.341285926877504],"luv":[64.2142253202301276,101.009378125853075,-8.23121004826552394],"rgb":[1,0.4,0.6],"xyz":[0.517394003912695,0.330658897310794619,0.337956983648317555],"hpluv":[355.341285926877504,200.265890662959123,64.2142253202301276],"hsluv":[355.341285926877504,100.000000000000199,64.2142253202301276]},"#ff66aa":{"lch":[64.6983418323177233,97.9876087444390436,347.629516841099075],"luv":[64.6983418323177233,95.7126081968365838,-20.9920961224008664],"rgb":[1,0.4,0.66666666666666663],"xyz":[0.532451696877947578,0.336681974496895742,0.417260833265316156],"hpluv":[347.629516841099075,192.184047560801417,64.6983418323177233],"hsluv":[347.629516841099075,100.000000000000441,64.6983418323177233]},"#ff66bb":{"lch":[65.2423543089962408,96.5541832870936787,339.215698562051898],"luv":[65.2423543089962408,90.270720679111,-34.2623306024503123],"rgb":[1,0.4,0.733333333333333282],"xyz":[0.549589288985284141,0.3435370113398305,0.507518818363957847],"hpluv":[339.215698562051898,187.793604034801348,65.2423543089962408],"hsluv":[339.215698562051898,100.000000000000597,65.2423543089962408]},"#ff66cc":{"lch":[65.8461771980182533,97.3465701370285,330.562118792095362],"luv":[65.8461771980182533,84.7780628468697159,-47.8438583036069218],"rgb":[1,0.4,0.8],"xyz":[0.568881664429005895,0.351253961517319302,0.609125329034228],"hpluv":[330.562118792095362,187.598522894675455,65.8461771980182533],"hsluv":[330.562118792095362,100.000000000000711,65.8461771980182533]},"#ff66dd":{"lch":[66.5093249736543157,100.405273498350255,322.181562409870594],"luv":[66.5093249736543157,79.3159229397089831,-61.5646271368605298],"rgb":[1,0.4,0.866666666666666696],"xyz":[0.590399989979639495,0.359861291737572808,0.722455176934234],"hpluv":[322.181562409870594,191.563741116159406,66.5093249736543157],"hsluv":[322.181562409870594,100.000000000000952,66.5093249736543157]},"#ff66ee":{"lch":[67.2309523334132706,105.527911758853008,314.488878023448478],"luv":[67.2309523334132706,73.9508789773533408,-75.2821868615750702],"rgb":[1,0.4,0.933333333333333348],"xyz":[0.614212170245814204,0.369386163844042825,0.847865993002757223],"hpluv":[314.488878023448478,199.176184031939982,67.2309523334132706],"hsluv":[314.488878023448478,100.000000000001066,67.2309523334132706]},"#ff66ff":{"lch":[68.0098958254125137,112.360313920932768,307.715012949244056],"luv":[68.0098958254125137,68.7346624616611592,-88.8841173702707437],"rgb":[1,0.4,1],"xyz":[0.640383218655645625,0.379854583207975549,0.985700181294539179],"hpluv":[307.715012949244056,209.642901019847784,68.0098958254125137],"hsluv":[307.715012949244056,100.000000000001421,68.0098958254125137]},"#ff7700":{"lch":[65.3236824647912755,127.817378582796977,27.3102887077963814],"luv":[65.3236824647912755,113.570196302134065,58.6437786953806466],"rgb":[1,0.466666666666666674,0],"xyz":[0.478356168307233265,0.344569743954078356,0.0413192750626848],"hpluv":[27.3102887077963814,248.289625700463205,65.3236824647912755],"hsluv":[27.3102887077963814,100.00000000000226,65.3236824647912755]},"#ff7711":{"lch":[65.3555057958206476,126.824695098806032,26.9045059733925385],"luv":[65.3555057958206476,113.097436843789765,57.3887886809793],"rgb":[1,0.466666666666666674,0.0666666666666666657],"xyz":[0.479367833806870369,0.344974410153933209,0.0466473800274404271],"hpluv":[26.9045059733925385,246.24134425049084,65.3555057958206476],"hsluv":[26.9045059733925385,99.9999999999999716,65.3555057958206476]},"#ff7722":{"lch":[65.4144320044565291,125.020679344179442,26.1430666348463],"luv":[65.4144320044565291,112.230643754756542,55.0858681158159058],"rgb":[1,0.466666666666666674,0.133333333333333331],"xyz":[0.481243191945347426,0.345724553409324,0.0565242662234196266],"hpluv":[26.1430666348463,242.520026060215031,65.4144320044565291],"hsluv":[26.1430666348463,100.000000000000156,65.4144320044565291]},"#ff7733":{"lch":[65.511267747206432,122.151716277204869,24.8632302030062533],"luv":[65.511267747206432,110.829965834679456,51.3591322215488688],"rgb":[1,0.466666666666666674,0.2],"xyz":[0.484330942677805132,0.346959653702307136,0.0727864200810307699],"hpluv":[24.8632302030062533,236.604443239770575,65.511267747206432],"hsluv":[24.8632302030062533,100.000000000000128,65.511267747206432]},"#ff7744":{"lch":[65.6506715027637853,118.22870540382597,22.9581907744090898],"luv":[65.6506715027637853,108.863777518532288,46.1162089276663139],"rgb":[1,0.466666666666666674,0.266666666666666663],"xyz":[0.488788937922024047,0.348742851799994702,0.0962651950339174084],"hpluv":[22.9581907744090898,228.519406804146513,65.6506715027637853],"hsluv":[22.9581907744090898,100.000000000000199,65.6506715027637853]},"#ff7755":{"lch":[65.8363783536997857,113.378413750733145,20.3056908730066645],"luv":[65.8363783536997857,106.332452226692425,39.3455754576116092],"rgb":[1,0.466666666666666674,0.333333333333333315],"xyz":[0.494751351961386032,0.351127817415739563,0.12766724230789131],"hpluv":[20.3056908730066645,218.526329281612362,65.8363783536997857],"hsluv":[20.3056908730066645,100.000000000000171,65.8363783536997857]},"#ff7766":{"lch":[66.0714111968285351,107.847817312906827,16.7638759706376135],"luv":[66.0714111968285351,103.264450834403533,31.1063481146080676],"rgb":[1,0.466666666666666674,0.4],"xyz":[0.502336347734894217,0.354161815725142881,0.167614886715035272],"hpluv":[16.7638759706376135,207.127185394700234,66.0714111968285351],"hsluv":[16.7638759706376135,100.000000000000426,66.0714111968285351]},"#ff7777":{"lch":[66.3581913431115851,102.006782949974053,12.1770506300619488],"luv":[66.3581913431115851,99.7116772923406671,21.5166256497442419],"rgb":[1,0.466666666666666674,0.466666666666666674],"xyz":[0.511650360755096067,0.357887420933223677,0.216668688621433181],"hpluv":[12.1770506300619488,195.062523033846361,66.3581913431115851],"hsluv":[12.1770506300619488,100.000000000000355,66.3581913431115851]},"#ff7788":{"lch":[66.6986047917809,96.3441833198397291,6.39999172914420456],"luv":[66.6986047917809,95.7437601312525,10.7393694179903871],"rgb":[1,0.466666666666666674,0.533333333333333326],"xyz":[0.52279077785704,0.362343587774001274,0.275341552025005376],"hpluv":[6.39999172914420456,183.293927388427107,66.6986047917809],"hsluv":[6.39999172914420456,100.000000000000639,66.6986047917809]},"#ff7799":{"lch":[67.0940474565320244,91.4474963932601,359.352586865695173],"luv":[67.0940474565320244,91.4416585161261679,-1.0332881570442134],"rgb":[1,0.466666666666666674,0.6],"xyz":[0.535847741966112623,0.367566373417630432,0.344108229666123255],"hpluv":[359.352586865695173,172.952623850798517,67.0940474565320244],"hsluv":[359.352586865695173,100.000000000000782,67.0940474565320244]},"#ff77aa":{"lch":[67.5454605183692,87.9484746627524,351.107126776790835],"luv":[67.5454605183692,86.8912550098467449,-13.5957345634056814],"rgb":[1,0.466666666666666674,0.66666666666666663],"xyz":[0.550905434931365234,0.373589450603731554,0.423412079283121856],"hpluv":[351.107126776790835,165.223368139110704,67.5454605183692],"hsluv":[351.107126776790835,100.000000000000938,67.5454605183692]},"#ff77bb":{"lch":[68.0533617234635244,86.4195813509952,341.973592157308417],"luv":[68.0533617234635244,82.1775887588569,-26.7429980866295693],"rgb":[1,0.466666666666666674,0.733333333333333282],"xyz":[0.568043027038701798,0.380444487446666313,0.513670064381763658],"hpluv":[341.973592157308417,161.139458954487083,68.0533617234635244],"hsluv":[341.973592157308417,100.000000000001037,68.0533617234635244]},"#ff77cc":{"lch":[68.6178757233526682,87.2373067072756214,332.49967924393593],"luv":[68.6178757233526682,77.3802105983984347,-40.2821385887937],"rgb":[1,0.466666666666666674,0.8],"xyz":[0.587335402482423552,0.388161437624155115,0.615276575052033814],"hpluv":[332.49967924393593,161.325977991170333,68.6178757233526682],"hsluv":[332.49967924393593,100.000000000001265,68.6178757233526682]},"#ff77dd":{"lch":[69.238765020261809,90.480647802514838,323.326201907778],"luv":[69.238765020261809,72.5699004301545756,-54.0403291840472],"rgb":[1,0.466666666666666674,0.866666666666666696],"xyz":[0.608853728033057151,0.396768767844408621,0.728606422952039812],"hpluv":[323.326201907778,165.823361543811586,69.238765020261809],"hsluv":[323.326201907778,100.00000000000145,69.238765020261809]},"#ff77ee":{"lch":[69.9154621504300593,95.9376886025569604,314.973456368277198],"luv":[69.9154621504300593,67.8067552495039791,-67.8696105553513149],"rgb":[1,0.466666666666666674,0.933333333333333348],"xyz":[0.632665908299231861,0.406293639950878638,0.854017239020563],"hpluv":[314.973456368277198,174.122680701596721,69.9154621504300593],"hsluv":[314.973456368277198,100.000000000001535,69.9154621504300593]},"#ff77ff":{"lch":[70.6471031550122,103.213892868752552,307.715012949244283],"luv":[70.6471031550122,63.1394826173239494,-81.6487196221654],"rgb":[1,0.466666666666666674,1],"xyz":[0.658836956709063282,0.416762059314811362,0.99185142731234488],"hpluv":[307.715012949244283,185.388643374650655,70.6471031550122],"hsluv":[307.715012949244283,100.000000000001975,70.6471031550122]},"#ff8800":{"lch":[68.6580440198892603,118.150361410828182,32.8458067740872153],"luv":[68.6580440198892603,99.2620471866307383,64.0823992202883375],"rgb":[1,0.533333333333333326,0],"xyz":[0.500428538032203774,0.388714483404019873,0.0486767316376747472],"hpluv":[32.8458067740872153,218.364961888913399,68.6580440198892603],"hsluv":[32.8458067740872153,100.000000000002245,68.6580440198892603]},"#ff8811":{"lch":[68.6874112197728408,117.19102013872596,32.4606037779481582],"luv":[68.6874112197728408,98.8811760474647485,62.89871401408422],"rgb":[1,0.533333333333333326,0.0666666666666666657],"xyz":[0.501440203531840933,0.389119149603874726,0.0540048366024303769],"hpluv":[32.4606037779481582,216.499308154785638,68.6874112197728408],"hsluv":[32.4606037779481582,100.000000000000739,68.6874112197728408]},"#ff8822":{"lch":[68.7417963707939492,115.443262249268372,31.7362513605757321],"luv":[68.7417963707939492,98.1820090833864754,60.724294076614548],"rgb":[1,0.533333333333333326,0.133333333333333331],"xyz":[0.503315561670317879,0.389869292859265526,0.0638817227984095765],"hpluv":[31.7362513605757321,213.101761826290613,68.7417963707939492],"hsluv":[31.7362513605757321,100.000000000000668,68.7417963707939492]},"#ff8833":{"lch":[68.8311889682804292,112.651741292777714,30.5141745142023382],"luv":[68.8311889682804292,97.0498776480180823,57.1990914683060439],"rgb":[1,0.533333333333333326,0.2],"xyz":[0.506403312402775696,0.391104393152248653,0.0801438766560207128],"hpluv":[30.5141745142023382,207.678703624478942,68.8311889682804292],"hsluv":[30.5141745142023382,100.000000000000824,68.8311889682804292]},"#ff8844":{"lch":[68.9599197258043688,108.808998086617962,28.6842020071901302],"luv":[68.9599197258043688,95.4557990826346554,52.2263198599069725],"rgb":[1,0.533333333333333326,0.266666666666666663],"xyz":[0.510861307646994556,0.392887591249936219,0.103622651608907351],"hpluv":[28.6842020071901302,200.2199693629492,68.9599197258043688],"hsluv":[28.6842020071901302,100.000000000000838,68.9599197258043688]},"#ff8855":{"lch":[69.1314852187197602,104.012526361958052,26.1137258191789492],"luv":[69.1314852187197602,93.395152113439849,45.7815596272609682],"rgb":[1,0.533333333333333326,0.333333333333333315],"xyz":[0.516823721686356485,0.39527255686568108,0.135024698882881267],"hpluv":[26.1137258191789492,190.918970683811096,69.1314852187197602],"hsluv":[26.1137258191789492,100.000000000000867,69.1314852187197602]},"#ff8866":{"lch":[69.3487452092138881,98.4723154092605171,22.6389332988698087],"luv":[69.3487452092138881,90.8849122177262529,37.9042165627661802],"rgb":[1,0.533333333333333326,0.4],"xyz":[0.524408717459864726,0.398306555175084398,0.174972343290025228],"hpluv":[22.6389332988698087,180.183437843423292,69.3487452092138881],"hsluv":[22.6389332988698087,100.000000000001066,69.3487452092138881]},"#ff8877":{"lch":[69.6140261744794344,92.5206854303452246,18.0637242730473773],"luv":[69.6140261744794344,87.9605480867009248,28.6883114314535526],"rgb":[1,0.533333333333333326,0.466666666666666674],"xyz":[0.533722730480066576,0.402032160383165194,0.224026145196423138],"hpluv":[18.0637242730473773,168.648085666048672,69.6140261744794344],"hsluv":[18.0637242730473773,100.000000000001108,69.6140261744794344]},"#ff8888":{"lch":[69.9291829132988596,86.6211090413054,12.1770506300619186],"luv":[69.9291829132988596,84.672173963834382,18.2712749359175248],"rgb":[1,0.533333333333333326,0.533333333333333326],"xyz":[0.544863147582010487,0.406488327223942791,0.282699008599995305],"hpluv":[12.1770506300619186,157.182652238587849,69.9291829132988596],"hsluv":[12.1770506300619186,100.000000000001251,69.9291829132988596]},"#ff8899":{"lch":[70.29563969089034,81.3665448969888274,4.80888772903122597],"luv":[70.29563969089034,81.0801238487794791,6.82115423812421362],"rgb":[1,0.533333333333333326,0.6],"xyz":[0.557920111691083132,0.411711112867571949,0.351465686241113184],"hpluv":[4.80888772903122597,146.878021536398364,70.29563969089034],"hsluv":[4.80888772903122597,100.00000000000135,70.29563969089034]},"#ff88aa":{"lch":[70.7144212664750427,77.4442353273614827,355.944797831634332],"luv":[70.7144212664750427,77.2503443699940533,-5.47666688388778589],"rgb":[1,0.533333333333333326,0.66666666666666663],"xyz":[0.572977804656335743,0.417734190053673071,0.430769535858111841],"hpluv":[355.944797831634332,138.969799542374091,70.7144212664750427],"hsluv":[355.944797831634332,100.000000000001648,70.7144212664750427]},"#ff88bb":{"lch":[71.1861792611668847,75.5334875912487718,345.875835641341098],"luv":[71.1861792611668847,73.2500487000805,-18.431986141845023],"rgb":[1,0.533333333333333326,0.733333333333333282],"xyz":[0.590115396763672306,0.42458922689660783,0.521027520956753532],"hpluv":[345.875835641341098,134.642814203514433,71.1861792611668847],"hsluv":[345.875835641341098,100.000000000001776,71.1861792611668847]},"#ff88cc":{"lch":[71.711216864189268,76.1313589407537563,335.260476444218114],"luv":[71.711216864189268,69.1440007334156377,-31.8604924121286039],"rgb":[1,0.533333333333333326,0.8],"xyz":[0.609407772207394061,0.432306177074096631,0.622634031627023687],"hpluv":[335.260476444218114,134.714956877670915,71.711216864189268],"hsluv":[335.260476444218114,100.000000000001933,71.711216864189268]},"#ff88dd":{"lch":[72.2895135005839649,79.3885839073469413,324.950129439258774],"luv":[72.2895135005839649,64.9916618916399784,-45.5920074067441803],"rgb":[1,0.533333333333333326,0.866666666666666696],"xyz":[0.63092609775802766,0.440913507294350138,0.735963879527029685],"hpluv":[324.950129439258774,139.354847315526115,72.2895135005839649],"hsluv":[324.950129439258774,100.000000000002245,72.2895135005839649]},"#ff88ee":{"lch":[72.9207502525545124,85.0855243828499,315.651995307064169],"luv":[72.9207502525545124,60.845281511842515,-59.4760302748021203],"rgb":[1,0.533333333333333326,0.933333333333333348],"xyz":[0.654738278024202369,0.450438379400820155,0.861374695595552908],"hpluv":[315.651995307064169,148.062090862911901,72.9207502525545124],"hsluv":[315.651995307064169,100.000000000002444,72.9207502525545124]},"#ff88ff":{"lch":[73.6043362991539709,92.7672005781522842,307.715012949244624],"luv":[73.6043362991539709,56.7488822053271349,-73.3847250560567375],"rgb":[1,0.533333333333333326,1],"xyz":[0.68090932643403379,0.460906798764752879,0.999208883887334753],"hpluv":[307.715012949244624,159.930161835956909,73.6043362991539709],"hsluv":[307.715012949244624,100.000000000002771,73.6043362991539709]},"#ff9900":{"lch":[72.2588108283115389,109.907462524380705,39.4434130396340095],"luv":[72.2588108283115389,84.8763034831777077,69.8259509464759418],"rgb":[1,0.6,0],"xyz":[0.526298138484671219,0.440453684308955595,0.057299931788497],"hpluv":[39.4434130396340095,193.008172097547572,72.2588108283115389],"hsluv":[39.4434130396340095,100.000000000002288,72.2588108283115389]},"#ff9911":{"lch":[72.2858317740783889,108.970035258541955,39.0927051304156805],"luv":[72.2858317740783889,84.5745536570817791,68.7139975401902348],"rgb":[1,0.6,0.0666666666666666657],"xyz":[0.527309803984308378,0.440858350508810448,0.0626280367532526389],"hpluv":[39.0927051304156805,191.2904264008464,72.2858317740783889],"hsluv":[39.0927051304156805,100.000000000001506,72.2858317740783889]},"#ff9922":{"lch":[72.3358777005795304,107.257428554778556,38.4317580680427469],"luv":[72.3358777005795304,84.0200042697796,66.6692947517044274],"rgb":[1,0.6,0.133333333333333331],"xyz":[0.529185162122785324,0.441608493764201249,0.0725049229492318315],"hpluv":[38.4317580680427469,188.15378179700545,72.3358777005795304],"hsluv":[38.4317580680427469,100.00000000000145,72.3358777005795304]},"#ff9933":{"lch":[72.418154282067718,104.508625212907305,37.3122251519614778],"luv":[72.418154282067718,83.1203251002183237,63.3487513620113845],"rgb":[1,0.6,0.2],"xyz":[0.532272912855243141,0.442843594057184375,0.0887670768068429816],"hpluv":[37.3122251519614778,183.123470124205028,72.418154282067718],"hsluv":[37.3122251519614778,100.00000000000162,72.418154282067718]},"#ff9944":{"lch":[72.5366731246789556,100.695423976150749,35.6250099256014607],"luv":[72.5366731246789556,81.8499313718691326,58.6528528219818952],"rgb":[1,0.6,0.266666666666666663],"xyz":[0.536730908099462,0.444626792154871942,0.11224585175972962],"hpluv":[35.6250099256014607,176.153561585765658,72.5366731246789556],"hsluv":[35.6250099256014607,100.000000000001748,72.5366731246789556]},"#ff9955":{"lch":[72.6946936633514582,95.8821930466240673,33.2320443565807508],"luv":[72.6946936633514582,80.201421842029859,52.5464259293328269],"rgb":[1,0.6,0.333333333333333315],"xyz":[0.54269332213882393,0.447011757770616802,0.143647899033703508],"hpluv":[33.2320443565807508,167.368827825995851,72.6946936633514582],"hsluv":[33.2320443565807508,100.000000000001705,72.6946936633514582]},"#ff9966":{"lch":[72.8949069034106,90.2347392462793749,29.9516480142673025],"luv":[72.8949069034106,78.1836232693519406,45.0514064077924345],"rgb":[1,0.6,0.4],"xyz":[0.550278317912332171,0.450045756080020121,0.183595543440847497],"hpluv":[29.9516480142673025,157.078197331028889,72.8949069034106],"hsluv":[29.9516480142673025,100.000000000001819,72.8949069034106]},"#ff9977":{"lch":[73.1395321193821,84.0351966301436,25.5464816978182121],"luv":[73.1395321193821,75.8195571045914,36.2396058633438045],"rgb":[1,0.6,0.466666666666666674],"xyz":[0.559592330932534,0.453771361288100916,0.232649345347245406],"hpluv":[25.5464816978182121,145.796926659053128,73.1395321193821],"hsluv":[25.5464816978182121,100.000000000002018,73.1395321193821]},"#ff9988":{"lch":[73.430374185650777,77.702838567593929,19.7240568661095921],"luv":[73.430374185650777,73.1439295084068419,26.2239718107454713],"rgb":[1,0.6,0.533333333333333326],"xyz":[0.570732748034477932,0.458227528128878514,0.291322208750817546],"hpluv":[19.7240568661095921,134.276641294628575,73.430374185650777],"hsluv":[19.7240568661095921,100.000000000002203,73.430374185650777]},"#ff9999":{"lch":[73.76886125649402,71.8160022700114098,12.1770506300620251],"luv":[73.76886125649402,70.2001752793754,15.1483851545719261],"rgb":[1,0.6,0.6],"xyz":[0.583789712143550577,0.463450313772507672,0.360088886391935481],"hpluv":[12.1770506300620251,123.534275619879125,73.76886125649402],"hsluv":[12.1770506300620251,100.000000000002331,73.76886125649402]},"#ff99aa":{"lch":[74.1560723225582592,67.1124973440613,2.7130535693684088],"luv":[74.1560723225582592,67.0372720786985923,3.17670458229478481],"rgb":[1,0.6,0.66666666666666663],"xyz":[0.598847405108803188,0.469473390958608794,0.439392736008934082],"hpluv":[2.7130535693684088,114.840746523486033,74.1560723225582592],"hsluv":[2.7130535693684088,100.00000000000253,74.1560723225582592]},"#ff99bb":{"lch":[74.5927597146433925,64.4136927281220864,351.502648062184],"luv":[74.5927597146433925,63.7066038913843187,-9.51800564715024322],"rgb":[1,0.6,0.733333333333333282],"xyz":[0.615984997216139751,0.476328427801543552,0.529650721107575828],"hpluv":[351.502648062184,109.577363966618833,74.5927597146433925],"hsluv":[351.502648062184,100.000000000002615,74.5927597146433925]},"#ff99cc":{"lch":[75.0793694015197,64.4152606478183145,339.305696269483292],"luv":[75.0793694015197,60.259134450288677,-22.7631834247409977],"rgb":[1,0.6,0.8],"xyz":[0.635277372659861506,0.484045377979032354,0.631257231777846],"hpluv":[339.305696269483292,108.869813431806975,75.0793694015197],"hsluv":[339.305696269483292,100.000000000002871,75.0793694015197]},"#ff99dd":{"lch":[75.6160606971696296,67.4118390527965232,327.324068761847229],"luv":[75.6160606971696296,56.7430830794555,-36.3947601601954887],"rgb":[1,0.6,0.866666666666666696],"xyz":[0.656795698210495105,0.49265270819928586,0.744587079677852],"hpluv":[327.324068761847229,113.125745227459021,75.6160606971696296],"hsluv":[327.324068761847229,100.00000000000324,75.6160606971696296]},"#ff99ee":{"lch":[76.202726253448489,73.1905233351813393,316.627151984536795],"luv":[76.202726253448489,53.2022056350908201,-50.2630880631028845],"rgb":[1,0.6,0.933333333333333348],"xyz":[0.680607878476669814,0.502177580305755877,0.869997895746375205],"hpluv":[316.627151984536795,123.107716827744753,76.202726253448489],"hsluv":[316.627151984536795,100.000000000003524,76.202726253448489]},"#ff99ff":{"lch":[76.8390127436129,81.2030526869262275,307.715012949245],"luv":[76.8390127436129,49.6746958291708154,-64.2367524082209229],"rgb":[1,0.6,1],"xyz":[0.706778926886501235,0.512645999669688601,1.00783208403815694],"hpluv":[307.715012949245,141.150312559224801,76.8390127436129],"hsluv":[307.715012949245,100.000000000003752,76.8390127436129]},"#ee0000":{"lch":[49.7142799595632,167.190689697178925,12.1770506300617765],"luv":[49.7142799595632,163.428976145092918,35.2660811203203934],"rgb":[0.933333333333333348,0,0],"xyz":[0.352591085030832,0.181804778219026603,0.0165277071108199],"hpluv":[12.1770506300617765,426.746789183125202,49.7142799595632],"hsluv":[12.1770506300617765,100.000000000002217,49.7142799595632]},"#ee0011":{"lch":[49.7630000621001756,165.722449822455,11.6881730851639158],"luv":[49.7630000621001756,162.286136628676445,33.5729092170260728],"rgb":[0.933333333333333348,0,0.0666666666666666657],"xyz":[0.353602750530469079,0.182209444418881455,0.0218558120755755342],"hpluv":[11.6881730851639158,422.585038037937124,49.7630000621001756],"hsluv":[11.6881730851639158,99.9999999999963762,49.7630000621001756]},"#ee0022":{"lch":[49.8531236873270558,163.0858535413212,10.7756858750078184],"luv":[49.8531236873270558,160.210108449799208,30.4912573667411486],"rgb":[0.933333333333333348,0,0.133333333333333331],"xyz":[0.355478108668946136,0.182959587674272284,0.0317326982715547268],"hpluv":[10.7756858750078184,415.110044299310516,49.8531236873270558],"hsluv":[10.7756858750078184,99.9999999999964473,49.8531236873270558]},"#ee0033":{"lch":[50.000975779064234,158.977402767524836,9.25647316775448559],"luv":[50.000975779064234,156.907230803998146,25.5721628363475],"rgb":[0.933333333333333348,0,0.2],"xyz":[0.358565859401403841,0.184194687967255383,0.047994852129165877],"hpluv":[9.25647316775448559,403.456061197389261,50.000975779064234],"hsluv":[9.25647316775448559,99.9999999999965183,50.000975779064234]},"#ee0044":{"lch":[50.2132784041556164,153.529579514286212,7.02933300215353],"luv":[50.2132784041556164,152.375594335021788,18.7885613308314312],"rgb":[0.933333333333333348,0,0.266666666666666663],"xyz":[0.363023854645622757,0.185977886064942977,0.0714736270820525155],"hpluv":[7.02933300215353,387.983100931209492,50.2132784041556164],"hsluv":[7.02933300215353,99.9999999999966462,50.2132784041556164]},"#ee0055":{"lch":[50.4951150037793326,147.071833727726926,3.99754465361350508],"luv":[50.4951150037793326,146.714013644902735,10.2529252527975352],"rgb":[0.933333333333333348,0,0.333333333333333315],"xyz":[0.368986268684984742,0.188362851680687809,0.102875674356026417],"hpluv":[3.99754465361350508,369.589367027053072,50.4951150037793326],"hsluv":[3.99754465361350508,99.999999999996831,50.4951150037793326]},"#ee0066":{"lch":[50.8502318550204109,140.098840030056522,0.0757634158231174915],"luv":[50.8502318550204109,140.0987175463531,0.185255592479522613],"rgb":[0.933333333333333348,0,0.4],"xyz":[0.376571264458492927,0.1913968499900911,0.142823318763170393],"hpluv":[0.0757634158231174915,349.60765112382461,50.8502318550204109],"hsluv":[0.0757634158231174915,99.9999999999970584,50.8502318550204109]},"#ee0077":{"lch":[51.2812017254514956,133.219993530026585,355.209470699020642],"luv":[51.2812017254514956,132.754613083251769,-11.1256182415379214],"rgb":[0.933333333333333348,0,0.466666666666666674],"xyz":[0.385885277478694833,0.195122455198171924,0.191877120669568302],"hpluv":[355.209470699020642,329.648072606093592,51.2812017254514956],"hsluv":[355.209470699020642,99.9999999999973284,51.2812017254514956]},"#ee0088":{"lch":[51.7895361854883163,127.090944021268115,349.407446028193533],"luv":[51.7895361854883163,124.925218603260163,-23.3623160055840167],"rgb":[0.933333333333333348,0,0.533333333333333326],"xyz":[0.397025694580638633,0.199578622038949521,0.250549984073140442],"hpluv":[349.407446028193533,311.395197619459395,51.7895361854883163],"hsluv":[349.407446028193533,99.9999999999974705,51.7895361854883163]},"#ee0099":{"lch":[52.3757812732210652,122.329563392952366,342.780178840499048],"luv":[52.3757812732210652,116.846263825073436,-36.2142611415956637],"rgb":[0.933333333333333348,0,0.6],"xyz":[0.410082658689711388,0.204801407682578679,0.319316661714258376],"hpluv":[342.780178840499048,296.374093031221,52.3757812732210652],"hsluv":[342.780178840499048,99.9999999999978,52.3757812732210652]},"#ee00aa":{"lch":[53.0396114453995722,119.424239873739239,335.563712743666827],"luv":[53.0396114453995722,108.726436909364494,-49.403552366347],"rgb":[0.933333333333333348,0,0.66666666666666663],"xyz":[0.425140351654963888,0.210824484868679773,0.398620511331257],"hpluv":[335.563712743666827,285.713971708863653,53.0396114453995722],"hsluv":[335.563712743666827,99.999999999998,53.0396114453995722]},"#ee00bb":{"lch":[53.779927529436435,118.655378520732356,328.101249142938343],"luv":[53.779927529436435,100.736423933687789,-62.6998544252744381],"rgb":[0.933333333333333348,0,0.733333333333333282],"xyz":[0.442277943762300563,0.217679521711614532,0.488878496429898723],"hpluv":[328.101249142938343,279.966806180862307,53.779927529436435],"hsluv":[328.101249142938343,99.9999999999982094,53.779927529436435]},"#ee00cc":{"lch":[54.5949595671901,120.061129768120921,320.773339602207614],"luv":[54.5949595671901,93.0053918954961,-75.9254368414351575],"rgb":[0.933333333333333348,0,0.8],"xyz":[0.461570319206022317,0.225396471889103334,0.590485007100168824],"hpluv":[320.773339602207614,279.054611328209262,54.5949595671901],"hsluv":[320.773339602207614,99.9999999999984,54.5949595671901]},"#ee00dd":{"lch":[55.4823728661035744,123.466264594666441,313.907226483092529],"luv":[55.4823728661035744,85.6229535549924634,-88.9529556421808252],"rgb":[0.933333333333333348,0,0.866666666666666696],"xyz":[0.483088644756655805,0.234003802109356868,0.703814855000174822],"hpluv":[313.907226483092529,282.379138449157608,55.4823728661035744],"hsluv":[313.907226483092529,99.9999999999986215,55.4823728661035744]},"#ee00ee":{"lch":[56.4393743497109597,128.559742977308588,307.715012949243601],"luv":[56.4393743497109597,78.644409501394918,-101.698890694877051],"rgb":[0.933333333333333348,0,0.933333333333333348],"xyz":[0.506900825022830626,0.243528674215826912,0.829225671068698],"hpluv":[307.715012949243601,289.042783730483393,56.4393743497109597],"hsluv":[307.715012949243601,99.9999999999988489,56.4393743497109597]},"#ee00ff":{"lch":[57.4628159598150745,134.982567880189606,302.284502363601803],"luv":[57.4628159598150745,72.0973885084188879,-114.115118199983058],"rgb":[0.933333333333333348,0,1],"xyz":[0.533071873432661936,0.253997093579759636,0.96705985936047989],"hpluv":[302.284502363601803,298.078126285043766,57.4628159598150745],"hsluv":[302.284502363601803,99.9999999999989484,57.4628159598150745]},"#ee1100":{"lch":[50.1937733395544683,164.746074066243921,12.6667024036514828],"luv":[50.1937733395544683,160.736507742479517,36.1253927174799117],"rgb":[0.933333333333333348,0.0666666666666666657,0],"xyz":[0.354595485291760382,0.185813578740883473,0.0171958405311293527],"hpluv":[12.6667024036514828,416.489977947977081,50.1937733395544683],"hsluv":[12.6667024036514828,100.000000000002245,50.1937733395544683]},"#ee1111":{"lch":[50.2417909300708345,163.305921695383518,12.1770506300617907],"luv":[50.2417909300708345,159.631613634988071,34.4466542507197317],"rgb":[0.933333333333333348,0.0666666666666666657,0.0666666666666666657],"xyz":[0.355607150791397486,0.186218244940738326,0.0225239454958849825],"hpluv":[12.1770506300617907,412.454596338970589,50.2417909300708345],"hsluv":[12.1770506300617907,96.6508962208003197,50.2417909300708345]},"#ee1122":{"lch":[50.3306190654122219,160.718934991358793,11.2629010575952293],"luv":[50.3306190654122219,157.623701713525833,31.390201064696047],"rgb":[0.933333333333333348,0.0666666666666666657,0.133333333333333331],"xyz":[0.357482508929874543,0.186968388196129154,0.032400831691864182],"hpluv":[11.2629010575952293,405.204351077732667,50.3306190654122219],"hsluv":[11.2629010575952293,96.6948337079543592,50.3306190654122219]},"#ee1133":{"lch":[50.4763571232054318,156.685700791802191,9.74029685215880647],"luv":[50.4763571232054318,154.427033260746356,26.5084935615454427],"rgb":[0.933333333333333348,0.0666666666666666657,0.2],"xyz":[0.360570259662332249,0.188203488489112253,0.0486629855494753252],"hpluv":[9.74029685215880647,393.895198182016713,50.4763571232054318],"hsluv":[9.74029685215880647,96.7647175585846,50.4763571232054318]},"#ee1144":{"lch":[50.6856484752898382,151.333831494518165,7.50679337730589413],"luv":[50.6856484752898382,150.036806479185287,19.7708183022028514],"rgb":[0.933333333333333348,0.0666666666666666657,0.266666666666666663],"xyz":[0.365028254906551164,0.189986686586799847,0.0721417605023619568],"hpluv":[7.50679337730589413,378.870112575267399,50.6856484752898382],"hsluv":[7.50679337730589413,96.8605546889772455,50.6856484752898382]},"#ee1155":{"lch":[50.9635312364098496,144.984673036864649,4.46374659640210858],"luv":[50.9635312364098496,144.544902405536135,11.283909082431693],"rgb":[0.933333333333333348,0.0666666666666666657,0.333333333333333315],"xyz":[0.370990668945913149,0.19237165220254468,0.103543807776335872],"hpluv":[4.46374659640210858,360.995599227985224,50.9635312364098496],"hsluv":[4.46374659640210858,96.9801964566503,50.9635312364098496]},"#ee1166":{"lch":[51.3137360134299598,138.123816003378664,0.523151936541392],"luv":[51.3137360134299598,138.118058344046318,1.26115288756691357],"rgb":[0.933333333333333348,0.0666666666666666657,0.4],"xyz":[0.378575664719421334,0.19540565051194797,0.143491452183479834],"hpluv":[0.523151936541392,341.565705345826359,51.3137360134299598],"hsluv":[0.523151936541392,97.1198273857598764,51.3137360134299598]},"#ee1177":{"lch":[51.7388469835676119,131.353183798903302,355.627348241097309],"luv":[51.7388469835676119,130.970848560864681,-10.014775152519368],"rgb":[0.933333333333333348,0.0666666666666666657,0.466666666666666674],"xyz":[0.38788967773962324,0.199131255720028794,0.192545254089877743],"hpluv":[355.627348241097309,322.153744971780554,51.7388469835676119],"hsluv":[355.627348241097309,97.2745732157476,51.7388469835676119]},"#ee1188":{"lch":[52.2404115410600411,125.324707533591734,349.782339698165117],"luv":[52.2404115410600411,123.337180279157977,-22.2311106147846438],"rgb":[0.933333333333333348,0.0666666666666666657,0.533333333333333326],"xyz":[0.39903009484156704,0.203587422560806391,0.251218117493449911],"hpluv":[349.782339698165117,304.417375015566734,52.2404115410600411],"hsluv":[349.782339698165117,97.4391430985313605,52.2404115410600411]},"#ee1199":{"lch":[52.819032808459994,120.657103381490217,343.097768544337384],"luv":[52.819032808459994,115.44498939014953,-35.079780802050081],"rgb":[0.933333333333333348,0.0666666666666666657,0.6],"xyz":[0.412087058950639795,0.208810208204435549,0.31998479513456779],"hpluv":[343.097768544337384,289.869003225703352,52.819032808459994],"hsluv":[343.097768544337384,97.6083995478766298,52.819032808459994]},"#ee11aa":{"lch":[53.4744599034404615,117.843047501566133,335.812437212199143],"luv":[53.4744599034404615,107.497497568615216,-48.2832461723726496],"rgb":[0.933333333333333348,0.0666666666666666657,0.66666666666666663],"xyz":[0.427144751915892296,0.214833285390536644,0.399288644751566446],"hpluv":[335.812437212199143,279.638449078323276,53.4744599034404615],"hsluv":[335.812437212199143,97.7777799659692,53.4744599034404615]},"#ee11bb":{"lch":[54.205681814132376,117.167943285093472,328.276238054291071],"luv":[54.205681814132376,99.6622453247977376,-61.6097702517929662],"rgb":[0.933333333333333348,0.0666666666666666657,0.733333333333333282],"xyz":[0.44428234402322897,0.221688322233471402,0.489546629850208137],"hpluv":[328.276238054291071,274.285798241860448,54.205681814132376],"hsluv":[328.276238054291071,97.9435422525978652,54.205681814132376]},"#ee11cc":{"lch":[55.0110259993956703,118.672848043699901,320.878255441103249],"luv":[55.0110259993956703,92.0672263164348266,-74.8790404666182781],"rgb":[0.933333333333333348,0.0666666666666666657,0.8],"xyz":[0.463574719466950724,0.229405272410960204,0.591153140520478293],"hpluv":[320.878255441103249,273.741691636115945,55.0110259993956703],"hsluv":[320.878255441103249,98.102849778989,55.0110259993956703]},"#ee11dd":{"lch":[55.8882602794840864,122.182226882396691,313.952719233652829],"luv":[55.8882602794840864,84.8023500190691522,-87.9605479586430334],"rgb":[0.933333333333333348,0.0666666666666666657,0.866666666666666696],"xyz":[0.485093045017584212,0.238012602631213738,0.704482988420484291],"hpluv":[313.952719233652829,277.412976370396279,55.8882602794840864],"hsluv":[313.952719233652829,98.2537358693348608,55.8882602794840864]},"#ee11ee":{"lch":[56.83469533821048,127.382376320214306,307.715012949243601],"luv":[56.83469533821048,77.9241738866570302,-100.767519176899128],"rgb":[0.933333333333333348,0.0666666666666666657,0.933333333333333348],"xyz":[0.508905225283758922,0.247537474737683783,0.829893804489007514],"hpluv":[307.715012949243601,284.403630900032795,56.83469533821048],"hsluv":[307.715012949243601,98.3949944120453495,56.83469533821048]},"#ee11ff":{"lch":[57.8472847680859275,133.910906422249354,302.2526850652647],"luv":[57.8472847680859275,71.4621107907268254,-113.248830369952643],"rgb":[0.933333333333333348,0.0666666666666666657,1],"xyz":[0.535076273693590343,0.258005894101616451,0.967727992780789359],"hpluv":[302.2526850652647,293.746227206253536,57.8472847680859275],"hsluv":[302.2526850652647,99.99999999999892,57.8472847680859275]},"#ee2200":{"lch":[51.0646940471157222,160.407609402057773,13.5847947923325787],"luv":[51.0646940471157222,155.919944837816502,37.677207378671163],"rgb":[0.933333333333333348,0.133333333333333331,0],"xyz":[0.358311109026528296,0.19324482621041944,0.018434381776051962],"hpluv":[13.5847947923325787,398.605749597291435,51.0646940471157222],"hsluv":[13.5847947923325787,100.000000000002203,51.0646940471157222]},"#ee2211":{"lch":[51.1114738997186322,159.015005648229618,13.0939108674416342],"luv":[51.1114738997186322,154.880623331235768,36.0244991337056817],"rgb":[0.933333333333333348,0.133333333333333331,0.0666666666666666657],"xyz":[0.3593227745261654,0.193649492410274293,0.0237624867408075952],"hpluv":[13.0939108674416342,394.783534202752207,51.1114738997186322],"hsluv":[13.0939108674416342,96.7702863870018462,51.1114738997186322]},"#ee2222":{"lch":[51.1980191888258105,156.511980987808,12.1770506300618031],"luv":[51.1980191888258105,152.990533465747774,33.0135860305098348],"rgb":[0.933333333333333348,0.133333333333333331,0.133333333333333331],"xyz":[0.361198132664642457,0.194399635665665121,0.0336393729367867877],"hpluv":[12.1770506300618031,387.912483642854795,51.1980191888258105],"hsluv":[12.1770506300618031,90.899918517349,51.1980191888258105]},"#ee2233":{"lch":[51.340031013958,152.605977320930094,10.6487510890373542],"luv":[51.340031013958,149.977869701108148,28.1996970549978769],"rgb":[0.933333333333333348,0.133333333333333331,0.2],"xyz":[0.364285883397100163,0.19563473595864822,0.0499015267943979379],"hpluv":[10.6487510890373542,377.185287566809563,51.340031013958],"hsluv":[10.6487510890373542,91.0856949770771,51.340031013958]},"#ee2244":{"lch":[51.5440125284501391,147.416232714385046,8.4042516634418849],"luv":[51.5440125284501391,145.833202035739902,21.5458314229178391],"rgb":[0.933333333333333348,0.133333333333333331,0.266666666666666663],"xyz":[0.368743878641319078,0.197417934056335814,0.0733803017472845764],"hpluv":[8.4042516634418849,362.916246958463432,51.5440125284501391],"hsluv":[8.4042516634418849,91.3409150161676848,51.5440125284501391]},"#ee2255":{"lch":[51.8149196409757,141.25016266814734,5.34127242035781613],"luv":[51.8149196409757,140.636840571385164,13.1486701942394504],"rgb":[0.933333333333333348,0.133333333333333331,0.333333333333333315],"xyz":[0.374706292680681063,0.199802899672080647,0.104782349021258478],"hpluv":[5.34127242035781613,345.918233291596209,51.8149196409757],"hsluv":[5.34127242035781613,91.6602615743055082,51.8149196409757]},"#ee2266":{"lch":[52.1564522427987924,134.577740656965489,1.36671179444129165],"luv":[52.1564522427987924,134.539455426625494,3.20986196595936],"rgb":[0.933333333333333348,0.133333333333333331,0.4],"xyz":[0.382291288454189249,0.202836897981483938,0.144729993428402454],"hpluv":[1.36671179444129165,327.419481975304109,52.1564522427987924],"hsluv":[1.36671179444129165,92.0339967122243365,52.1564522427987924]},"#ee2277":{"lch":[52.5712108639856694,127.988129961564283,356.416786702014292],"luv":[52.5712108639856694,127.737923683219179,-7.99901644943552803],"rgb":[0.933333333333333348,0.133333333333333331,0.466666666666666674],"xyz":[0.391605301474391154,0.206562503189564761,0.193783795334800363],"hpluv":[356.416786702014292,308.930679724572485,52.5712108639856694],"hsluv":[356.416786702014292,92.4494947830095,52.5712108639856694]},"#ee2288":{"lch":[53.0608018273771194,122.127216672078461,350.491948161024197],"luv":[53.0608018273771194,120.449481512132621,-20.1737318195523763],"rgb":[0.933333333333333348,0.133333333333333331,0.533333333333333326],"xyz":[0.402745718576334955,0.211018670030342359,0.25245665873837253],"hpluv":[350.491948161024197,292.063965437042782,53.0608018273771194],"hsluv":[350.491948161024197,92.892885362452958,53.0608018273771194]},"#ee2299":{"lch":[53.6259244704506557,117.615935516390621,343.699890485995525],"luv":[53.6259244704506557,112.888334232708232,-33.0110933105844282],"rgb":[0.933333333333333348,0.133333333333333331,0.6],"xyz":[0.415802682685407654,0.216241455673971517,0.32122333637949041],"hpluv":[343.699890485995525,278.311211390643507,53.6259244704506557],"hsluv":[343.699890485995525,93.3505397228777412,53.6259244704506557]},"#ee22aa":{"lch":[54.266455218013121,114.955451111725907,336.284451026203612],"luv":[54.266455218013121,105.247863162980167,-46.2346519390706305],"rgb":[0.933333333333333348,0.133333333333333331,0.66666666666666663],"xyz":[0.43086037565066021,0.222264532860072611,0.400527185996489],"hpluv":[336.284451026203612,268.805062052359688,54.266455218013121],"hsluv":[336.284451026203612,93.8102001508292,54.266455218013121]},"#ee22bb":{"lch":[54.981534566577821,114.440827463928798,328.608334651454868],"luv":[54.981534566577821,97.6897319326175,-59.6105633722921],"rgb":[0.933333333333333348,0.133333333333333331,0.733333333333333282],"xyz":[0.447997967757996884,0.22911956970300737,0.490785171095130757],"hpluv":[328.608334651454868,264.121319791368,54.981534566577821],"hsluv":[328.608334651454868,94.2616688954678636,54.981534566577821]},"#ee22cc":{"lch":[55.7696584616915629,116.118636638570607,321.077185717181408],"luv":[55.7696584616915629,90.3394913251054419,-72.9541916679335856],"rgb":[0.933333333333333348,0.133333333333333331,0.8],"xyz":[0.467290343201718583,0.236836519880496171,0.592391681765400913],"hpluv":[321.077185717181408,264.206361207665168,55.7696584616915629],"hsluv":[321.077185717181408,94.6970823725699518,55.7696584616915629]},"#ee22dd":{"lch":[56.6287730491083749,119.812596042269817,314.038835862099],"luv":[56.6287730491083749,83.2872216309056,-86.1295354880806201],"rgb":[0.933333333333333348,0.133333333333333331,0.866666666666666696],"xyz":[0.488808668752352182,0.245443850100749705,0.70572152966540691],"hpluv":[314.038835862099,268.475495638829329,56.6287730491083749],"hsluv":[314.038835862099,95.1108639535381,56.6287730491083749]},"#ee22ee":{"lch":[57.5563705104872128,125.203701850491953,307.715012949243658],"luv":[57.5563705104872128,76.5914038981754,-99.0440498261932163],"rgb":[0.933333333333333348,0.133333333333333331,0.933333333333333348],"xyz":[0.512620849018526892,0.254968722207219722,0.831132345733930133],"hpluv":[307.715012949243658,276.03432908057755,57.5563705104872128],"hsluv":[307.715012949243658,95.4994708803944263,57.5563705104872128]},"#ee22ff":{"lch":[58.5495832280214046,131.922896299071255,302.192710378625122],"luv":[58.5495832280214046,70.2843784028787582,-111.641196341030223],"rgb":[0.933333333333333348,0.133333333333333331,1],"xyz":[0.538791897428358313,0.265437141571152446,0.968966534025712],"hpluv":[302.192710378625122,285.914180736870946,58.5495832280214046],"hsluv":[302.192710378625122,99.9999999999989,58.5495832280214046]},"#ee3300":{"lch":[52.4512471844783761,153.77210005382733,15.1254552240259841],"luv":[52.4512471844783761,148.444942331914945,40.1242800687903269],"rgb":[0.933333333333333348,0.2,0],"xyz":[0.364428831115539142,0.205480270388441244,0.0204736224723888437],"hpluv":[15.1254552240259841,372.015515114283232,52.4512471844783761],"hsluv":[15.1254552240259841,100.000000000002174,52.4512471844783761]},"#ee3311":{"lch":[52.4961529429458693,152.446596739109111,14.6331501802662043],"luv":[52.4961529429458693,147.501711829562538,38.5124637576621893],"rgb":[0.933333333333333348,0.2,0.0666666666666666657],"xyz":[0.365440496615176247,0.205884936588296097,0.0258017274371444769],"hpluv":[14.6331501802662043,368.493287978140756,52.4961529429458693],"hsluv":[14.6331501802662043,96.9493433827183395,52.4961529429458693]},"#ee3322":{"lch":[52.5792408568970302,150.061966488521733,13.7129404445972121],"luv":[52.5792408568970302,145.784540850223095,35.5733247742160685],"rgb":[0.933333333333333348,0.2,0.133333333333333331],"xyz":[0.367315854753653304,0.206635079843686925,0.0356786136331236695],"hpluv":[13.7129404445972121,362.155969729293304,52.5792408568970302],"hsluv":[13.7129404445972121,91.3983957113456,52.5792408568970302]},"#ee3333":{"lch":[52.7156069212027916,146.335083442311,12.177050630061796],"luv":[52.7156069212027916,143.042611430097821,30.8669396171076365],"rgb":[0.933333333333333348,0.2,0.2],"xyz":[0.370403605486111,0.207870180136670024,0.0519407674907348127],"hpluv":[12.177050630061796,352.248031751653059,52.7156069212027916],"hsluv":[12.177050630061796,82.5426319963487316,52.7156069212027916]},"#ee3344":{"lch":[52.9115382124740705,141.372894204534333,9.91688783885485314],"luv":[52.9115382124740705,139.260586308771792,24.3471623953096028],"rgb":[0.933333333333333348,0.2,0.266666666666666663],"xyz":[0.374861600730329925,0.209653378234357618,0.0754195424436214512],"hpluv":[9.91688783885485314,339.043238938553714,52.9115382124740705],"hsluv":[9.91688783885485314,83.0163224279527867,52.9115382124740705]},"#ee3355":{"lch":[53.1718605143623222,135.462446214194244,6.82400118051175664],"luv":[53.1718605143623222,134.502806079917804,16.0956357737583851],"rgb":[0.933333333333333348,0.2,0.333333333333333315],"xyz":[0.38082401476969191,0.212038343850102451,0.106821589717595367],"hpluv":[6.82400118051175664,323.278173463789,53.1718605143623222],"hsluv":[6.82400118051175664,83.6110915378108,53.1718605143623222]},"#ee3366":{"lch":[53.5002196972096158,129.050901787066266,2.79642975700151464],"luv":[53.5002196972096158,128.89722530875369,6.29607494868134765],"rgb":[0.933333333333333348,0.2,0.4],"xyz":[0.388409010543200095,0.215072342159505742,0.146769234124739328],"hpluv":[2.79642975700151464,306.086943567777439,53.5002196972096158],"hsluv":[2.79642975700151464,84.310080928774866,53.5002196972096158]},"#ee3377":{"lch":[53.8992319384372252,122.709031404530748,357.759441587930837],"luv":[53.8992319384372252,122.615219389586755,-4.79732866099687261],"rgb":[0.933333333333333348,0.2,0.466666666666666674],"xyz":[0.397723023563402,0.218797947367586565,0.195823036031137238],"hpluv":[357.759441587930837,288.89051161323988,53.8992319384372252],"hsluv":[357.759441587930837,85.0909052409050872,53.8992319384372252]},"#ee3388":{"lch":[54.3705825415329,117.074862235921088,351.703100554939169],"luv":[54.3705825415329,115.849509832295894,-16.8942131860788436],"rgb":[0.933333333333333348,0.2,0.533333333333333326],"xyz":[0.408863440665345801,0.223254114208364163,0.254495899434709405],"hpluv":[351.703100554939169,273.2366774905733,54.3705825415329],"hsluv":[351.703100554939169,85.9285066952877,54.3705825415329]},"#ee3399":{"lch":[54.9151057717267292,112.774715889061866,344.730687431692274],"luv":[54.9151057717267292,108.793611621096844,-29.6999430015709507],"rgb":[0.933333333333333348,0.2,0.6],"xyz":[0.4219204047744185,0.22847689985199332,0.323262577075827284],"hpluv":[344.730687431692274,260.590898768244074,54.9151057717267292],"hsluv":[344.730687431692274,86.7978129198036896,54.9151057717267292]},"#ee33aa":{"lch":[55.5328602544255,110.325325240584178,337.093995035693695],"luv":[55.5328602544255,101.625579555338021,-42.9408776049389047],"rgb":[0.933333333333333348,0.2,0.66666666666666663],"xyz":[0.436978097739671056,0.234499977038094415,0.402566426692825885],"hpluv":[337.093995035693695,252.095155701888757,55.5328602544255],"hsluv":[337.093995035693695,87.6758366884225779,55.5328602544255]},"#ee33bb":{"lch":[56.2232062298057826,110.03895679054483,329.178007243031175],"luv":[56.2232062298057826,94.4974163460242664,-56.3809392922602726],"rgb":[0.933333333333333348,0.2,0.733333333333333282],"xyz":[0.454115689847007731,0.241355013881029173,0.492824411791467631],"hpluv":[329.178007243031175,248.353441541401367,56.2232062298057826],"hsluv":[329.178007243031175,88.5430404155392665,56.2232062298057826]},"#ee33cc":{"lch":[56.9848866198670123,111.971807156825847,321.417898872172259],"luv":[56.9848866198670123,87.5300782585605788,-69.8295854062993726],"rgb":[0.933333333333333348,0.2,0.8],"xyz":[0.47340806529072943,0.249071964058517975,0.594430922461737787],"hpluv":[321.417898872172259,249.337916143678171,56.9848866198670123],"hsluv":[321.417898872172259,89.3839737673679764,56.9848866198670123]},"#ee33dd":{"lch":[57.8161114567543848,115.945977330727956,314.185904182223908],"luv":[57.8161114567543848,80.813036999634221,-83.1427850752753557],"rgb":[0.933333333333333348,0.2,0.866666666666666696],"xyz":[0.494926390841363029,0.257679294278771509,0.707760770361743785],"hpluv":[314.185904182223908,254.475591939392586,57.8161114567543848],"hsluv":[314.185904182223908,90.1873197259471482,57.8161114567543848]},"#ee33ee":{"lch":[58.7146439354817886,121.632779311923699,307.715012949243715],"luv":[58.7146439354817886,74.4069479563921448,-96.2192241652253415],"rgb":[0.933333333333333348,0.2,0.933333333333333348],"xyz":[0.518738571107537738,0.267204166385241526,0.833171586430267],"hpluv":[307.715012949243715,262.87151341613469,58.7146439354817886],"hsluv":[307.715012949243715,90.9455375510239747,58.7146439354817886]},"#ee33ff":{"lch":[59.6778857977730581,128.651158016084139,302.091050100274117],"luv":[59.6778857977730581,68.3480180420837229,-108.993893813362092],"rgb":[0.933333333333333348,0.2,1],"xyz":[0.544909619517369159,0.27767258574917425,0.971005774722048853],"hpluv":[302.091050100274117,273.551812848380507,59.6778857977730581],"hsluv":[302.091050100274117,99.9999999999986784,59.6778857977730581]},"#ee4400":{"lch":[54.3591594970822598,145.188828472067655,17.4116852889838647],"luv":[54.3591594970822598,138.536177662057611,43.4456372018905412],"rgb":[0.933333333333333348,0.266666666666666663,0],"xyz":[0.373261401598505183,0.223145411354373546,0.023417812633377437],"hpluv":[17.4116852889838647,338.922026437804789,54.3591594970822598],"hsluv":[17.4116852889838647,100.000000000002217,54.3591594970822598]},"#ee4411":{"lch":[54.4016650840252112,143.940172045268554,16.9187727396215735],"luv":[54.4016650840252112,137.710194578710485,41.8888462184768713],"rgb":[0.933333333333333348,0.266666666666666663,0.0666666666666666657],"xyz":[0.374273067098142287,0.223550077554228399,0.0287459175981330667],"hpluv":[16.9187727396215735,335.744689025208913,54.4016650840252112],"hsluv":[16.9187727396215735,97.1754310281257574,54.4016650840252112]},"#ee4422":{"lch":[54.4803236312215944,141.690847159829417,15.9963876830432117],"luv":[54.4803236312215944,136.204446081142294,39.0467032744039173],"rgb":[0.933333333333333348,0.266666666666666663,0.133333333333333331],"xyz":[0.376148425236619344,0.224300220809619227,0.0386228037941122662],"hpluv":[15.9963876830432117,330.020900264600868,54.4803236312215944],"hsluv":[15.9963876830432117,92.0288025918740118,54.4803236312215944]},"#ee4433":{"lch":[54.6094526105793534,138.167821982121467,14.4538486850626899],"luv":[54.6094526105793534,133.794673004457735,34.4867004352900608],"rgb":[0.933333333333333348,0.266666666666666663,0.2],"xyz":[0.37923617596907705,0.225535321102602326,0.0548849576517234095],"hpluv":[14.4538486850626899,321.054243711338643,54.6094526105793534],"hsluv":[14.4538486850626899,83.7991355104008591,54.6094526105793534]},"#ee4444":{"lch":[54.7950558424119549,133.462657054844783,12.1770506300618084],"luv":[54.7950558424119549,130.459808710538397,28.151716454753565],"rgb":[0.933333333333333348,0.266666666666666663,0.266666666666666663],"xyz":[0.383694171213295965,0.22731851920028992,0.078363732604610048],"hpluv":[12.1770506300618084,309.070617226475065,54.7950558424119549],"hsluv":[12.1770506300618084,79.6495466444067546,54.7950558424119549]},"#ee4455":{"lch":[55.04178262974213,127.837203216659944,9.0482956458548145],"luv":[55.04178262974213,126.246413461005446,20.1045670057943724],"rgb":[0.933333333333333348,0.266666666666666663,0.333333333333333315],"xyz":[0.38965658525265795,0.229703484816034753,0.109765779878583963],"hpluv":[9.0482956458548145,294.716259365516066,55.04178262974213],"hsluv":[9.0482956458548145,80.0457187830871106,55.04178262974213]},"#ee4466":{"lch":[55.3531965298607105,121.710491561886229,4.95183922571805102],"luv":[55.3531965298607105,121.256220070521849,10.5058483924504795],"rgb":[0.933333333333333348,0.266666666666666663,0.4],"xyz":[0.397241581026166135,0.232737483125438044,0.149713424285727925],"hpluv":[4.95183922571805102,279.013127650855779,55.3531965298607105],"hsluv":[4.95183922571805102,80.511500113091131,55.3531965298607105]},"#ee4477":{"lch":[55.7319177265462855,115.631099927359429,359.795147057523252],"luv":[55.7319177265462855,115.63036086114974,-0.41342173536332294],"rgb":[0.933333333333333348,0.266666666666666663,0.466666666666666674],"xyz":[0.406555594046368041,0.236463088333518867,0.198767226192125834],"hpluv":[359.795147057523252,263.275227085929203,55.7319177265462855],"hsluv":[359.795147057523252,81.0316034214938412,55.7319177265462855]},"#ee4488":{"lch":[56.1797144871475069,110.229334232011354,353.550243523911263],"luv":[56.1797144871475069,109.531664472369371,-12.3822697089333467],"rgb":[0.933333333333333348,0.266666666666666663,0.533333333333333326],"xyz":[0.417696011148311841,0.240919255174296465,0.257440089595698],"hpluv":[353.550243523911263,248.975712077739217,56.1797144871475069],"hsluv":[353.550243523911263,81.5885451367485217,56.1797144871475069]},"#ee4499":{"lch":[56.6975745677487,106.142668326601637,346.310852745323245],"luv":[56.6975745677487,103.127575819694869,-25.1190992084518889],"rgb":[0.933333333333333348,0.266666666666666663,0.6],"xyz":[0.430752975257384541,0.246142040817925623,0.326206767236815909],"hpluv":[346.310852745323245,237.55536706581762,56.6975745677487],"hsluv":[346.310852745323245,82.1643886194057,56.6975745677487]},"#ee44aa":{"lch":[57.2857706939250164,103.913945498461985,338.339047623856459],"luv":[57.2857706939250164,96.5759938315173798,-38.356035828954532],"rgb":[0.933333333333333348,0.266666666666666663,0.66666666666666663],"xyz":[0.445810668222637096,0.252165118004026745,0.405510616853814509],"hpluv":[338.339047623856459,230.179372132151769,57.2857706939250164],"hsluv":[338.339047623856459,82.742186475039972,57.2857706939250164]},"#ee44bb":{"lch":[57.9439265752057224,103.883653730246948,330.054621671216069],"luv":[57.9439265752057224,90.015359877018625,-51.8560362788815183],"rgb":[0.933333333333333348,0.266666666666666663,0.733333333333333282],"xyz":[0.462948260329973771,0.259020154846961503,0.495768601952456256],"hpluv":[330.054621671216069,227.498543532010189,57.9439265752057224],"hsluv":[330.054621671216069,83.3069826860278,57.9439265752057224]},"#ee44cc":{"lch":[58.6710858878032866,106.123661593235155,321.940977409416575],"luv":[58.6710858878032866,83.5592367986741493,-65.4223623509468837],"rgb":[0.933333333333333348,0.266666666666666663,0.8],"xyz":[0.48224063577369547,0.266737105024450305,0.597375112622726356],"hpluv":[321.940977409416575,229.523641905846944,58.6710858878032866],"hsluv":[321.940977409416575,83.8463488142865288,58.6710858878032866]},"#ee44dd":{"lch":[59.4657843936948041,110.45324904546132,314.41066654104867],"luv":[59.4657843936948041,77.2947793232282407,-78.9014405069524116],"rgb":[0.933333333333333348,0.266666666666666663,0.866666666666666696],"xyz":[0.503758961324329069,0.275344435244703811,0.710704960522732354],"hpluv":[314.41066654104867,235.695163072106425,59.4657843936948041],"hsluv":[314.41066654104867,84.3505154479208699,59.4657843936948041]},"#ee44ee":{"lch":[60.3261240941145189,116.527805305600168,307.715012949243771],"luv":[60.3261240941145189,71.28406005268711,-92.180866733529669],"rgb":[0.933333333333333348,0.266666666666666663,0.933333333333333348],"xyz":[0.527571141590503778,0.284869307351173828,0.836115776591255577],"hpluv":[307.715012949243771,245.111377339321677,60.3261240941145189],"hsluv":[307.715012949243771,84.8122051950840898,60.3261240941145189]},"#ee44ff":{"lch":[61.2498476847862321,123.946828366557639,301.937515996566106],"luv":[61.2498476847862321,65.5671420475233617,-105.184438705774298],"rgb":[0.933333333333333348,0.266666666666666663,1],"xyz":[0.553742190000335199,0.295337726715106552,0.973949964883037422],"hpluv":[301.937515996566106,256.785047727470896,61.2498476847862321],"hsluv":[301.937515996566106,99.9999999999986073,61.2498476847862321]},"#ee5500":{"lch":[56.7595334156469136,135.29504726150742,20.5772435658132551],"luv":[56.7595334156469136,126.663115619922038,47.5521288161507414],"rgb":[0.933333333333333348,0.333333333333333315,0],"xyz":[0.385074658312851148,0.24677192478306581,0.0273555648714926478],"hpluv":[20.5772435658132551,302.470071141489655,56.7595334156469136],"hsluv":[20.5772435658132551,100.000000000002331,56.7595334156469136]},"#ee5511":{"lch":[56.7992830001534799,134.121232245619609,20.0864579205919],"luv":[56.7992830001534799,125.963368804879124,46.0622910677426],"rgb":[0.933333333333333348,0.333333333333333315,0.0666666666666666657],"xyz":[0.386086323812488252,0.247176590982920663,0.0326836698362482775],"hpluv":[20.0864579205919,299.636011805134103,56.7992830001534799],"hsluv":[20.0864579205919,97.4301566790671245,56.7992830001534799]},"#ee5522":{"lch":[56.8728535321199331,132.003018379302972,19.1666168944474329],"luv":[56.8728535321199331,124.685803630375247,43.3387498007741385],"rgb":[0.933333333333333348,0.333333333333333315,0.133333333333333331],"xyz":[0.387961681950965309,0.247926734238311491,0.042560556032227477],"hpluv":[19.1666168944474329,294.522290528054612,56.8728535321199331],"hsluv":[19.1666168944474329,92.7404035063857748,56.8728535321199331]},"#ee5533":{"lch":[56.9936637318031813,128.675597773649343,17.6241311186411558],"luv":[56.9936637318031813,122.635981466153211,38.9592801812266671],"rgb":[0.933333333333333348,0.333333333333333315,0.2],"xyz":[0.391049432683423,0.24916183453129459,0.0588227098898386203],"hpluv":[17.6241311186411558,286.489655583397507,56.9936637318031813],"hsluv":[17.6241311186411558,85.2217597168545353,56.9936637318031813]},"#ee5544":{"lch":[57.1673833238913431,124.212647444540593,15.3377586553938237],"luv":[57.1673833238913431,119.788604494467549,32.8553194848226298],"rgb":[0.933333333333333348,0.333333333333333315,0.266666666666666663],"xyz":[0.39550742792764193,0.250945032628982156,0.0823014848427252588],"hpluv":[15.3377586553938237,275.712737821839653,57.1673833238913431],"hsluv":[15.3377586553938237,78.8138286806830308,57.1673833238913431]},"#ee5555":{"lch":[57.3984455800741813,118.847398490007407,12.1770506300618084],"luv":[57.3984455800741813,116.173386735287238,25.068871978930396],"rgb":[0.933333333333333348,0.333333333333333315,0.333333333333333315],"xyz":[0.401469841967003915,0.253329998244727,0.113703532116699174],"hpluv":[12.1770506300618084,262.741620924066638,57.3984455800741813],"hsluv":[12.1770506300618084,79.1862648733910817,57.3984455800741813]},"#ee5566":{"lch":[57.6903015433249777,112.967028718059339,8.00617638558467881],"luv":[57.6903015433249777,111.865945908872092,15.7340307391382019],"rgb":[0.933333333333333348,0.333333333333333315,0.4],"xyz":[0.409054837740512101,0.256363996554130336,0.153651176523843136],"hpluv":[8.00617638558467881,248.478160638648092,57.6903015433249777],"hsluv":[8.00617638558467881,79.626682914648967,57.6903015433249777]},"#ee5577":{"lch":[58.0455538260385,107.095574323644513,2.70497781295448236],"luv":[58.0455538260385,106.976246145051803,5.05418642558356],"rgb":[0.933333333333333348,0.333333333333333315,0.466666666666666674],"xyz":[0.418368850760714,0.260089601762211131,0.202704978430241045],"hpluv":[2.70497781295448236,234.121819944652458,58.0455538260385],"hsluv":[2.70497781295448236,80.121743738144815,58.0455538260385]},"#ee5588":{"lch":[58.4660405277881523,101.857434077675435,356.214905006905212],"luv":[58.4660405277881523,101.63524992227579,-6.72405012805051783],"rgb":[0.933333333333333348,0.333333333333333315,0.533333333333333326],"xyz":[0.429509267862657806,0.264545768602988729,0.261377841833813185],"hpluv":[356.214905006905212,221.069268787819283,58.4660405277881523],"hsluv":[356.214905006905212,80.6557447307456385,58.4660405277881523]},"#ee5599":{"lch":[58.9528982622070714,97.9100075268454475,348.609359498013816],"luv":[58.9528982622070714,95.9815181358717808,-19.3369529719717974],"rgb":[0.933333333333333348,0.333333333333333315,0.6],"xyz":[0.442566231971730506,0.269768554246617887,0.33014451947493112],"hpluv":[348.609359498013816,210.746926462762332,58.9528982622070714],"hsluv":[348.609359498013816,81.2121283261168685,58.9528982622070714]},"#ee55aa":{"lch":[59.5066178042993812,95.8379147411847327,340.160257686713578],"luv":[59.5066178042993812,90.1495111294489817,-32.5264745255299346],"rgb":[0.933333333333333348,0.333333333333333315,0.66666666666666663],"xyz":[0.457623924936983062,0.275791631432719,0.40944836909192972],"hpluv":[340.160257686713578,204.36730380296666,59.5066178042993812],"hsluv":[340.160257686713578,81.7747968800248515,59.5066178042993812]},"#ee55bb":{"lch":[60.1270988419473156,96.02691270708236,331.338718337462637],"luv":[60.1270988419473156,84.2607812264238305,-46.0574501157669],"rgb":[0.933333333333333348,0.333333333333333315,0.733333333333333282],"xyz":[0.474761517044319736,0.282646668275653767,0.499706354190571467],"hpluv":[331.338718337462637,202.657202566236862,60.1270988419473156],"hsluv":[331.338718337462637,82.3290961128101202,60.1270988419473156]},"#ee55cc":{"lch":[60.8137066481247359,98.5745380895967855,322.704854800823],"luv":[60.8137066481247359,78.4184921400445774,-59.728382282288],"rgb":[0.933333333333333348,0.333333333333333315,0.8],"xyz":[0.494053892488041435,0.290363618453142569,0.601312864860841567],"hpluv":[322.704854800823,205.68499115665557,60.8137066481247359],"hsluv":[322.704854800823,82.862416210457269,60.8137066481247359]},"#ee55dd":{"lch":[61.5653314057239669,103.296154527471415,314.73674606959],"luv":[61.5653314057239669,72.7050419742243577,-73.3762387404091925],"rgb":[0.933333333333333348,0.333333333333333315,0.866666666666666696],"xyz":[0.515572218038675,0.298970948673396075,0.714642712760847565],"hpluv":[314.73674606959,212.905685416828703,61.5653314057239669],"hsluv":[314.73674606959,83.3644351442966496,61.5653314057239669]},"#ee55ee":{"lch":[62.3804497031794796,109.822432229930158,307.715012949243942],"luv":[62.3804497031794796,67.1821530808003473,-86.8764923804219364],"rgb":[0.933333333333333348,0.333333333333333315,0.933333333333333348],"xyz":[0.539384398304849744,0.308495820779866092,0.840053528829370788],"hpluv":[307.715012949243942,223.399338603574023,62.3804497031794796],"hsluv":[307.715012949243942,83.8270760150894318,62.3804497031794796]},"#ee55ff":{"lch":[63.2571870514493355,117.722992850638121,301.718618818209791],"luv":[63.2571870514493355,61.8926401270512301,-100.139922827085911],"rgb":[0.933333333333333348,0.333333333333333315,1],"xyz":[0.565555446714681165,0.318964240143798816,0.977887717121152633],"hpluv":[301.718618818209791,236.15152010236153,63.2571870514493355],"hsluv":[301.718618818209791,99.9999999999986358,63.2571870514493355]},"#ee6600":{"lch":[59.6010827175637274,124.896403377083828,24.7633991985742],"luv":[59.6010827175637274,113.411584725929117,52.315619335764687],"rgb":[0.933333333333333348,0.4,0],"xyz":[0.400102716018697624,0.276828040194759151,0.032364917440108],"hpluv":[24.7633991985742,265.910269095548301,59.6010827175637274],"hsluv":[24.7633991985742,100.000000000002458,59.6010827175637274]},"#ee6611":{"lch":[59.6379025762155521,123.785593795891074,24.2806773941880323],"luv":[59.6379025762155521,112.835768380983566,50.9014990474188],"rgb":[0.933333333333333348,0.4,0.0666666666666666657],"xyz":[0.401114381518334728,0.277232706394614,0.0376930224048636284],"hpluv":[24.2806773941880323,263.38259338209491,59.6379025762155521],"hsluv":[24.2806773941880323,97.6946368166697425,59.6379025762155521]},"#ee6622":{"lch":[59.7060621192549235,121.776511986799889,23.3741045361832462],"luv":[59.7060621192549235,111.782804083827386,48.312768320888857],"rgb":[0.933333333333333348,0.4,0.133333333333333331],"xyz":[0.402989739656811785,0.277982849650004804,0.0475699086008428279],"hpluv":[23.3741045361832462,258.812011755725052,59.7060621192549235],"hsluv":[23.3741045361832462,93.4807634058905847,59.7060621192549235]},"#ee6633":{"lch":[59.818019190990654,118.60827278102343,21.848413141726418],"luv":[59.818019190990654,110.088842330137865,44.1403349161252621],"rgb":[0.933333333333333348,0.4,0.2],"xyz":[0.406077490389269491,0.279217949942987931,0.0638320624584539642],"hpluv":[21.848413141726418,251.606745577849637,59.818019190990654],"hsluv":[21.848413141726418,86.7067277856042722,59.818019190990654]},"#ee6644":{"lch":[59.9790782653121,114.334087778781978,19.5741908506499591],"luv":[59.9790782653121,107.726545105393242,38.3050271878496318],"rgb":[0.933333333333333348,0.4,0.266666666666666663],"xyz":[0.410535485633488406,0.281001148040675497,0.0873108374113406],"hpluv":[19.5741908506499591,241.888527179759762,59.9790782653121],"hsluv":[19.5741908506499591,77.7164494297015551,59.9790782653121]},"#ee6655":{"lch":[60.1934276072459227,109.155383321287928,16.4048569251700904],"luv":[60.1934276072459227,104.711671726378157,30.827966398783424],"rgb":[0.933333333333333348,0.4,0.333333333333333315],"xyz":[0.416497899672850391,0.283386113656420358,0.118712884685314518],"hpluv":[16.4048569251700904,230.109957101660228,60.1934276072459227],"hsluv":[16.4048569251700904,78.0627041699660822,60.1934276072459227]},"#ee6666":{"lch":[60.4643778553048179,103.423697151150392,12.1770506300619203],"luv":[60.4643778553048179,101.096711576265875,21.8155000143976636],"rgb":[0.933333333333333348,0.4,0.4],"xyz":[0.424082895446358576,0.286420111965823676,0.15866052909245848],"hpluv":[12.1770506300619203,217.050003231938149,60.4643778553048179],"hsluv":[12.1770506300619203,78.4746058088251601,60.4643778553048179]},"#ee6677":{"lch":[60.7944870758990845,97.6355083856116,6.72933164538236728],"luv":[60.7944870758990845,96.9628770314166388,11.4408468002682859],"rgb":[0.933333333333333348,0.4,0.466666666666666674],"xyz":[0.433396908466560482,0.290145717173904472,0.207714330998856389],"hpluv":[6.72933164538236728,203.79002370037793,60.7944870758990845],"hsluv":[6.72933164538236728,78.9407958828298177,60.7944870758990845]},"#ee6688":{"lch":[61.1856375663111294,92.4106294683140419,359.951978350089689],"luv":[61.1856375663111294,92.4105970103857,-0.0774526573243247418],"rgb":[0.933333333333333348,0.4,0.533333333333333326],"xyz":[0.444537325568504282,0.294601884014682069,0.266387194402428529],"hpluv":[359.951978350089689,191.6512981090967,61.1856375663111294],"hsluv":[359.951978350089689,79.4474583444281706,61.1856375663111294]},"#ee6699":{"lch":[61.6390913266860281,88.437141466109523,351.875732288608958],"luv":[61.6390913266860281,87.5495765855601746,-12.4979850530316181],"rgb":[0.933333333333333348,0.4,0.6],"xyz":[0.457594289677577,0.299824669658311227,0.335153872043546464],"hpluv":[351.875732288608958,182.061365307506776,61.6390913266860281],"hsluv":[351.875732288608958,79.9795786975914353,61.6390913266860281]},"#ee66aa":{"lch":[62.1555369290736337,86.3639450462453624,342.77320214224],"luv":[62.1555369290736337,82.489654306882187,-25.5770978862333536],"rgb":[0.933333333333333348,0.4,0.66666666666666663],"xyz":[0.472651982642829538,0.305847746844412349,0.414457721660545064],"hpluv":[342.77320214224,176.316102232879075,62.1555369290736337],"hsluv":[342.77320214224,80.5221008496243,62.1555369290736337]},"#ee66bb":{"lch":[62.735134131647655,86.6495273870251168,333.187217955259598],"luv":[62.735134131647655,77.3334216921159765,-39.0855790002422907],"rgb":[0.933333333333333348,0.4,0.733333333333333282],"xyz":[0.489789574750166212,0.312702783687347108,0.504715706759186755],"hpluv":[333.187217955259598,175.264796900814019,62.735134131647655],"hsluv":[333.187217955259598,81.0608551813628679,62.735134131647655]},"#ee66cc":{"lch":[63.3775592853136516,89.4351699392481549,323.800511847500275],"luv":[63.3775592853136516,72.1711045195964545,-52.8202735176909144],"rgb":[0.933333333333333348,0.4,0.8],"xyz":[0.509081950193887911,0.320419733864835909,0.606322217429456911],"hpluv":[323.800511847500275,179.065596131410075,63.3775592853136516],"hsluv":[323.800511847500275,81.5831918811758072,63.3775592853136516]},"#ee66dd":{"lch":[64.0820526997291751,94.5324861988586918,315.200217206616742],"luv":[64.0820526997291751,67.0777383779463179,-66.6105694393704795],"rgb":[0.933333333333333348,0.4,0.866666666666666696],"xyz":[0.53060027574452151,0.329027064085089416,0.719652065329462909],"hpluv":[315.200217206616742,187.190580763285084,64.0820526997291751],"hsluv":[315.200217206616742,82.0783141076240241,64.0820526997291751]},"#ee66ee":{"lch":[64.8474680131467,101.534802649490857,307.715012949244169],"luv":[64.8474680131467,62.1123254704966499,-80.32045302236628],"rgb":[0.933333333333333348,0.4,0.933333333333333348],"xyz":[0.55441245601069622,0.338551936191559433,0.845062881397986132],"hpluv":[307.715012949244169,198.683239249207219,64.8474680131467],"hsluv":[307.715012949244169,82.5373501246235,64.8474680131467]},"#ee66ff":{"lch":[65.6723229483953759,109.966867844968618,301.415067453827589],"luv":[65.6723229483953759,57.3184789471434897,-93.8472375449520797],"rgb":[0.933333333333333348,0.4,1],"xyz":[0.580583504420527641,0.349020355555492157,0.982897069689768088],"hpluv":[301.415067453827589,212.480364902930489,65.6723229483953759],"hsluv":[301.415067453827589,99.9999999999984794,65.6723229483953759]},"#ee7700":{"lch":[62.8217158048736763,114.851740825540901,30.0981414692213356],"luv":[62.8217158048736763,99.3660150566978,57.5961580525066097],"rgb":[0.933333333333333348,0.466666666666666674,0],"xyz":[0.418556454072115225,0.313735516301594908,0.0385161634579137],"hpluv":[30.0981414692213356,231.988851559171735,62.8217158048736763],"hsluv":[30.0981414692213356,100.000000000002203,62.8217158048736763]},"#ee7711":{"lch":[62.8555901763931075,113.786950077776382,29.6341042910547],"luv":[62.8555901763931075,98.9037041004629458,56.2630191441096059],"rgb":[0.933333333333333348,0.466666666666666674,0.0666666666666666657],"xyz":[0.419568119571752329,0.314140182501449761,0.0438442684226693288],"hpluv":[29.6341042910547,229.71421718860654,62.8555901763931075],"hsluv":[29.6341042910547,97.9532933827149463,62.8555901763931075]},"#ee7722":{"lch":[62.9183073649527955,111.855609649988921,28.7604537228304977],"luv":[62.9183073649527955,98.0569879769147406,53.8191835600085398],"rgb":[0.933333333333333348,0.466666666666666674,0.133333333333333331],"xyz":[0.421443477710229386,0.314890325756840561,0.0537211546186485284],"hpluv":[28.7604537228304977,225.59011469442973,62.9183073649527955],"hsluv":[28.7604537228304977,94.206312745702121,62.9183073649527955]},"#ee7733":{"lch":[63.0213536795682501,108.794922632811733,27.2836719807386174],"luv":[63.0213536795682501,96.6912591797812411,49.8711899688373208],"rgb":[0.933333333333333348,0.466666666666666674,0.2],"xyz":[0.424531228442687092,0.316125426049823688,0.0699833084762596647],"hpluv":[27.2836719807386174,219.058559128587405,63.0213536795682501],"hsluv":[27.2836719807386174,88.1668112455654,63.0213536795682501]},"#ee7744":{"lch":[63.1696562136619235,104.634411539935968,25.0668522383795889],"luv":[63.1696562136619235,94.7793214210065571,44.3310309972846497],"rgb":[0.933333333333333348,0.466666666666666674,0.266666666666666663],"xyz":[0.428989223686906,0.317908624147511254,0.0934620834291463],"hpluv":[25.0668522383795889,210.186756956079222,63.1696562136619235],"hsluv":[25.0668522383795889,79.7210233436604199,63.1696562136619235]},"#ee7755":{"lch":[63.3671413614491286,99.5393983003294096,21.9455950678528],"luv":[63.3671413614491286,92.3266881357997278,37.2004633286522051],"rgb":[0.933333333333333348,0.466666666666666674,0.333333333333333315],"xyz":[0.434951637726268,0.320293589763256115,0.124864130703120219],"hpluv":[21.9455950678528,199.328877993420377,63.3671413614491286],"hsluv":[21.9455950678528,76.6090179557391,63.3671413614491286]},"#ee7766":{"lch":[63.6169573916324822,93.8195852400781263,17.7221756586824775],"luv":[63.6169573916324822,89.367258373090749,28.5588463614608763],"rgb":[0.933333333333333348,0.466666666666666674,0.4],"xyz":[0.442536633499776177,0.323327588072659433,0.16481177511026418],"hpluv":[17.7221756586824775,187.13711975631665,63.6169573916324822],"hsluv":[17.7221756586824775,76.9903860669667,63.6169573916324822]},"#ee7777":{"lch":[63.9215909451051232,87.936547917610838,12.1770506300618937],"luv":[63.9215909451051232,85.9580160709841863,18.5487447771187846],"rgb":[0.933333333333333348,0.466666666666666674,0.466666666666666674],"xyz":[0.451850646519978083,0.327053193280740229,0.21386557701666209],"hpluv":[12.1770506300618937,174.56660414904394,63.9215909451051232],"hsluv":[12.1770506300618937,77.4248320836617268,63.9215909451051232]},"#ee7788":{"lch":[64.2829374304473,82.5014209284754543,5.11726519711922112],"luv":[64.2829374304473,82.1725895095950847,7.35866757674724514],"rgb":[0.933333333333333348,0.466666666666666674,0.533333333333333326],"xyz":[0.462991063621921883,0.331509360121517827,0.272538440420234229],"hpluv":[5.11726519711922112,162.85647909200884,64.2829374304473],"hsluv":[5.11726519711922112,77.9003779592442669,64.2829374304473]},"#ee7799":{"lch":[64.7023501026032477,78.2413537817778177,356.48599323172067],"luv":[64.7023501026032477,78.0942478632934893,-4.79561177242263259],"rgb":[0.933333333333333348,0.466666666666666674,0.6],"xyz":[0.476048027730994638,0.336732145765147,0.341305118061352164],"hpluv":[356.48599323172067,153.446019679421255,64.7023501026032477],"hsluv":[356.48599323172067,78.4035888028378167,64.7023501026032477]},"#ee77aa":{"lch":[65.1806796634753596,75.8992199041959,346.522692233148291],"luv":[65.1806796634753596,73.8091300431969302,-17.6890899803221124],"rgb":[0.933333333333333348,0.466666666666666674,0.66666666666666663],"xyz":[0.491105720696247139,0.342755222951248106,0.420608967678350765],"hpluv":[346.522692233148291,147.76029654451807,65.1806796634753596],"hsluv":[346.522692233148291,78.9205551316135256,65.1806796634753596]},"#ee77bb":{"lch":[65.7183104585581646,76.0514193956389875,335.85959217762661],"luv":[65.7183104585581646,69.4004166910179094,-31.1030634376174824],"rgb":[0.933333333333333348,0.466666666666666674,0.733333333333333282],"xyz":[0.508243312803583813,0.349610259794182865,0.510866952776992456],"hpluv":[335.85959217762661,146.845370988132231,65.7183104585581646],"hsluv":[335.85959217762661,79.4377328719524627,65.7183104585581646]},"#ee77cc":{"lch":[66.3151963922866,78.9180750862202416,325.378996221060731],"luv":[66.3151963922866,64.9439055461397459,-44.8369457894756067],"rgb":[0.933333333333333348,0.466666666666666674,0.8],"xyz":[0.527535688247305568,0.357327209971671667,0.612473463447262612],"hpluv":[325.378996221060731,151.008971652655617,66.3151963922866],"hsluv":[325.378996221060731,79.9425706591808307,66.3151963922866]},"#ee77dd":{"lch":[66.9708980107196652,84.3115421117289543,315.859798591258766],"luv":[66.9708980107196652,60.5051526262217152,-58.7159487612646842],"rgb":[0.933333333333333348,0.466666666666666674,0.866666666666666696],"xyz":[0.549054013797939056,0.365934540191925173,0.725803311347268609],"hpluv":[315.859798591258766,159.749768323538632,66.9708980107196652],"hsluv":[315.859798591258766,80.4238985377879345,66.9708980107196652]},"#ee77ee":{"lch":[67.6846211881785251,91.7687338274624409,307.715012949244453],"luv":[67.6846211881785251,56.1380858067324056,-72.5948746830766112],"rgb":[0.933333333333333348,0.466666666666666674,0.933333333333333348],"xyz":[0.572866194064113765,0.37545941229839519,0.851214127415791832],"hpluv":[307.715012949244453,172.045795420537047,67.6846211881785251],"hsluv":[307.715012949244453,80.8720902094370757,67.6846211881785251]},"#ee77ff":{"lch":[68.4552572311626761,100.746525491660947,300.997699928034137],"luv":[68.4552572311626761,51.8848298156272918,-86.3587102361150585],"rgb":[0.933333333333333348,0.466666666666666674,1],"xyz":[0.599037242473945186,0.385927831662327914,0.989048315707573789],"hpluv":[300.997699928034137,186.750854251257437,68.4552572311626761],"hsluv":[300.997699928034137,99.9999999999982,68.4552572311626761]},"#ee8800":{"lch":[66.3576417146455,105.981377873447272,36.6492300119340797],"luv":[66.3576417146455,85.0293774107247771,63.2618165491550428],"rgb":[0.933333333333333348,0.533333333333333326,0],"xyz":[0.440628823797085678,0.35788025575153648,0.045873620032903642],"hpluv":[36.6492300119340797,202.664622836431278,66.3576417146455],"hsluv":[36.6492300119340797,100.000000000002288,66.3576417146455]},"#ee8811":{"lch":[66.3886714607036907,104.946342152180421,36.2201184819273792],"luv":[66.3886714607036907,84.6657638625926552,62.0116373004794923],"rgb":[0.933333333333333348,0.533333333333333326,0.0666666666666666657],"xyz":[0.441640489296722782,0.358284921951391333,0.0512017249976592717],"hpluv":[36.2201184819273792,200.591559481147556,66.3886714607036907],"hsluv":[36.2201184819273792,98.1954604930108701,66.3886714607036907]},"#ee8822":{"lch":[66.4461305943750773,103.062674429887437,35.4099902294173745],"luv":[66.4461305943750773,83.9988395226221201,59.7169140151578],"rgb":[0.933333333333333348,0.533333333333333326,0.133333333333333331],"xyz":[0.443515847435199839,0.359035065206782134,0.0610786111936384712],"hpluv":[35.4099902294173745,196.820821024497235,66.4461305943750773],"hsluv":[35.4099902294173745,94.8869488142181581,66.4461305943750773]},"#ee8833":{"lch":[66.5405621290638578,100.059958052790449,34.0337853874148877],"luv":[66.5405621290638578,82.920456825626232,56.0017235927220369],"rgb":[0.933333333333333348,0.533333333333333326,0.2],"xyz":[0.446603598167657545,0.36027016549976526,0.0773407650512496214],"hpluv":[34.0337853874148877,190.815292572549708,66.5405621290638578],"hsluv":[34.0337853874148877,89.5408718212573689,66.5405621290638578]},"#ee8844":{"lch":[66.6765193585480347,95.9403990837829639,31.9512880443390657],"luv":[66.6765193585480347,81.4052672986078107,50.7714745934935223],"rgb":[0.933333333333333348,0.533333333333333326,0.266666666666666663],"xyz":[0.45106159341187646,0.362053363597452826,0.10081954000413626],"hpluv":[31.9512880443390657,182.586190035925256,66.6765193585480347],"hsluv":[31.9512880443390657,82.0371002457568608,66.6765193585480347]},"#ee8855":{"lch":[66.8576614114874559,90.8274017958005,28.983496619036984],"luv":[66.8576614114874559,79.4521157428502391,44.0111147434430805],"rgb":[0.933333333333333348,0.533333333333333326,0.333333333333333315],"xyz":[0.457024007451238445,0.364438329213197687,0.132221587278110175],"hpluv":[28.983496619036984,172.387208051834335,66.8576614114874559],"hsluv":[28.983496619036984,74.7174368883009663,66.8576614114874559]},"#ee8866":{"lch":[67.0869600103699213,84.978663004295683,24.8971939400565283],"luv":[67.0869600103699213,77.081139807049837,35.7752854921339249],"rgb":[0.933333333333333348,0.533333333333333326,0.4],"xyz":[0.464609003224746631,0.367472327522601,0.172169231685254109],"hpluv":[24.8971939400565283,160.735241770302764,67.0869600103699213],"hsluv":[24.8971939400565283,75.0669061044520447,67.0869600103699213]},"#ee8877":{"lch":[67.3668077908477727,78.8051510957513841,19.4009345351312952],"luv":[67.3668077908477727,74.3303771171996743,26.1772205713113095],"rgb":[0.933333333333333348,0.533333333333333326,0.466666666666666674],"xyz":[0.473923016244948536,0.371197932730681801,0.221223033591652019],"hpluv":[19.4009345351312952,148.438980876884,67.3668077908477727],"hsluv":[19.4009345351312952,75.4672397967126329,67.3668077908477727]},"#ee8888":{"lch":[67.6990830402889117,72.8916076032019191,12.177050630062066],"luv":[67.6990830402889117,71.2515799877231757,15.3752661190709663],"rgb":[0.933333333333333348,0.533333333333333326,0.533333333333333326],"xyz":[0.485063433346892336,0.375654099571459399,0.279895896995224214],"hpluv":[12.177050630062066,136.626224949154164,67.6990830402889117],"hsluv":[12.177050630062066,75.9081099773692927,67.6990830402889117]},"#ee8899":{"lch":[68.0851935471165319,67.9986383575237312,2.99916583787236446],"luv":[68.0851935471165319,67.9055003914663615,3.55778513430191889],"rgb":[0.933333333333333348,0.533333333333333326,0.6],"xyz":[0.498120397455965036,0.380876885215088556,0.348662574636342093],"hpluv":[2.99916583787236446,126.732168582193651,68.0851935471165319],"hsluv":[2.99916583787236446,76.3775584855855385,68.0851935471165319]},"#ee88aa":{"lch":[68.5261104708773274,64.9933943358063573,351.976176804910949],"luv":[68.5261104708773274,64.3571165389368,-9.07209226602857832],"rgb":[0.933333333333333348,0.533333333333333326,0.66666666666666663],"xyz":[0.513178090421217648,0.386899962401189679,0.427966424253340694],"hpluv":[351.976176804910949,120.351764916629207,68.5261104708773274],"hsluv":[351.976176804910949,76.8628030471707859,68.5261104708773274]},"#ee88bb":{"lch":[69.0223979406526098,64.6433047463018,339.810246341231903],"luv":[69.0223979406526098,60.6712812589502875,-22.3103670727442456],"rgb":[0.933333333333333348,0.533333333333333326,0.733333333333333282],"xyz":[0.530315682528554211,0.393754999244124437,0.51822440935198244],"hpluv":[339.810246341231903,118.842788638920595,69.0223979406526098],"hsluv":[339.810246341231903,77.3509666785266887,69.0223979406526098]},"#ee88cc":{"lch":[69.5742414545850778,67.3203562589766307,327.709288072293873],"luv":[69.5742414545850778,56.9091584539883399,-35.9635656031820687],"rgb":[0.933333333333333348,0.533333333333333326,0.8],"xyz":[0.549608057972276,0.401471949421613239,0.619830920022252596],"hpluv":[327.709288072293873,122.782720563937247,69.5742414545850778],"hsluv":[327.709288072293873,77.8296635442389686,69.5742414545850778]},"#ee88dd":{"lch":[70.1814766713242,72.856404222049747,316.817937357318669],"luv":[70.1814766713242,53.1256441200966663,-49.8570112721525547],"rgb":[0.933333333333333348,0.533333333333333326,0.866666666666666696],"xyz":[0.571126383522909564,0.410079279641866745,0.733160767922258594],"hpluv":[316.817937357318669,131.729959343498166,70.1814766713242],"hsluv":[316.817937357318669,78.2874043120714163,70.1814766713242]},"#ee88ee":{"lch":[70.8436192863675558,80.7013698438951224,307.715012949244851],"luv":[70.8436192863675558,49.367799206375345,-63.839889537812887],"rgb":[0.933333333333333348,0.533333333333333326,0.933333333333333348],"xyz":[0.594938563789084274,0.419604151748336762,0.858571583990781817],"hpluv":[307.715012949244851,144.550464850223619,70.8436192863675558],"hsluv":[307.715012949244851,78.7138135635212848,70.8436192863675558]},"#ee88ff":{"lch":[71.5598961203093182,90.2054153167292583,300.42003582834775],"luv":[71.5598961203093182,45.674190228859068,-77.7874366424399426],"rgb":[0.933333333333333348,0.533333333333333326,1],"xyz":[0.621109612198915695,0.430072571112269486,0.996405772282563662],"hpluv":[300.42003582834775,159.956626210428567,71.5598961203093182],"hsluv":[300.42003582834775,99.99999999999784,71.5598961203093182]},"#ee9900":{"lch":[70.1492527845175715,98.9919938823364731,44.3502140795235036],"luv":[70.1492527845175715,70.7872313214223112,69.1995862317686772],"rgb":[0.933333333333333348,0.6,0],"xyz":[0.466498424249553179,0.409619456656472147,0.0544968201837259],"hpluv":[44.3502140795235036,179.06732625175573,70.1492527845175715],"hsluv":[44.3502140795235036,100.000000000002217,70.1492527845175715]},"#ee9911":{"lch":[70.1776126165771785,97.9766822185852533,43.9766782844564119],"luv":[70.1776126165771785,70.5062245085518526,68.0316291449155273],"rgb":[0.933333333333333348,0.6,0.0666666666666666657],"xyz":[0.467510089749190283,0.410024122856327,0.0598249251484815267],"hpluv":[43.9766782844564119,177.15910010767405,70.1776126165771785],"hsluv":[43.9766782844564119,98.4152296143538337,70.1776126165771785]},"#ee9922":{"lch":[70.2301348691785,96.1222676294158447,43.2696050504519505],"luv":[70.2301348691785,69.9901292501651824,65.8852953379296622],"rgb":[0.933333333333333348,0.6,0.133333333333333331],"xyz":[0.46938544788766734,0.410774266111717801,0.0697018113444607262],"hpluv":[43.2696050504519505,173.676009463775955,70.2301348691785],"hsluv":[43.2696050504519505,95.5057584668238,70.2301348691785]},"#ee9933":{"lch":[70.3164728806357573,93.1473438817036339,42.0626701373461103],"luv":[70.3164728806357573,69.1537511222041417,62.4034163964169508],"rgb":[0.933333333333333348,0.6,0.2],"xyz":[0.472473198620125046,0.412009366404700927,0.0859639652020718625],"hpluv":[42.0626701373461103,168.094198140054317,70.3164728806357573],"hsluv":[42.0626701373461103,90.7937976503380213,70.3164728806357573]},"#ee9944":{"lch":[70.4408210614760719,89.024296887742608,40.221678197216157],"luv":[70.4408210614760719,67.9746586813449483,57.4871395488729533],"rgb":[0.933333333333333348,0.6,0.266666666666666663],"xyz":[0.476931193864343961,0.413792564502388494,0.109442740154958501],"hpluv":[40.221678197216157,160.370125602871781,70.4408210614760719],"hsluv":[40.221678197216157,84.1577311163605657,70.4408210614760719]},"#ee9955":{"lch":[70.6065752665828654,83.8291063606938138,37.5652459120346904],"luv":[70.6065752665828654,66.4479455240540631,51.1076276974862154],"rgb":[0.933333333333333348,0.6,0.333333333333333315],"xyz":[0.482893607903705946,0.416177530118133354,0.140844787428932416],"hpluv":[37.5652459120346904,150.656896294971034,70.6065752665828654],"hsluv":[37.5652459120346904,75.5772228053980797,70.6065752665828654]},"#ee9966":{"lch":[70.8165243284349373,77.7550236522342,33.8383101580563],"luv":[70.8165243284349373,64.5842808158336652,43.297971946282189],"rgb":[0.933333333333333348,0.6,0.4],"xyz":[0.490478603677214131,0.419211528427536673,0.180792431836076378],"hpluv":[33.8383101580563,139.326323276972687,70.8165243284349373],"hsluv":[33.8383101580563,72.525293376848623,70.8165243284349373]},"#ee9977":{"lch":[71.0729506656700778,71.1378337295946,28.6840524218341386],"luv":[71.0729506656700778,62.4077841236731601,34.1446901949989154],"rgb":[0.933333333333333348,0.6,0.466666666666666674],"xyz":[0.499792616697416037,0.422937133635617468,0.229846233742474287],"hpluv":[28.6840524218341386,127.009327518651787,71.0729506656700778],"hsluv":[28.6840524218341386,72.8885787597460677,71.0729506656700778]},"#ee9988":{"lch":[71.3776900371935312,64.4963091800695878,21.6331741754282376],"luv":[71.3776900371935312,59.9533946760230378,23.7773918811996943],"rgb":[0.933333333333333348,0.6,0.533333333333333326],"xyz":[0.510933033799359837,0.427393300476395066,0.288519097146046455],"hpluv":[21.6331741754282376,114.659937381049531,71.3776900371935312],"hsluv":[21.6331741754282376,73.2902809537896189,71.3776900371935312]},"#ee9999":{"lch":[71.732171153908709,58.5818834203282179,12.1770506300621602],"luv":[71.732171153908709,57.263818011494017,12.3568690136061505],"rgb":[0.933333333333333348,0.6,0.6],"xyz":[0.523989997908432592,0.432616086120024224,0.35728577478716439],"hpluv":[12.1770506300621602,103.630759412975706,71.732171153908709],"hsluv":[12.1770506300621602,73.7196701825771186,71.732171153908709]},"#ee99aa":{"lch":[72.1374451439022408,54.3863410009709725,0.0659165211073427237],"luv":[72.1374451439022408,54.3863050092105,0.0625693137293968082],"rgb":[0.933333333333333348,0.6,0.66666666666666663],"xyz":[0.539047690873685093,0.438639163306125346,0.436589624404162935],"hpluv":[0.0659165211073427237,95.6683780017161,72.1374451439022408],"hsluv":[0.0659165211073427237,74.1649147609968082,72.1374451439022408]},"#ee99bb":{"lch":[72.5942101669252366,52.9692652640659247,345.882936464906891],"luv":[72.5942101669252366,51.3695627363271683,-12.9194073739288822],"rgb":[0.933333333333333348,0.6,0.733333333333333282],"xyz":[0.556185282981021767,0.445494200149060104,0.526847609502804737],"hpluv":[345.882936464906891,92.5894045166522091,72.5942101669252366],"hsluv":[345.882936464906891,74.6136876066909878,72.5942101669252366]},"#ee99cc":{"lch":[73.1028341171650737,55.013164482536844,331.314039518972208],"luv":[73.1028341171650737,48.2610582375421515,-26.4067893575727517],"rgb":[0.933333333333333348,0.6,0.8],"xyz":[0.575477658424743521,0.453211150326548906,0.628454120173074893],"hpluv":[331.314039518972208,95.4930444317639342,73.1028341171650737],"hsluv":[331.314039518972208,75.0536815693659491,73.1028341171650737]},"#ee99dd":{"lch":[73.6633770412179274,60.4388711558699896,318.269971219550712],"luv":[73.6633770412179274,45.1048908137830935,-40.2294167403973049],"rgb":[0.933333333333333348,0.6,0.866666666666666696],"xyz":[0.596995983975377,0.461818480546802412,0.74178396807308089],"hpluv":[318.269971219550712,104.112780668711437,73.6633770412179274],"hsluv":[318.269971219550712,75.472992612571872,73.6633770412179274]},"#ee99ee":{"lch":[74.2756141069900337,68.5596754700476083,307.71501294924542],"luv":[74.2756141069900337,41.9403078139404499,-54.2350410807456953],"rgb":[0.933333333333333348,0.6,0.933333333333333348],"xyz":[0.620808164241551719,0.471343352653272429,0.867194784141604114],"hpluv":[307.71501294924542,117.128296895720368,74.2756141069900337],"hsluv":[307.71501294924542,75.8603506282489235,74.2756141069900337]},"#ee99ff":{"lch":[74.9390594560707,78.5455210447045857,299.603294913962486],"luv":[74.9390594560707,38.8008486558083519,-68.2927010724659],"rgb":[0.933333333333333348,0.6,1],"xyz":[0.64697921265138314,0.481811772017205153,1.00502897243338585],"hpluv":[299.603294913962486,133.000267199001968,74.9390594560707],"hsluv":[299.603294913962486,99.9999999999973284,74.9390594560707]},"#dd0000":{"lch":[46.1435564305616239,155.182233977468201,12.1770506300617765],"luv":[46.1435564305616239,151.69070515099267,32.7330981276182555],"rgb":[0.866666666666666696,0,0],"xyz":[0.298181282529475455,0.153749723804264049,0.0139772476185688679],"hpluv":[12.1770506300617765,426.746789183125316,46.1435564305616239],"hsluv":[12.1770506300617765,100.000000000002217,46.1435564305616239]},"#dd0011":{"lch":[46.1980288678146636,153.577384001942391,11.5987087531524224],"luv":[46.1980288678146636,150.441300178721519,30.8776306962803169],"rgb":[0.866666666666666696,0,0.0666666666666666657],"xyz":[0.29919294802911256,0.154154390004118902,0.0193053525833244977],"hpluv":[11.5987087531524224,421.835520233675084,46.1980288678146636],"hsluv":[11.5987087531524224,99.9999999999964473,46.1980288678146636]},"#dd0022":{"lch":[46.2987546285526292,150.712226421231577,10.5179424282654246],"luv":[46.2987546285526292,148.17992816752087,27.5115263319381462],"rgb":[0.866666666666666696,0,0.133333333333333331],"xyz":[0.301068306167589617,0.15490453325950973,0.0291822387793036972],"hpluv":[10.5179424282654246,413.065099977246746,46.2987546285526292],"hsluv":[10.5179424282654246,99.9999999999964615,46.2987546285526292]},"#dd0033":{"lch":[46.4638920568500637,146.293058552209629,8.71533624525386585],"luv":[46.4638920568500637,144.603865814948932,22.1671146505918131],"rgb":[0.866666666666666696,0,0.2],"xyz":[0.304156056900047322,0.156139633552492829,0.0454443926369148404],"hpluv":[8.71533624525386585,399.528220173505417,46.4638920568500637],"hsluv":[8.71533624525386585,99.9999999999966,46.4638920568500637]},"#dd0044":{"lch":[46.7007828741672242,140.527307525302433,6.06736355557067153],"luv":[46.7007828741672242,139.740117429456177,14.853408400522655],"rgb":[0.866666666666666696,0,0.266666666666666663],"xyz":[0.308614052144266238,0.157922831650180423,0.0689231675898014789],"hpluv":[6.06736355557067153,381.835137536210595,46.7007828741672242],"hsluv":[6.06736355557067153,99.9999999999967315,46.7007828741672242]},"#dd0055":{"lch":[47.0148448700731194,133.854751810486647,2.4577968894866693],"luv":[47.0148448700731194,133.731616129679537,5.74015936982693],"rgb":[0.866666666666666696,0,0.333333333333333315],"xyz":[0.314576466183628223,0.160307797265925256,0.10032521486377538],"hpluv":[2.4577968894866693,361.275168455412427,47.0148448700731194],"hsluv":[2.4577968894866693,99.9999999999969873,47.0148448700731194]},"#dd0066":{"lch":[47.4099042919878073,126.898325188331157,357.792852491951692],"luv":[47.4099042919878073,126.80418183984473,-4.88716722969802841],"rgb":[0.866666666666666696,0,0.4],"xyz":[0.322161461957136408,0.163341795575328547,0.140272859270919342],"hpluv":[357.792852491951692,339.645713706877359,47.4099042919878073],"hsluv":[357.792852491951692,99.9999999999972857,47.4099042919878073]},"#dd0077":{"lch":[47.8883827301537,120.388643903007392,352.036106438093952],"luv":[47.8883827301537,119.227564738695264,-16.6797298325047478],"rgb":[0.866666666666666696,0,0.466666666666666674],"xyz":[0.331475474977338314,0.16706740078340937,0.189326661177317251],"hpluv":[352.036106438093952,319.002934776287759,47.8883827301537],"hsluv":[352.036106438093952,99.9999999999974136,47.8883827301537]},"#dd0088":{"lch":[48.4514347566520058,115.064311489444805,345.260130057314882],"luv":[48.4514347566520058,111.277652945923506,-29.2759241252361342],"rgb":[0.866666666666666696,0,0.533333333333333326],"xyz":[0.342615892079282114,0.171523567624186968,0.247999524580889419],"hpluv":[345.260130057314882,301.351479235409442,48.4514347566520058],"hsluv":[345.260130057314882,99.9999999999976836,48.4514347566520058]},"#dd0099":{"lch":[49.0990738312553816,111.554442433955828,337.69359677942],"luv":[49.0990738312553816,103.206522936464793,-42.3415546492536166],"rgb":[0.866666666666666696,0,0.6],"xyz":[0.355672856188354869,0.176746353267816125,0.316766202222007354],"hpluv":[337.69359677942,288.305479360883112,49.0990738312553816],"hsluv":[337.69359677942,99.9999999999979252,49.0990738312553816]},"#dd00aa":{"lch":[49.8303011832281442,110.265023964610052,329.72204926251294],"luv":[49.8303011832281442,95.2237329190616606,-55.5951094870335041],"rgb":[0.866666666666666696,0,0.66666666666666663],"xyz":[0.370730549153607369,0.18276943045391722,0.396070051839005954],"hpluv":[329.72204926251294,280.791263168904948,49.8303011832281442],"hsluv":[329.72204926251294,99.9999999999981526,49.8303011832281442]},"#dd00bb":{"lch":[50.6432416523731064,111.311454300018838,321.811503537589374],"luv":[50.6432416523731064,87.4886923962170613,-68.8183737179635244],"rgb":[0.866666666666666696,0,0.733333333333333282],"xyz":[0.387868141260944044,0.189624467296851978,0.486328036937647701],"hpluv":[321.811503537589374,278.905890401213071,50.6432416523731064],"hsluv":[321.811503537589374,99.9999999999984,50.6432416523731064]},"#dd00cc":{"lch":[51.5352850119508901,114.534817141075266,314.3830496716472],"luv":[51.5352850119508901,80.1116001600253753,-81.8557014345352201],"rgb":[0.866666666666666696,0,0.8],"xyz":[0.407160516704665798,0.19734141747434078,0.587934547607917857],"hpluv":[314.3830496716472,282.014975724645751,51.5352850119508901],"hsluv":[314.3830496716472,99.9999999999986215,51.5352850119508901]},"#dd00dd":{"lch":[52.5032286812834883,119.593841400887641,307.715012949243601],"luv":[52.5032286812834883,73.1596596193909647,-94.6062952735996419],"rgb":[0.866666666666666696,0,0.866666666666666696],"xyz":[0.428678842255299286,0.205948747694594314,0.701264395507923854],"hpluv":[307.715012949243601,289.042783730483222,52.5032286812834883],"hsluv":[307.715012949243601,99.9999999999987779,52.5032286812834883]},"#dd00ee":{"lch":[53.5434168792756111,126.080010820296707,301.921476351261958],"luv":[53.5434168792756111,66.6656277920787659,-107.01337860068783],"rgb":[0.866666666666666696,0,0.933333333333333348],"xyz":[0.452491022521474051,0.215473619801064359,0.826675211576447078],"hpluv":[301.921476351261958,298.799235277631283,53.5434168792756111],"hsluv":[301.921476351261958,99.999999999998991,53.5434168792756111]},"#dd00ff":{"lch":[54.6518715304170399,133.605457484958208,296.990855958497434],"luv":[54.6518715304170399,60.6366090811706258,-119.053013019000375],"rgb":[0.866666666666666696,0,1],"xyz":[0.478662070931305417,0.225942039164997055,0.964509399868228923],"hpluv":[296.990855958497434,310.211923209940835,54.6518715304170399],"hsluv":[296.990855958497434,99.99999999999919,54.6518715304170399]},"#dd1100":{"lch":[46.6790301132195,152.538998994032681,12.7564763340959253],"luv":[46.6790301132195,148.773935032481603,33.6817824506429915],"rgb":[0.866666666666666696,0.0666666666666666657,0],"xyz":[0.300185682790403863,0.157758524326120919,0.0146453810388783197],"hpluv":[12.7564763340959253,414.665968881342394,46.6790301132195],"hsluv":[12.7564763340959253,100.000000000002373,46.6790301132195]},"#dd1111":{"lch":[46.7325769897078942,150.969760125239,12.1770506300617818],"luv":[46.7325769897078942,147.573010021229663,31.8445471870185592],"rgb":[0.866666666666666696,0.0666666666666666657,0.0666666666666666657],"xyz":[0.301197348290040967,0.158163190525975772,0.0199734860036339529],"hpluv":[12.1770506300617818,409.92986676092562,46.7325769897078942],"hsluv":[12.1770506300617818,96.0592738250283,46.7325769897078942]},"#dd1122":{"lch":[46.8315975390355774,148.166934443607602,11.093898425687982],"luv":[46.8315975390355774,145.398162733087418,28.509905932130728],"rgb":[0.866666666666666696,0.0666666666666666657,0.133333333333333331],"xyz":[0.303072706428518,0.1589133337813666,0.0298503721996131455],"hpluv":[11.093898425687982,401.468660625611221,46.8315975390355774],"hsluv":[11.093898425687982,96.1199649520447821,46.8315975390355774]},"#dd1133":{"lch":[46.9939567691892393,143.840838530693645,9.28627571582045697],"luv":[46.9939567691892393,141.955717705878527,23.2112265902085468],"rgb":[0.866666666666666696,0.0666666666666666657,0.2],"xyz":[0.30616045716097573,0.160148434074349699,0.0461125260572242957],"hpluv":[9.28627571582045697,388.400266865181436,46.9939567691892393],"hsluv":[9.28627571582045697,96.2159198798013477,46.9939567691892393]},"#dd1144":{"lch":[47.2268997120704555,138.191174032002039,6.62861883301083665],"luv":[47.2268997120704555,137.267398010546174,15.951865839373701],"rgb":[0.866666666666666696,0.0666666666666666657,0.266666666666666663],"xyz":[0.310618452405194645,0.161931632172037293,0.0695913010101109342],"hpluv":[6.62861883301083665,371.304486157060069,47.2268997120704555],"hsluv":[6.62861883301083665,96.346372634165391,47.2268997120704555]},"#dd1155":{"lch":[47.5357948285950442,131.646215003298352,3.00154982487266553],"luv":[47.5357948285950442,131.465612026054913,6.89338663571585908],"rgb":[0.866666666666666696,0.0666666666666666657,0.333333333333333315],"xyz":[0.31658086644455663,0.164316597787782126,0.100993348284084836],"hpluv":[3.00154982487266553,351.420379681935685,47.5357948285950442],"hsluv":[3.00154982487266553,96.5074087268808114,47.5357948285950442]},"#dd1166":{"lch":[47.9244613368761776,124.817323026056556,358.307054390798669],"luv":[47.9244613368761776,124.762840903711279,-3.68750010524401839],"rgb":[0.866666666666666696,0.0666666666666666657,0.4],"xyz":[0.324165862218064815,0.167350596097185417,0.140940992691228811],"hpluv":[358.307054390798669,330.488955339688346,47.9244613368761776],"hsluv":[358.307054390798669,96.6928417837132912,47.9244613368761776]},"#dd1177":{"lch":[48.3953520744879313,118.427317384197096,352.504166614065639],"luv":[48.3953520744879313,117.415279069986227,-15.4493282615978131],"rgb":[0.866666666666666696,0.0666666666666666657,0.466666666666666674],"xyz":[0.333479875238266721,0.17107620130526624,0.189994794597626721],"hpluv":[352.504166614065639,310.51856077863863,48.3953520744879313],"hsluv":[352.504166614065639,96.8952584834877229,48.3953520744879313]},"#dd1188":{"lch":[48.949686611979061,113.213254375126112,345.662599129740954],"luv":[48.949686611979061,109.687147393784173,-28.0351683216148473],"rgb":[0.866666666666666696,0.0666666666666666657,0.533333333333333326],"xyz":[0.344620292340210521,0.175532368146043838,0.248667658001198888],"hpluv":[345.662599129740954,293.48552443008623,48.949686611979061],"hsluv":[345.662599129740954,97.1070447043031209,48.949686611979061]},"#dd1199":{"lch":[49.5875717372425,109.808639676001164,338.012756373247385],"luv":[49.5875717372425,101.821953610845213,-41.1123717433662961],"rgb":[0.866666666666666696,0.0666666666666666657,0.6],"xyz":[0.357677256449283276,0.180755153789673,0.317434335642316767],"hpluv":[338.012756373247385,280.997849503034615,49.5875717372425],"hsluv":[338.012756373247385,97.321211179253126,49.5875717372425]},"#dd11aa":{"lch":[50.3081241313593779,108.626384639058173,329.948207544292131],"luv":[50.3081241313593779,94.0240738412992556,-54.3982074892042462],"rgb":[0.866666666666666696,0.0666666666666666657,0.66666666666666663],"xyz":[0.372734949414535777,0.18677823097577409,0.396738185259315368],"hpluv":[329.948207544292131,273.991145484396441,50.3081241313593779],"hsluv":[329.948207544292131,97.5319211216277751,50.3081241313593779]},"#dd11bb":{"lch":[51.1095995740137,109.78676639377484,321.947120969557943],"luv":[51.1095995740137,86.4507346157054855,-67.6712979010019495],"rgb":[0.866666666666666696,0.0666666666666666657,0.733333333333333282],"xyz":[0.389872541521872451,0.193633267818708849,0.486996170357957114],"hpluv":[321.947120969557943,272.57551535007633,51.1095995740137],"hsluv":[321.947120969557943,97.7347175386083791,51.1095995740137]},"#dd11cc":{"lch":[51.9895276454598303,113.13117809908816,314.441471026924035],"luv":[51.9895276454598303,79.2122218564644527,-80.7718228508547469],"rgb":[0.866666666666666696,0.0666666666666666657,0.8],"xyz":[0.409164916965594205,0.20135021799619765,0.588602681028227326],"hpluv":[314.441471026924035,276.12502270002949,51.9895276454598303],"hsluv":[314.441471026924035,97.9265130550616,51.9895276454598303]},"#dd11dd":{"lch":[52.9448482611329325,118.314931067086022,307.715012949243601],"luv":[52.9448482611329325,72.3773062506166553,-93.594596282658145],"rgb":[0.866666666666666696,0.0666666666666666657,0.866666666666666696],"xyz":[0.430683242516227693,0.209957548216451184,0.701932528928233324],"hpluv":[307.715012949243601,283.566663729067216,52.9448482611329325],"hsluv":[307.715012949243601,98.1054292618058525,52.9448482611329325]},"#dd11ee":{"lch":[53.9720454332022257,124.924845967379298,301.881652150577509],"luv":[53.9720454332022257,65.9811112999591103,-106.078791902980541],"rgb":[0.866666666666666696,0.0666666666666666657,0.933333333333333348],"xyz":[0.454495422782402458,0.219482420322921229,0.827343344996756547],"hpluv":[301.881652150577509,293.71036424495378,53.9720454332022257],"hsluv":[301.881652150577509,98.2705657762439841,53.9720454332022257]},"#dd11ff":{"lch":[55.067273793018515,132.56906123155207,296.926443611211937],"luv":[55.067273793018515,60.0334023394080774,-118.197066796810802],"rgb":[0.866666666666666696,0.0666666666666666657,1],"xyz":[0.480666471192233824,0.229950839686853925,0.965177533288538392],"hpluv":[296.926443611211937,305.483621811531123,55.067273793018515],"hsluv":[296.926443611211937,99.9999999999990763,55.067273793018515]},"#dd2200":{"lch":[47.6481385708110494,147.881667770992,13.8451074484812633],"luv":[47.6481385708110494,143.585141583480663,35.3877772568702937],"rgb":[0.866666666666666696,0.133333333333333331,0],"xyz":[0.303901306525171777,0.165189771795656887,0.0158839222838009289],"hpluv":[13.8451074484812633,393.829031299888356,47.6481385708110494],"hsluv":[13.8451074484812633,100.000000000002302,47.6481385708110494]},"#dd2211":{"lch":[47.7000692420668,146.371743885583,13.2640103652051735],"luv":[47.7000692420668,142.467011758872331,33.583298953557744],"rgb":[0.866666666666666696,0.133333333333333331,0.0666666666666666657],"xyz":[0.304912972024808882,0.16559443799551174,0.0212120272485565586],"hpluv":[13.2640103652051735,389.383517616197651,47.7000692420668],"hsluv":[13.2640103652051735,96.2235359913314596,47.7000692420668]},"#dd2222":{"lch":[47.796111526211412,143.672697420673273,12.1770506300617871],"luv":[47.796111526211412,140.440127868319678,30.3053537920670948],"rgb":[0.866666666666666696,0.133333333333333331,0.133333333333333331],"xyz":[0.306788330163285938,0.166344581250902568,0.0310889134445357582],"hpluv":[12.1770506300617871,381.435408792809369,47.796111526211412],"hsluv":[12.1770506300617871,89.3821391188339618,47.796111526211412]},"#dd2233":{"lch":[47.9536166692339805,139.501418135148583,10.3611027729364178],"luv":[47.9536166692339805,137.226679529052944,25.0895214611231978],"rgb":[0.866666666666666696,0.133333333333333331,0.2],"xyz":[0.309876080895743644,0.167579681543885667,0.0473510673021469],"hpluv":[10.3611027729364178,369.144652707036585,47.9536166692339805],"hsluv":[10.3611027729364178,89.634195646670733,47.9536166692339805]},"#dd2244":{"lch":[48.1796580724099073,134.044487106872765,7.68678657448498281],"luv":[48.1796580724099073,132.839973125453383,17.9294747210675],"rgb":[0.866666666666666696,0.133333333333333331,0.266666666666666663],"xyz":[0.314334076139962559,0.169362879641573261,0.0708298422550335399],"hpluv":[7.68678657448498281,353.040533161258963,48.1796580724099073],"hsluv":[7.68678657448498281,89.9776949827144819,48.1796580724099073]},"#dd2255":{"lch":[48.4795139291676236,127.710640494506933,4.02871777991100277],"luv":[48.4795139291676236,127.395062601571667,8.9724979943620351],"rgb":[0.866666666666666696,0.133333333333333331,0.333333333333333315],"xyz":[0.320296490179324544,0.171747845257318094,0.102231889529007441],"hpluv":[4.02871777991100277,334.278275235680212,48.4795139291676236],"hsluv":[4.02871777991100277,90.4030378986951746,48.4795139291676236]},"#dd2266":{"lch":[48.8569858046774499,121.091623353111601,359.280669781128381],"luv":[48.8569858046774499,121.082080247128843,-1.52022673298942879],"rgb":[0.866666666666666696,0.133333333333333331,0.4],"xyz":[0.32788148595283273,0.174781843566721384,0.142179533936151403],"hpluv":[359.280669781128381,314.504423311283745,48.8569858046774499],"hsluv":[359.280669781128381,90.8946273178398627,48.8569858046774499]},"#dd2277":{"lch":[49.3145747506863046,114.897314975199777,353.392641366134796],"luv":[49.3145747506863046,114.134166521370943,-13.2206286152450421],"rgb":[0.866666666666666696,0.133333333333333331,0.466666666666666674],"xyz":[0.337195498973034635,0.178507448774802208,0.191233335842549312],"hpluv":[353.392641366134796,295.64729776044,49.3145747506863046],"hsluv":[353.392641366134796,91.4334620569677128,49.3145747506863046]},"#dd2288":{"lch":[49.8536069462695934,109.863045744465836,346.42832123602642],"luv":[49.8536069462695934,106.795352255968297,-25.780643063628979],"rgb":[0.866666666666666696,0.133333333333333331,0.533333333333333326],"xyz":[0.348335916074978436,0.182963615615579805,0.24990619924612148],"hpluv":[346.42832123602642,279.636833718457694,49.8536069462695934],"hsluv":[346.42832123602642,91.999736258284841,49.8536069462695934]},"#dd2299":{"lch":[50.4743452384724947,106.631383564155598,338.620922954440232],"luv":[50.4743452384724947,99.2939711585852507,-38.8710593162073792],"rgb":[0.866666666666666696,0.133333333333333331,0.6],"xyz":[0.361392880184051135,0.188186401259208963,0.318672876887239387],"hpluv":[338.620922954440232,268.07337181170567,50.4743452384724947],"hsluv":[338.620922954440232,92.5749897333771088,50.4743452384724947]},"#dd22aa":{"lch":[51.176101525576982,105.62881092572934,330.379319008457628],"luv":[51.176101525576982,91.8248770713425699,-52.2076397514415902],"rgb":[0.866666666666666696,0.133333333333333331,0.66666666666666663],"xyz":[0.376450573149303691,0.194209478445310058,0.397976726504238],"hpluv":[330.379319008457628,261.911470041672374,51.176101525576982],"hsluv":[330.379319008457628,93.1435427232804898,51.176101525576982]},"#dd22bb":{"lch":[51.9573548685870321,106.984993341056935,322.205396597718504],"luv":[51.9573548685870321,84.5409044706425306,-65.5638945721781425],"rgb":[0.866666666666666696,0.133333333333333331,0.733333333333333282],"xyz":[0.393588165256640365,0.201064515288244816,0.488234711602879734],"hpluv":[322.205396597718504,261.285408571692301,51.9573548685870321],"hsluv":[322.205396597718504,93.6931794305449301,51.9573548685870321]},"#dd22cc":{"lch":[52.8158750154556174,110.541708291411879,314.55250800555325],"luv":[52.8158750154556174,77.5519304210182838,-78.7728846745956],"rgb":[0.866666666666666696,0.133333333333333331,0.8],"xyz":[0.412880540700362064,0.208781465465733618,0.58984122227315],"hpluv":[314.55250800555325,265.583456637160452,52.8158750154556174],"hsluv":[314.55250800555325,94.2152138812719073,52.8158750154556174]},"#dd22dd":{"lch":[53.7488483860564088,115.947384169062644,307.715012949243658],"luv":[53.7488483860564088,70.9289965118926204,-91.721716891171],"rgb":[0.866666666666666696,0.133333333333333331,0.866666666666666696],"xyz":[0.434398866250995663,0.217388795685987152,0.703171070173155943],"hpluv":[307.715012949243658,273.735496610715643,53.7488483860564088],"hsluv":[307.715012949243658,94.704144859729837,53.7488483860564088]},"#dd22ee":{"lch":[54.7530025006588374,122.779599443276055,301.806367069585178],"luv":[54.7530025006588374,64.7110170709106,-104.342293961267828],"rgb":[0.866666666666666696,0.133333333333333331,0.933333333333333348],"xyz":[0.458211046517170373,0.226913667792457197,0.828581886241679166],"hpluv":[301.806367069585178,284.549350776984397,54.7530025006588374],"hsluv":[301.806367069585178,95.1571011878196629,54.7530025006588374]},"#dd22ff":{"lch":[55.8247247862810525,130.638613434108407,296.804995701950531],"luv":[55.8247247862810525,58.9121835814083425,-116.601037498200881],"rgb":[0.866666666666666696,0.133333333333333331,1],"xyz":[0.484382094927001794,0.237382087156389893,0.966416074533461],"hpluv":[296.804995701950531,296.950662194199822,55.8247247862810525],"hsluv":[296.804995701950531,99.9999999999989768,55.8247247862810525]},"#dd3300":{"lch":[49.1823134049741526,140.84390252957769,15.6779143459349193],"luv":[49.1823134049741526,135.603943521894649,38.06015476941716],"rgb":[0.866666666666666696,0.2,0],"xyz":[0.310019028614182623,0.17742521597367869,0.0179231629801378106],"hpluv":[15.6779143459349193,363.386194305474646,49.1823134049741526],"hsluv":[15.6779143459349193,100.000000000002331,49.1823134049741526]},"#dd3311":{"lch":[49.2318310772226226,139.415415721210906,15.0950854994101622],"luv":[49.2318310772226226,134.60488288385605,36.3067988748864323],"rgb":[0.866666666666666696,0.2,0.0666666666666666657],"xyz":[0.311030694113819728,0.177829882173533543,0.0232512679448934403],"hpluv":[15.0950854994101622,359.338818773581409,49.2318310772226226],"hsluv":[15.0950854994101622,96.4660724045404834,49.2318310772226226]},"#dd3322":{"lch":[49.3234253076193,136.858666305461554,14.0037238091571297],"luv":[49.3234253076193,132.791226888227897,33.117738516222083],"rgb":[0.866666666666666696,0.2,0.133333333333333331],"xyz":[0.312906052252296785,0.178580025428924372,0.0331281541408726399],"hpluv":[14.0037238091571297,352.093818956611813,49.3234253076193],"hsluv":[14.0037238091571297,90.0546185843159321,49.3234253076193]},"#dd3333":{"lch":[49.4736766963079901,132.899088309008249,12.1770506300618315],"luv":[49.4736766963079901,129.908920002044738,28.0328410488111714],"rgb":[0.866666666666666696,0.2,0.2],"xyz":[0.31599380298475449,0.179815125721907471,0.0493903079984837831],"hpluv":[12.1770506300618315,340.868713502871344,49.4736766963079901],"hsluv":[12.1770506300618315,79.876105021286179,49.4736766963079901]},"#dd3344":{"lch":[49.6893958667399289,127.704341644457742,9.47932118493828391],"luv":[49.6893958667399289,125.960552293014786,21.031836364974712],"rgb":[0.866666666666666696,0.2,0.266666666666666663],"xyz":[0.320451798228973406,0.181598323819595064,0.0728690829513704286],"hpluv":[9.47932118493828391,326.122882655454703,49.6893958667399289],"hsluv":[9.47932118493828391,80.502956859434363,49.6893958667399289]},"#dd3355":{"lch":[49.9757165444531495,121.655077778432485,5.77481987360355742],"luv":[49.9757165444531495,121.037681249067731,12.2408197080725127],"rgb":[0.866666666666666696,0.2,0.333333333333333315],"xyz":[0.326414212268335391,0.183983289435339897,0.10427113022534433],"hpluv":[5.77481987360355742,308.89475746512926,49.9757165444531495],"hsluv":[5.77481987360355742,81.2827465905028674,49.9757165444531495]},"#dd3366":{"lch":[50.3364012453720164,115.314978813651479,0.942739432835561],"luv":[50.3364012453720164,115.29936949267524,1.8972963354308543],"rgb":[0.866666666666666696,0.2,0.4],"xyz":[0.333999208041843576,0.187017287744743188,0.144218774632488278],"hpluv":[0.942739432835561,290.698564526315124,50.3364012453720164],"hsluv":[0.942739432835561,82.1889615211792375,50.3364012453720164]},"#dd3377":{"lch":[50.77400791740952,109.376176789803836,354.916348657894],"luv":[50.77400791740952,108.945933542464203,-9.69183231981436],"rgb":[0.866666666666666696,0.2,0.466666666666666674],"xyz":[0.343313221062045482,0.190742892952824,0.193272576538886187],"hpluv":[354.916348657894,273.35096965093777,50.77400791740952],"hsluv":[354.916348657894,83.1884512053650269,50.77400791740952]},"#dd3388":{"lch":[51.2900053848270545,104.574014460431073,347.747121452304157],"luv":[51.2900053848270545,102.191864987712989,-22.1934051173651383],"rgb":[0.866666666666666696,0.2,0.533333333333333326],"xyz":[0.354453638163989282,0.195199059793601609,0.251945439942458382],"hpluv":[347.747121452304157,258.720214242298141,51.2900053848270545],"hsluv":[347.747121452304157,84.245872474104587,51.2900053848270545]},"#dd3399":{"lch":[51.8848727297214509,101.568582070491487,339.671486537323062],"luv":[51.8848727297214509,95.2425012264059347,-35.2851643605103433],"rgb":[0.866666666666666696,0.2,0.6],"xyz":[0.367510602273062,0.200421845437230767,0.320712117583576262],"hpluv":[339.671486537323062,248.403642764366595,51.8848727297214509],"hsluv":[339.671486537323062,85.3275173092541763,51.8848727297214509]},"#dd33aa":{"lch":[52.5581975758694284,100.811065681036794,331.124654782349864],"luv":[52.5581975758694284,88.2774684157494,-48.6822301651504219],"rgb":[0.866666666666666696,0.2,0.66666666666666663],"xyz":[0.382568295238314537,0.206444922623331861,0.400015967200574862],"hpluv":[331.124654782349864,243.392431352391867,52.5581975758694284],"hsluv":[331.124654782349864,86.4040244757801,52.5581975758694284]},"#dd33bb":{"lch":[53.3087788146031301,102.447919096954379,322.651217662355],"luv":[53.3087788146031301,81.4417156804123579,-62.1516136100020091],"rgb":[0.866666666666666696,0.2,0.733333333333333282],"xyz":[0.399705887345651212,0.21329995946626662,0.490273952299216609],"hpluv":[322.651217662355,243.861776984359892,53.3087788146031301],"hsluv":[322.651217662355,87.4518397844355633,53.3087788146031301]},"#dd33cc":{"lch":[54.1347343907921612,106.321268361530926,314.743497623169446],"luv":[54.1347343907921612,74.8431687457043751,-75.5163041872859253],"rgb":[0.866666666666666696,0.2,0.8],"xyz":[0.418998262789372911,0.221016909643755421,0.59188046296948682],"hpluv":[314.743497623169446,249.220329072313831,54.1347343907921612],"hsluv":[314.743497623169446,88.4535853271675734,54.1347343907921612]},"#dd33dd":{"lch":[55.033612168624586,112.066789743934578,307.715012949243715],"luv":[55.033612168624586,68.5551036430149,-88.6519211749340741],"rgb":[0.866666666666666696,0.2,0.866666666666666696],"xyz":[0.44051658834000651,0.229624239864008955,0.705210310869492818],"hpluv":[307.715012949243715,258.397459164480438,55.033612168624586],"hsluv":[307.715012949243715,89.3976510430439077,55.033612168624586]},"#dd33ee":{"lch":[56.0025007026426351,119.245240694744666,301.678101579798295],"luv":[56.0025007026426351,62.6212128139869506,-101.479116738632214],"rgb":[0.866666666666666696,0.2,0.933333333333333348],"xyz":[0.464328768606181219,0.239149111970479,0.830621126938016],"hpluv":[301.678101579798295,270.192295422478139,56.0025007026426351],"hsluv":[301.678101579798295,90.277343199481848,56.0025007026426351]},"#dd33ff":{"lch":[57.0381364623091116,127.442655532056975,296.59904001960814],"luv":[57.0381364623091116,57.0616979163907772,-113.954346472440875],"rgb":[0.866666666666666696,0.2,1],"xyz":[0.49049981701601264,0.249617531334411696,0.968455315229797886],"hpluv":[296.59904001960814,283.523336448078851,57.0381364623091116],"hsluv":[296.59904001960814,99.9999999999989626,57.0381364623091116]},"#dd4400":{"lch":[51.2775121999195278,131.902040393952689,18.409420821930695],"luv":[51.2775121999195278,125.151834557466444,41.6553305951168156],"rgb":[0.866666666666666696,0.266666666666666663,0],"xyz":[0.318851599097148664,0.19509035693961102,0.0208673531411264039],"hpluv":[18.409420821930695,326.410329295551833,51.2775121999195278],"hsluv":[18.409420821930695,100.000000000002245,51.2775121999195278]},"#dd4411":{"lch":[51.3239968707682124,130.563017922041524,17.8265447991253865],"luv":[51.3239968707682124,124.294382399750674,39.9700907276414128],"rgb":[0.866666666666666696,0.266666666666666663,0.0666666666666666657],"xyz":[0.319863264596785768,0.195495023139465873,0.0261954581058820371],"hpluv":[17.8265447991253865,322.804096021626094,51.3239968707682124],"hsluv":[17.8265447991253865,96.7659447415066154,51.3239968707682124]},"#dd4422":{"lch":[51.4099976690743148,128.162025810787327,16.7333496749677373],"luv":[51.4099976690743148,122.735013936090269,36.9001519513490237],"rgb":[0.866666666666666696,0.266666666666666663,0.133333333333333331],"xyz":[0.321738622735262825,0.196245166394856702,0.0360723443018612297],"hpluv":[16.7333496749677373,316.337811591652041,51.4099976690743148],"hsluv":[16.7333496749677373,90.8878404873512551,51.4099976690743148]},"#dd4433":{"lch":[51.551120550377874,124.432504768689228,14.8985084842763058],"luv":[51.551120550377874,120.249428964759446,31.9925472049216744],"rgb":[0.866666666666666696,0.266666666666666663,0.2],"xyz":[0.324826373467720531,0.197480266687839801,0.0523344981594723729],"hpluv":[14.8985084842763058,306.291581325991444,51.551120550377874],"hsluv":[14.8985084842763058,81.5276169642245634,51.551120550377874]},"#dd4444":{"lch":[51.7538349343952575,119.518854000271219,12.1770506300618191],"luv":[51.7538349343952575,116.829734805674121,25.2105042943215345],"rgb":[0.866666666666666696,0.266666666666666663,0.266666666666666663],"xyz":[0.329284368711939446,0.199263464785527394,0.0758132731123590115],"hpluv":[12.1770506300618191,293.044254198223086,51.7538349343952575],"hsluv":[12.1770506300618191,68.6693518559736,51.7538349343952575]},"#dd4455":{"lch":[52.0230766847265045,113.767549619287195,8.41751308754220773],"luv":[52.0230766847265045,112.542004033713866,16.6539086839248256],"rgb":[0.866666666666666696,0.266666666666666663,0.333333333333333315],"xyz":[0.335246782751301431,0.201648430401272227,0.107215320386332927],"hpluv":[8.41751308754220773,277.499175779034886,52.0230766847265045],"hsluv":[8.41751308754220773,69.8262296658756867,52.0230766847265045]},"#dd4466":{"lch":[52.3625377834239316,107.708396397149357,3.47572472865958737],"luv":[52.3625377834239316,107.51027478189765,6.52989056311981209],"rgb":[0.866666666666666696,0.266666666666666663,0.4],"xyz":[0.342831778524809616,0.204682428710675518,0.147162964793476875],"hpluv":[3.47572472865958737,261.016642983210886,52.3625377834239316],"hsluv":[3.47572472865958737,71.1800009153795088,52.3625377834239316]},"#dd4477":{"lch":[52.7748219535637304,102.013560717275851,357.256373562230806],"luv":[52.7748219535637304,101.896624345108023,-4.88308481282748108],"rgb":[0.866666666666666696,0.266666666666666663,0.466666666666666674],"xyz":[0.352145791545011522,0.208408033918756341,0.196216766699874784],"hpluv":[357.256373562230806,245.284698321799027,52.7748219535637304],"hsluv":[357.256373562230806,72.6848757644217898,52.7748219535637304]},"#dd4488":{"lch":[53.2615487789460502,97.4233940898595137,349.787328406912707],"luv":[53.2615487789460502,95.8798587184095368,-17.273401753155067],"rgb":[0.866666666666666696,0.266666666666666663,0.533333333333333326],"xyz":[0.363286208646955322,0.212864200759533939,0.254889630103446951],"hpluv":[349.787328406912707,232.107295472344475,53.2615487789460502],"hsluv":[349.787328406912707,74.290572198007979,53.2615487789460502]},"#dd4499":{"lch":[53.8234397136373133,94.6288173232078123,341.30539151945959],"luv":[53.8234397136373133,89.63624285692255,-30.330793502376995],"rgb":[0.866666666666666696,0.266666666666666663,0.6],"xyz":[0.376343172756028,0.218086986403163097,0.323656307744564886],"hpluv":[341.30539151945959,223.095746339835301,53.8234397136373133],"hsluv":[341.30539151945959,75.9477058190526577,53.8234397136373133]},"#dd44aa":{"lch":[54.4604007326765327,94.1226543521493539,332.285935566136516],"luv":[54.4604007326765327,83.3248558176969425,-43.7726223255380802],"rgb":[0.866666666666666696,0.266666666666666663,0.66666666666666663],"xyz":[0.391400865721280578,0.224110063589264191,0.402960157361563487],"hpluv":[332.285935566136516,219.307083848265933,54.4604007326765327],"hsluv":[332.285935566136516,77.6118806813578175,54.4604007326765327]},"#dd44bb":{"lch":[55.1716077278512387,96.0796222427451596,323.344264550451],"luv":[55.1716077278512387,77.0786382371216,-57.3600674495728526],"rgb":[0.866666666666666696,0.266666666666666663,0.733333333333333282],"xyz":[0.408538457828617252,0.23096510043219895,0.493218142460205233],"hpluv":[323.344264550451,220.981019921853772,55.1716077278512387],"hsluv":[323.344264550451,79.2461809113807334,55.1716077278512387]},"#dd44cc":{"lch":[55.9555962107488511,100.342448880687911,315.038748994660807],"luv":[55.9555962107488511,71.0007950362134,-70.9048246002984],"rgb":[0.866666666666666696,0.266666666666666663,0.8],"xyz":[0.427830833272338951,0.238682050609687751,0.594824653130475389],"hpluv":[315.038748994660807,227.551915064947707,55.9555962107488511],"hsluv":[315.038748994660807,80.8221578956601547,55.9555962107488511]},"#dd44dd":{"lch":[56.8103543983327484,106.525561993860563,307.715012949243828],"luv":[56.8103543983327484,65.1653443433699664,-84.2684594300729515],"rgb":[0.866666666666666696,0.266666666666666663,0.866666666666666696],"xyz":[0.44934915882297255,0.247289380829941285,0.708154501030481387],"hpluv":[307.715012949243828,237.939016458104504,56.8103543983327484],"hsluv":[307.715012949243828,82.3196529548951474,56.8103543983327484]},"#dd44ee":{"lch":[57.7334174818232384,114.162073161526394,301.482814132357476],"luv":[57.7334174818232384,59.6203198077272134,-97.3570563162323452],"rgb":[0.866666666666666696,0.266666666666666663,0.933333333333333348],"xyz":[0.473161339089147259,0.256814252936411302,0.83356531709900461],"hpluv":[301.482814132357476,250.91920763959763,57.7334174818232384],"hsluv":[301.482814132357476,85.8927976857303577,57.7334174818232384]},"#dd44ff":{"lch":[58.721960397178492,122.814959128704743,296.287773174859751],"luv":[58.721960397178492,54.3922733794591196,-110.113554035820684],"rgb":[0.866666666666666696,0.266666666666666663,1],"xyz":[0.49933238749897868,0.267282672300344,0.971399505390786455],"hpluv":[296.287773174859751,265.393357493052918,58.721960397178492],"hsluv":[296.287773174859751,99.9999999999987779,58.721960397178492]},"#dd5500":{"lch":[53.8905970004369834,121.845910621274882,22.2085433527856502],"luv":[53.8905970004369834,112.806678507237621,46.055175814369008],"rgb":[0.866666666666666696,0.333333333333333315,0],"xyz":[0.330664855811494629,0.218716870368303284,0.0248051053792416147],"hpluv":[22.2085433527856502,286.904453583707834,53.8905970004369834],"hsluv":[22.2085433527856502,100.000000000002217,53.8905970004369834]},"#dd5511":{"lch":[53.9336739056601573,120.58904296901602,21.6306448037720749],"luv":[53.9336739056601573,112.097097503939963,44.4517492948856656],"rgb":[0.866666666666666696,0.333333333333333315,0.0666666666666666657],"xyz":[0.331676521311131733,0.219121536568158137,0.0301332103439972479],"hpluv":[21.6306448037720749,283.71818310283129,53.9336739056601573],"hsluv":[21.6306448037720749,97.0955711707227493,53.9336739056601573]},"#dd5522":{"lch":[54.0133869328819856,118.329807147086328,20.5443811064534074],"luv":[54.0133869328819856,110.804107011743554,41.5258128011568957],"rgb":[0.866666666666666696,0.333333333333333315,0.133333333333333331],"xyz":[0.33355187944960879,0.219871679823548966,0.0400100965399764405],"hpluv":[20.5443811064534074,277.99185559962018,54.0133869328819856],"hsluv":[20.5443811064534074,91.805999212684128,54.0133869328819856]},"#dd5533":{"lch":[54.1442392255445526,114.805940194650788,18.7140712474621722],"luv":[54.1442392255445526,108.736323489647134,36.8349814433582736],"rgb":[0.866666666666666696,0.333333333333333315,0.2],"xyz":[0.336639630182066496,0.221106780116532065,0.0562722503975875837],"hpluv":[18.7140712474621722,269.061420184977408,54.1442392255445526],"hsluv":[18.7140712474621722,83.3546452149230674,54.1442392255445526]},"#dd5544":{"lch":[54.3323026853354207,110.135081135525823,15.9827981501284579],"luv":[54.3323026853354207,105.877744255237971,30.3255563535325479],"rgb":[0.866666666666666696,0.333333333333333315,0.266666666666666663],"xyz":[0.341097625426285411,0.222889978214219658,0.0797510253504742223],"hpluv":[15.9827981501284579,257.221277658214035,54.3323026853354207],"hsluv":[15.9827981501284579,71.6878656400709104,54.3323026853354207]},"#dd5555":{"lch":[54.5822696158357132,104.625049281135261,12.1770506300618937],"luv":[54.5822696158357132,102.271033836367579,22.0689051636128752],"rgb":[0.866666666666666696,0.333333333333333315,0.333333333333333315],"xyz":[0.347060039465647396,0.225274943829964491,0.111153072624448138],"hpluv":[12.1770506300618937,243.233512665758,54.5822696158357132],"hsluv":[12.1770506300618937,61.8784513389384,54.5822696158357132]},"#dd5566":{"lch":[54.8977244977922254,98.7674373059184205,7.11744080010036573],"luv":[54.8977244977922254,98.0063618739055897,12.2376347477602359],"rgb":[0.866666666666666696,0.333333333333333315,0.4],"xyz":[0.354645035239155582,0.228308942139367782,0.151100717031592086],"hpluv":[7.11744080010036573,228.296245111676484,54.8977244977922254],"hsluv":[7.11744080010036573,62.7979151590930655,54.8977244977922254]},"#dd5577":{"lch":[55.2812881935381597,93.2135187108595886,0.661514811515945267],"luv":[55.2812881935381597,93.2073060454778783,1.07618316489082022],"rgb":[0.866666666666666696,0.333333333333333315,0.466666666666666674],"xyz":[0.363959048259357487,0.232034547347448605,0.20015451893799],"hpluv":[0.661514811515945267,213.963687644495565,55.2812881935381597],"hsluv":[0.661514811515945267,63.8225359413096456,55.2812881935381597]},"#dd5588":{"lch":[55.7347110848163538,88.7163187329837,352.791835078768599],"luv":[55.7347110848163538,88.0151786426913532,-11.1316457915027787],"rgb":[0.866666666666666696,0.333333333333333315,0.533333333333333326],"xyz":[0.375099465361301287,0.236490714188226203,0.258827382341562162],"hpluv":[352.791835078768599,201.984054112510194,55.7347110848163538],"hsluv":[352.791835078768599,64.9173177009572,55.7347110848163538]},"#dd5599":{"lch":[56.2589463845586408,86.0173277442407169,343.733753082454825],"luv":[56.2589463845586408,82.5740942724548717,-24.0935598727929836],"rgb":[0.866666666666666696,0.333333333333333315,0.6],"xyz":[0.388156429470374,0.241713499831855361,0.327594059982680097],"hpluv":[343.733753082454825,194.014271994181229,56.2589463845586408],"hsluv":[343.733753082454825,66.0466553819121,56.2589463845586408]},"#dd55aa":{"lch":[56.8542178605490278,85.677853149792881,334.018383993549605],"luv":[56.8542178605490278,77.0187914763158545,-37.5339883290498477],"rgb":[0.866666666666666696,0.333333333333333315,0.66666666666666663],"xyz":[0.403214122435626543,0.247736577017956455,0.406897909599678698],"hpluv":[334.018383993549605,191.225239227061849,56.8542178605490278],"hsluv":[334.018383993549605,67.3075554564469485,56.8542178605490278]},"#dd55bb":{"lch":[57.5200884026389332,87.9206422548043633,324.375348896731964],"luv":[57.5200884026389332,71.4663144117056817,-51.2113780219251638],"rgb":[0.866666666666666696,0.333333333333333315,0.733333333333333282],"xyz":[0.420351714542963217,0.254591613860891242,0.497155894698320444],"hpluv":[324.375348896731964,193.959311397505388,57.5200884026389332],"hsluv":[324.375348896731964,69.5366313504716,57.5200884026389332]},"#dd55cc":{"lch":[58.2555317670128829,92.5910381182408315,315.474469199465034],"luv":[58.2555317670128829,66.0116746837007895,-64.9273374262858596],"rgb":[0.866666666666666696,0.333333333333333315,0.8],"xyz":[0.439644089986684916,0.262308564038380043,0.5987624053685906],"hpluv":[315.474469199465034,201.683843426221756,58.2555317670128829],"hsluv":[315.474469199465034,71.7082017587958802,58.2555317670128829]},"#dd55dd":{"lch":[59.0590075291469532,99.2700295618383848,307.715012949244056],"luv":[59.0590075291469532,60.7268860008133231,-78.5288742174016363],"rgb":[0.866666666666666696,0.333333333333333315,0.866666666666666696],"xyz":[0.461162415537318515,0.270915894258633549,0.712092253268596598],"hpluv":[307.715012949244056,213.290412049590259,59.0590075291469532],"hsluv":[307.715012949244056,73.7919865345850923,59.0590075291469532]},"#dd55ee":{"lch":[59.9285380001613674,107.447476486145689,301.201070052482692],"luv":[59.9285380001613674,55.6624113436061592,-91.905691698915],"rgb":[0.866666666666666696,0.333333333333333315,0.933333333333333348],"xyz":[0.484974595803493225,0.280440766365103566,0.837503069337119821],"hpluv":[301.201070052482692,227.510719406260364,59.9285380001613674],"hsluv":[301.201070052482692,84.9240358585231405,59.9285380001613674]},"#dd55ff":{"lch":[60.8617852443614,116.651127585902827,295.843561463814751],"luv":[60.8617852443614,50.8500320114402413,-104.984569397117028],"rgb":[0.866666666666666696,0.333333333333333315,1],"xyz":[0.511145644213324646,0.29090918572903629,0.975337257628901666],"hpluv":[295.843561463814751,243.211205533984923,60.8617852443614],"hsluv":[295.843561463814751,99.9999999999987,60.8617852443614]},"#dd6600":{"lch":[56.9556719941368783,111.624872970007345,27.247071009398578],"luv":[56.9556719941368783,99.2390381331236568,51.1050445257873349],"rgb":[0.866666666666666696,0.4,0],"xyz":[0.345692913517341105,0.248772985779996625,0.0298144579478569621],"hpluv":[27.247071009398578,248.69286407076,56.9556719941368783],"hsluv":[27.247071009398578,100.000000000002402,56.9556719941368783]},"#dd6611":{"lch":[56.9952083090352204,110.431802069127656,26.6846840374429064],"luv":[56.9952083090352204,98.6698726856829325,49.5927326573774181],"rgb":[0.866666666666666696,0.4,0.0666666666666666657],"xyz":[0.346704579016978209,0.249177651979851478,0.0351425629126125919],"hpluv":[26.6846840374429064,245.864111809588593,56.9952083090352204],"hsluv":[26.6846840374429064,97.4289366186781,56.9952083090352204]},"#dd6622":{"lch":[57.0683850250612181,108.280332786330632,25.6245441521289443],"luv":[57.0683850250612181,97.630674939023308,46.8282156319165637],"rgb":[0.866666666666666696,0.4,0.133333333333333331],"xyz":[0.348579937155455266,0.249927795235242306,0.0450194491085917914],"hpluv":[25.6245441521289443,240.764984433182946,57.0683850250612181],"hsluv":[25.6245441521289443,92.7369917538900239,57.0683850250612181]},"#dd6633":{"lch":[57.1885511035567617,104.905985735707603,23.8291565941278485],"luv":[57.1885511035567617,95.9631904105633566,42.3831561992078036],"rgb":[0.866666666666666696,0.4,0.2],"xyz":[0.351667687887912972,0.251162895528225405,0.0612816029662029346],"hpluv":[23.8291565941278485,232.771873337598265,57.1885511035567617],"hsluv":[23.8291565941278485,85.2149281001260306,57.1885511035567617]},"#dd6644":{"lch":[57.3613500282636153,100.395707721520722,21.1283100845564071],"luv":[57.3613500282636153,93.6466609873464222,36.1884099516133162],"rgb":[0.866666666666666696,0.4,0.266666666666666663],"xyz":[0.356125683132131887,0.252946093625912971,0.0847603779190895801],"hpluv":[21.1283100845564071,222.093121414046323,57.3613500282636153],"hsluv":[21.1283100845564071,74.7790089775498785,57.3613500282636153]},"#dd6655":{"lch":[57.5911977652478555,95.0134939889914136,17.3206113628181804],"luv":[57.5911977652478555,90.7049894048208927,28.2872575034667619],"rgb":[0.866666666666666696,0.4,0.333333333333333315],"xyz":[0.362088097171493872,0.255331059241657832,0.116162425193063482],"hpluv":[17.3206113628181804,209.347849744778358,57.5911977652478555],"hsluv":[17.3206113628181804,61.5516693045169205,57.5911977652478555]},"#dd6666":{"lch":[57.8815358558834703,89.2064417623026742,12.1770506300619559],"luv":[57.8815358558834703,87.1993378887650579,18.8166076552624659],"rgb":[0.866666666666666696,0.4,0.4],"xyz":[0.369673092945002058,0.25836505755106115,0.156110069600207457],"hpluv":[12.1770506300619559,195.566965385494854,57.8815358558834703],"hsluv":[12.1770506300619559,60.6635523422702,57.8815358558834703]},"#dd6677":{"lch":[58.2349645673757834,83.6008411979688901,5.48003957367995387],"luv":[58.2349645673757834,83.2187459143753188,7.98379467713524704],"rgb":[0.866666666666666696,0.4,0.466666666666666674],"xyz":[0.378987105965203963,0.262090662759141946,0.205163871506605366],"hpluv":[5.48003957367995387,182.165511808695555,58.2349645673757834],"hsluv":[5.48003957367995387,61.6238417996400329,58.2349645673757834]},"#dd6688":{"lch":[58.6533262634944208,78.9686504698842,357.125632416080862],"luv":[58.6533262634944208,78.8692993006444,-3.95997283577995],"rgb":[0.866666666666666696,0.4,0.533333333333333326],"xyz":[0.390127523067147763,0.266546829599919544,0.263836734910177506],"hpluv":[357.125632416080862,170.8446551494321,58.6533262634944208],"hsluv":[357.125632416080862,62.6596910240402778,58.6533262634944208]},"#dd6699":{"lch":[59.1377678367746853,76.1279623836736192,347.292482429378936],"luv":[59.1377678367746853,74.2632604984211184,-16.746187531306056],"rgb":[0.866666666666666696,0.4,0.6],"xyz":[0.403184487176220463,0.271769615243548701,0.332603412551295441],"hpluv":[347.292482429378936,163.349798950832565,59.1377678367746853],"hsluv":[347.292482429378936,63.7390009960191435,59.1377678367746853]},"#dd66aa":{"lch":[59.6887956605557406,75.751758533498986,336.577260120739709],"luv":[59.6887956605557406,69.5095811529117,-30.1122408476074845],"rgb":[0.866666666666666696,0.4,0.66666666666666663],"xyz":[0.418242180141473,0.277792692429649823,0.411907262168294042],"hpluv":[336.577260120739709,161.042027442088397,59.6887956605557406],"hsluv":[336.577260120739709,64.8305690383666473,59.6887956605557406]},"#dd66bb":{"lch":[60.3063295400458372,78.1477005551706,325.894443158435308],"luv":[60.3063295400458372,64.706761589723726,-43.8189240697585518],"rgb":[0.866666666666666696,0.4,0.733333333333333282],"xyz":[0.435379772248809693,0.284647729272584582,0.502165247266935788],"hpluv":[325.894443158435308,164.434383230317081,60.3063295400458372],"hsluv":[325.894443158435308,65.9059953936301213,60.3063295400458372]},"#dd66cc":{"lch":[60.9897585015337427,83.1712006992562891,316.109248272524042],"luv":[60.9897585015337427,59.9384091909213694,-57.6613885491638314],"rgb":[0.866666666666666696,0.4,0.8],"xyz":[0.454672147692531392,0.292364679450073384,0.603771757937205944],"hpluv":[316.109248272524042,173.043537218511,60.9897585015337427],"hsluv":[316.109248272524042,66.9408479310096709,60.9897585015337427]},"#dd66dd":{"lch":[61.7379991889007158,90.3518241723814555,307.715012949244283],"luv":[61.7379991889007158,55.2713135142553753,-71.4740094977595675],"rgb":[0.866666666666666696,0.4,0.866666666666666696],"xyz":[0.476190473243165,0.30097200967032689,0.717101605837211942],"hpluv":[307.715012949244283,185.705044478150711,61.7379991889007158],"hsluv":[307.715012949244283,67.9151328937623759,61.7379991889007158]},"#dd66ee":{"lch":[62.5495564285741779,99.1126076890086125,300.803780654240427],"luv":[62.5495564285741779,50.7555210146825431,-85.1304063742412183],"rgb":[0.866666666666666696,0.4,0.933333333333333348],"xyz":[0.500002653509339701,0.310496881776796907,0.842512421905735165],"hpluv":[300.803780654240427,201.068480083703747,62.5495564285741779],"hsluv":[300.803780654240427,83.670703518064812,62.5495564285741779]},"#dd66ff":{"lch":[63.4225848554444696,108.928953372808309,295.226788235463459],"luv":[63.4225848554444696,46.4257694276883512,-98.5401685402585628],"rgb":[0.866666666666666696,0.4,1],"xyz":[0.526173701919171122,0.320965301140729631,0.980346610197517],"hpluv":[295.226788235463459,217.940889521273107,63.4225848554444696],"hsluv":[295.226788235463459,99.9999999999986073,63.4225848554444696]},"#dd7700":{"lch":[60.3985006876916088,102.209421710697811,33.6568691403047779],"luv":[60.3985006876916088,85.0762157619203,56.6463008330327753],"rgb":[0.866666666666666696,0.466666666666666674,0],"xyz":[0.364146651570758706,0.285680461886832382,0.0359657039656626626],"hpluv":[33.6568691403047779,214.735624532269611,60.3985006876916088],"hsluv":[33.6568691403047779,100.000000000002245,60.3985006876916088]},"#dd7711":{"lch":[60.4345564785723894,101.058408313912437,33.1281817520222],"luv":[60.4345564785723894,84.6313647704988,55.2298287886556736],"rgb":[0.866666666666666696,0.466666666666666674,0.0666666666666666657],"xyz":[0.36515831707039581,0.286085128086687235,0.0412938089304182923],"hpluv":[33.1281817520222,212.190746676882327,60.4345564785723894],"hsluv":[33.1281817520222,97.7465438968969238,60.4345564785723894]},"#dd7722":{"lch":[60.5013044729937803,98.9745052833742136,32.1281810047412648],"luv":[60.5013044729937803,83.8175940663154364,52.6361436754539582],"rgb":[0.866666666666666696,0.466666666666666674,0.133333333333333331],"xyz":[0.367033675208872867,0.286835271342078035,0.0511706951263974918],"hpluv":[32.1281810047412648,207.585936448863947,60.5013044729937803],"hsluv":[32.1281810047412648,93.6262478826975126,60.5013044729937803]},"#dd7733":{"lch":[60.6109510167574115,95.6833141687104813,30.4242910043150516],"luv":[60.6109510167574115,82.5076313520097813,48.4539717565960331],"rgb":[0.866666666666666696,0.466666666666666674,0.2],"xyz":[0.370121425941330573,0.288070371635061162,0.067432848984008642],"hpluv":[30.4242910043150516,200.320058173129354,60.6109510167574115],"hsluv":[30.4242910043150516,86.9991150080846722,60.6109510167574115]},"#dd7744":{"lch":[60.7687036553482756,91.2360291121886888,27.8356422373186483],"luv":[60.7687036553482756,80.6791699404734857,42.6014617809804932],"rgb":[0.866666666666666696,0.466666666666666674,0.266666666666666663],"xyz":[0.374579421185549488,0.289853569732748728,0.0909116239368952805],"hpluv":[27.8356422373186483,190.513488615549676,60.7687036553482756],"hsluv":[27.8356422373186483,77.760618312285672,60.7687036553482756]},"#dd7755":{"lch":[60.9786842032445122,85.8448802225428125,24.131655223886618],"luv":[60.9786842032445122,78.3427622472179479,35.096368243717265],"rgb":[0.866666666666666696,0.466666666666666674,0.333333333333333315],"xyz":[0.380541835224911473,0.292238535348493589,0.122313671210869182],"hpluv":[24.131655223886618,178.63875223296418,60.9786842032445122],"hsluv":[24.131655223886618,65.9765814384596894,60.9786842032445122]},"#dd7766":{"lch":[61.2441632046235895,79.8999585154359693,19.0216316495787474],"luv":[61.2441632046235895,75.5370685872685073,26.0414024201977448],"rgb":[0.866666666666666696,0.466666666666666674,0.4],"xyz":[0.388126830998419659,0.295272533657896907,0.162261315618013158],"hpluv":[19.0216316495787474,165.546946717194828,61.2441632046235895],"hsluv":[19.0216316495787474,57.9572057581871576,61.2441632046235895]},"#dd7777":{"lch":[61.5676827516498122,73.9875996712566,12.1770506300619097],"luv":[61.5676827516498122,72.3229127387857318,15.6064473244910626],"rgb":[0.866666666666666696,0.466666666666666674,0.466666666666666674],"xyz":[0.397440844018621564,0.298998138865977703,0.211315117524411067],"hpluv":[12.1770506300619097,152.491436777287873,61.5676827516498122],"hsluv":[12.1770506300619097,58.8480912007490744,61.5676827516498122]},"#dd7788":{"lch":[61.9511315612573,68.8928540500868252,3.33484257213660307],"luv":[61.9511315612573,68.7761927043778769,4.00757485979294081],"rgb":[0.866666666666666696,0.466666666666666674,0.533333333333333326],"xyz":[0.408581261120565364,0.303454305706755301,0.269987980927983207],"hpluv":[3.33484257213660307,141.112101622994089,61.9511315612573],"hsluv":[3.33484257213660307,59.8177792812577849,61.9511315612573]},"#dd7799":{"lch":[62.395798681375723,65.5359342889949659,352.534540584191575],"luv":[62.395798681375723,64.9804103256140309,-8.5149842657693231],"rgb":[0.866666666666666696,0.466666666666666674,0.6],"xyz":[0.421638225229638119,0.308677091350384458,0.338754658569101141],"hpluv":[352.534540584191575,133.27953643418,62.395798681375723],"hsluv":[352.534540584191575,60.8378233331756135,62.395798681375723]},"#dd77aa":{"lch":[62.9024183325334576,64.7691926058513587,340.409048511657261],"luv":[62.9024183325334576,61.0197310981447743,-21.7172909803219412],"rgb":[0.866666666666666696,0.466666666666666674,0.66666666666666663],"xyz":[0.43669591819489062,0.314700168536485581,0.418058508186099742],"hpluv":[340.409048511657261,130.659342151792146,62.9024183325334576],"hsluv":[340.409048511657261,61.8795186032410598,62.9024183325334576]},"#dd77bb":{"lch":[63.4712121738611472,67.0588140204747,328.168414880738283],"luv":[63.4712121738611472,56.973307333119962,-35.3684434115847779],"rgb":[0.866666666666666696,0.466666666666666674,0.733333333333333282],"xyz":[0.453833510302227294,0.321555205379420339,0.508316493284741489],"hpluv":[328.168414880738283,134.065922948238125,63.4712121738611472],"hsluv":[328.168414880738283,62.9156692244191049,63.4712121738611472]},"#dd77cc":{"lch":[64.1019320742502856,72.2937871392105649,317.045265551381931],"luv":[64.1019320742502856,52.9112642996390861,-49.2624580095555586],"rgb":[0.866666666666666696,0.466666666666666674,0.8],"xyz":[0.473125885745949049,0.329272155556909141,0.609923003955011644],"hpluv":[317.045265551381931,143.109736775843601,64.1019320742502856],"hsluv":[317.045265551381931,63.9218174738772262,64.1019320742502856]},"#dd77dd":{"lch":[64.7939046430230547,79.9242419089019904,307.715012949244624],"luv":[64.7939046430230547,48.8924033620837761,-63.225132172198613],"rgb":[0.866666666666666696,0.466666666666666674,0.866666666666666696],"xyz":[0.494644211296582537,0.337879485777162647,0.723252851855017642],"hpluv":[307.715012949244624,156.524995415635317,64.7939046430230547],"hsluv":[307.715012949244624,64.8769154463944,64.7939046430230547]},"#dd77ee":{"lch":[65.5460776792256,89.2673698488479772,300.244676230176196],"luv":[65.5460776792256,44.9634126652007424,-77.116501743983946],"rgb":[0.866666666666666696,0.466666666666666674,0.933333333333333348],"xyz":[0.518456391562757357,0.347404357883632664,0.848663667923540865],"hpluv":[300.244676230176196,172.816560464305326,65.5460776792256],"hsluv":[300.244676230176196,82.07388698168063,65.5460776792256]},"#dd77ff":{"lch":[66.3570680439545,99.7204006423648366,294.377473048092611],"luv":[66.3570680439545,41.1592308753033436,-90.8299290874281837],"rgb":[0.866666666666666696,0.466666666666666674,1],"xyz":[0.544627439972588667,0.357872777247565388,0.98649785621532271],"hpluv":[294.377473048092611,190.693615319177383,66.3570680439545],"hsluv":[294.377473048092611,99.9999999999983373,66.3570680439545]},"#dd8800":{"lch":[64.1467534130096766,94.4821411478558701,41.4445641191571781],"luv":[64.1467534130096766,70.8234804869986192,62.5372657508392],"rgb":[0.866666666666666696,0.533333333333333326,0],"xyz":[0.386219021295729159,0.329825201336773954,0.0433231605406526124],"hpluv":[41.4445641191571781,186.902182331454583,64.1467534130096766],"hsluv":[41.4445641191571781,100.000000000002416,64.1467534130096766]},"#dd8811":{"lch":[64.1795176641247593,93.3565504581455,40.9755438084832377],"luv":[64.1795176641247593,70.4832194968749235,61.2173282886440333],"rgb":[0.866666666666666696,0.533333333333333326,0.0666666666666666657],"xyz":[0.387230686795366263,0.330229867536628807,0.0486512655054082421],"hpluv":[40.9755438084832377,184.581288668542754,64.1795176641247593],"hsluv":[40.9755438084832377,98.0366401848460072,64.1795176641247593]},"#dd8822":{"lch":[64.2401831232140665,91.3094921720035444,40.0852847486271529],"luv":[64.2401831232140665,69.8596876954725303,58.7966614341343359],"rgb":[0.866666666666666696,0.533333333333333326,0.133333333333333331],"xyz":[0.38910604493384332,0.330980010792019608,0.0585281517013874417],"hpluv":[40.0852847486271529,180.363429125237786,64.2401831232140665],"hsluv":[40.0852847486271529,94.440421143342,64.2401831232140665]},"#dd8833":{"lch":[64.3398685532121704,88.0506151089842319,38.5586382769189342],"luv":[64.3398685532121704,68.8529964065635,54.8832916916272],"rgb":[0.866666666666666696,0.533333333333333326,0.2],"xyz":[0.392193795666301,0.332215111085002734,0.0747903055589985849],"hpluv":[38.5586382769189342,173.656703033806934,64.3398685532121704],"hsluv":[38.5586382769189342,88.6389494712849171,64.3398685532121704]},"#dd8844":{"lch":[64.4833562447751376,83.590391105324656,36.2144134416389392],"luv":[64.4833562447751376,67.4417066096926305,49.3859260793323571],"rgb":[0.866666666666666696,0.533333333333333326,0.266666666666666663],"xyz":[0.396651790910519941,0.333998309182690301,0.0982690805118852234],"hpluv":[36.2144134416389392,164.493238171948974,64.4833562447751376],"hsluv":[36.2144134416389392,80.515719620269337,64.4833562447751376]},"#dd8855":{"lch":[64.6744699451661234,78.0792033713498768,32.8038905377638059],"luv":[64.6744699451661234,65.6278986079903746,42.3006019272060527],"rgb":[0.866666666666666696,0.533333333333333326,0.333333333333333315],"xyz":[0.402614204949881926,0.336383274798435161,0.129671127785859125],"hpluv":[32.8038905377638059,153.194023310958244,64.6744699451661234],"hsluv":[32.8038905377638059,70.0933757373770874,64.6744699451661234]},"#dd8866":{"lch":[64.9162913059566762,71.8298791231791114,27.9793586637294176],"luv":[64.9162913059566762,63.4341634455056251,33.69923504798588],"rgb":[0.866666666666666696,0.533333333333333326,0.4],"xyz":[0.410199200723390112,0.33941727310783848,0.169618772193003087],"hpluv":[27.9793586637294176,140.40764710249897,64.9162913059566762],"hsluv":[27.9793586637294176,57.516131894534638,64.9162913059566762]},"#dd8877":{"lch":[65.211273186305,65.3549274640793243,21.2774014292581],"luv":[65.211273186305,60.8999714810578325,23.7162395299384023],"rgb":[0.866666666666666696,0.533333333333333326,0.466666666666666674],"xyz":[0.419513213743592,0.343142878315919275,0.218672574099401],"hpluv":[21.2774014292581,127.173019810527066,65.211273186305],"hsluv":[21.2774014292581,55.3192807564291797,65.211273186305]},"#dd8888":{"lch":[65.5613077882642585,59.4140252364257222,12.17705063006205],"luv":[65.5613077882642585,58.0772370198051675,12.5323954190731097],"rgb":[0.866666666666666696,0.533333333333333326,0.533333333333333326],"xyz":[0.430653630845535818,0.347599045156696873,0.277345437502973191],"hpluv":[12.17705063006205,114.995459986814794,65.5613077882642585],"hsluv":[12.17705063006205,56.217054427929,65.5613077882642585]},"#dd8899":{"lch":[65.9677735951440809,55.0265961591163304,0.371909902430330563],"luv":[65.9677735951440809,55.0254369244830599,0.357178006339119947],"rgb":[0.866666666666666696,0.533333333333333326,0.6],"xyz":[0.443710594954608517,0.352821830800326031,0.34611211514409107],"hpluv":[0.371909902430330563,105.847388780281833,65.9677735951440809],"hsluv":[0.371909902430330563,57.1692646853200088,65.9677735951440809]},"#dd88aa":{"lch":[66.4315725960282,53.3143351650078756,346.342357286170909],"luv":[66.4315725960282,51.8068159744011751,-12.5885723051236678],"rgb":[0.866666666666666696,0.533333333333333326,0.66666666666666663],"xyz":[0.458768287919861073,0.358844907986427153,0.425415964761089671],"hpluv":[346.342357286170909,101.837748961685463,66.4315725960282],"hsluv":[346.342357286170909,58.1497775423036174,66.4315725960282]},"#dd88bb":{"lch":[66.9531637379342754,55.0554122119122695,331.715662007953938],"luv":[66.9531637379342754,48.482176665295448,-26.0878699709014299],"rgb":[0.866666666666666696,0.533333333333333326,0.733333333333333282],"xyz":[0.475905880027197747,0.365699944829361911,0.515673949859731473],"hpluv":[331.715662007953938,104.344182679937973,66.9531637379342754],"hsluv":[331.715662007953938,59.1328526037280824,66.9531637379342754]},"#dd88cc":{"lch":[67.5325957217288391,60.2482932018326949,318.477460357427788],"luv":[67.5325957217288391,45.1075955230381,-39.9394749572899741],"rgb":[0.866666666666666696,0.533333333333333326,0.8],"xyz":[0.495198255470919446,0.373416895006850713,0.617280460530001629],"hpluv":[318.477460357427788,113.206309259525241,67.5325957217288391],"hsluv":[318.477460357427788,60.0943355072680134,67.5325957217288391]},"#dd88dd":{"lch":[68.1695406599531566,68.219499196860184,307.715012949245079],"luv":[68.1695406599531566,41.7322103060295,-53.965940125636024],"rgb":[0.866666666666666696,0.533333333333333326,0.866666666666666696],"xyz":[0.516716581021553,0.382024225227104219,0.730610308430007627],"hpluv":[307.715012949245079,126.986480244117786,68.1695406599531566],"hsluv":[307.715012949245079,61.0124281772922785,68.1695406599531566]},"#dd88ee":{"lch":[68.8633291469121,78.1074456653267504,299.445313850889818],"luv":[68.8633291469121,38.3970440138518896,-68.0179393936650456],"rgb":[0.866666666666666696,0.533333333333333326,0.933333333333333348],"xyz":[0.540528761287727755,0.391549097333574236,0.85602112449853085],"hpluv":[299.445313850889818,143.92748858218269,68.8633291469121],"hsluv":[299.445313850889818,80.0342386911036385,68.8633291469121]},"#dd88ff":{"lch":[69.6129866887261244,89.1875622693819281,293.199992160066699],"luv":[69.6129866887261244,35.1347073752451706,-81.975445111391565],"rgb":[0.866666666666666696,0.533333333333333326,1],"xyz":[0.566699809697559176,0.40201751669750696,0.993855312790312695],"hpluv":[293.199992160066699,162.574846632166981,69.6129866887261244],"hsluv":[293.199992160066699,99.9999999999981242,69.6129866887261244]},"#dd9900":{"lch":[68.1357569139589287,89.1370219700488775,50.3810095729648921],"luv":[68.1357569139589287,56.8408371488252229,68.6624199829113735],"rgb":[0.866666666666666696,0.6,0],"xyz":[0.41208862174819666,0.381564402241709621,0.0519463606914748674],"hpluv":[50.3810095729648921,166.005456049637957,68.1357569139589287],"hsluv":[50.3810095729648921,100.000000000002245,68.1357569139589287]},"#dd9911":{"lch":[68.1654896561650077,88.0318570495471278,50.0002977758109424],"luv":[68.1654896561650077,56.5854364905009248,67.4366089951992507],"rgb":[0.866666666666666696,0.6,0.0666666666666666657],"xyz":[0.413100287247833764,0.381969068441564474,0.0572744656562305],"hpluv":[50.0002977758109424,163.875726960716179,68.1654896561650077],"hsluv":[50.0002977758109424,98.2940371374324826,68.1654896561650077]},"#dd9922":{"lch":[68.2205507365204,86.012937831153792,49.27558445879027],"luv":[68.2205507365204,56.1166821435168472,65.1854543556261774],"rgb":[0.866666666666666696,0.6,0.133333333333333331],"xyz":[0.414975645386310821,0.382719211696955275,0.0671513518522096897],"hpluv":[49.27558445879027,159.988175949224541,68.2205507365204],"hsluv":[49.27558445879027,95.1643810214000325,68.2205507365204]},"#dd9933":{"lch":[68.3110514885433133,82.7730333151944677,48.0261582829398179],"luv":[68.3110514885433133,55.3578808500206918,61.5376313485756867],"rgb":[0.866666666666666696,0.6,0.2],"xyz":[0.418063396118768527,0.383954311989938402,0.0834135057098208399],"hpluv":[48.0261582829398179,153.757824966526499,68.3110514885433133],"hsluv":[48.0261582829398179,90.1021642959546512,68.3110514885433133]},"#dd9944":{"lch":[68.4413718194248,78.2806718730308688,46.0898611008159875],"luv":[68.4413718194248,54.2899414547091936,56.3956190296495805],"rgb":[0.866666666666666696,0.6,0.266666666666666663],"xyz":[0.422521391362987442,0.385737510087625968,0.106892280662707478],"hpluv":[46.0898611008159875,145.136005207448051,68.4413718194248],"hsluv":[46.0898611008159875,82.9860784920926449,68.4413718194248]},"#dd9955":{"lch":[68.615044439797245,72.617894762441864,43.2298844404699452],"luv":[68.615044439797245,52.9102318436571935,49.7379734808277689],"rgb":[0.866666666666666696,0.6,0.333333333333333315],"xyz":[0.428483805402349427,0.388122475703370828,0.138294327936681394],"hpluv":[43.2298844404699452,134.296171447129637,68.615044439797245],"hsluv":[43.2298844404699452,73.8078183466747362,68.615044439797245]},"#dd9966":{"lch":[68.8349542760461333,65.9999398631214262,39.0839575312566296],"luv":[68.8349542760461333,51.2306688139135815,41.6102227200810404],"rgb":[0.866666666666666696,0.6,0.4],"xyz":[0.436068801175857612,0.391156474012774147,0.178241972343825356],"hpluv":[39.0839575312566296,121.667290932950721,68.8349542760461333],"hsluv":[39.0839575312566296,62.6592399312796076,68.8349542760461333]},"#dd9977":{"lch":[69.1034430542988929,58.8170492635600723,33.0939178586399834],"luv":[69.1034430542988929,49.2755524050587468,32.1148753578207291],"rgb":[0.866666666666666696,0.6,0.466666666666666674],"xyz":[0.445382814196059518,0.394882079220854942,0.227295774250223265],"hpluv":[33.0939178586399834,108.004754244465147,69.1034430542988929],"hsluv":[33.0939178586399834,50.7393036295826789,69.1034430542988929]},"#dd9988":{"lch":[69.4223715869125328,51.7141196395305656,24.4437159362198635],"luv":[69.4223715869125328,47.0788901370553745,21.3992587150758773],"rgb":[0.866666666666666696,0.6,0.533333333333333326],"xyz":[0.456523231298003318,0.39933824606163254,0.285968637653795432],"hpluv":[24.4437159362198635,94.5255072345235305,69.4223715869125328],"hsluv":[24.4437159362198635,51.5589665528693786,69.4223715869125328]},"#dd9999":{"lch":[69.7931614924381591,45.7097919546320597,12.1770506300622632],"luv":[69.7931614924381591,44.6813426781189875,9.64171649740066705],"rgb":[0.866666666666666696,0.6,0.6],"xyz":[0.469580195407076073,0.404561031705261698,0.354735315294913311],"hpluv":[12.1770506300622632,83.1066353202273689,69.7931614924381591],"hsluv":[12.1770506300622632,52.4335711570844438,69.7931614924381591]},"#dd99aa":{"lch":[70.2168268189972196,42.2311183685245624,355.977290330288042],"luv":[70.2168268189972196,42.1270745474506256,-2.96259155636920823],"rgb":[0.866666666666666696,0.6,0.66666666666666663],"xyz":[0.484637888372328574,0.41058410889136282,0.434039164911911912],"hpluv":[355.977290330288042,76.3186553239153369,70.2168268189972196],"hsluv":[355.977290330288042,53.3392978779897788,70.2168268189972196]},"#dd99bb":{"lch":[70.694001085559151,42.6623948649138427,337.661645838825223],"luv":[70.694001085559151,39.4608168046039651,-16.2149274658665163],"rgb":[0.866666666666666696,0.6,0.733333333333333282],"xyz":[0.501775480479665248,0.417439145734297579,0.524297150010553659],"hpluv":[337.661645838825223,76.5776430619999502,70.694001085559151],"hsluv":[337.661645838825223,54.2517942883204398,70.694001085559151]},"#dd99cc":{"lch":[71.2249627580945912,47.3730793907595,320.82657583403028],"luv":[71.2249627580945912,36.7253906259007294,-29.9241430008982121],"rgb":[0.866666666666666696,0.6,0.8],"xyz":[0.521067855923387,0.42515609591178638,0.625903660680823815],"hpluv":[320.82657583403028,84.3992741769230719,71.2249627580945912],"hsluv":[320.82657583403028,55.1472527266246075,71.2249627580945912]},"#dd99dd":{"lch":[71.8096607795551876,55.5140341348433424,307.715012949246],"luv":[71.8096607795551876,33.9598410238411077,-43.9151133843462844],"rgb":[0.866666666666666696,0.6,0.866666666666666696],"xyz":[0.54258618147402049,0.433763426132039887,0.739233508580829812],"hpluv":[307.715012949246,98.0977936102115677,71.8096607795551876],"hsluv":[307.715012949246,56.0031828352742878,71.8096607795551876]},"#dd99ee":{"lch":[72.447740927007942,65.8885644567307907,298.26171852853804],"luv":[72.447740927007942,31.1982236173053273,-58.0342465212858656],"rgb":[0.866666666666666696,0.6,0.933333333333333348],"xyz":[0.566398361740195311,0.443288298238509904,0.864644324649353],"hpluv":[298.26171852853804,115.404973126410823,72.447740927007942],"hsluv":[298.26171852853804,77.3800261839098908,72.447740927007942]},"#dd99ff":{"lch":[73.1385732331520302,77.5656763031263,291.532620718417377],"luv":[73.1385732331520302,28.4689992262389602,-72.1522710898123592],"rgb":[0.866666666666666696,0.6,1],"xyz":[0.592569410150026621,0.453756717602442627,1.00247851294113488],"hpluv":[291.532620718417377,134.574391894016571,73.1385732331520302],"hsluv":[291.532620718417377,99.9999999999977689,73.1385732331520302]},"#cc0000":{"lch":[42.5207510295766156,142.998625281495549,12.1770506300617818],"luv":[42.5207510295766156,139.781222041964895,30.163169542547891],"rgb":[0.8,0,0],"xyz":[0.249012838889184379,0.128397245052238429,0.0116724768229302719],"hpluv":[12.1770506300617818,426.746789183124861,42.5207510295766156],"hsluv":[12.1770506300617818,100.000000000002174,42.5207510295766156]},"#cc0011":{"lch":[42.5821659889152784,141.236718626044905,11.4841194603559],"luv":[42.5821659889152784,138.409148973409117,28.119711390930437],"rgb":[0.8,0,0.0666666666666666657],"xyz":[0.250024504388821511,0.128801911252093282,0.0170005817876859033],"hpluv":[11.4841194603559,420.880880123779207,42.5821659889152784],"hsluv":[11.4841194603559,99.9999999999964331,42.5821659889152784]},"#cc0022":{"lch":[42.6956735686566518,138.114600243667155,10.1872609469282853],"luv":[42.6956735686566518,135.937217546775798,24.4277646564013864],"rgb":[0.8,0,0.133333333333333331],"xyz":[0.251899862527298513,0.12955205450748411,0.0268774679836651],"hpluv":[10.1872609469282853,410.482879191578036,42.6956735686566518],"hsluv":[10.1872609469282853,99.9999999999964615,42.6956735686566518]},"#cc0033":{"lch":[42.881611378965772,133.362165770655935,8.01952044887972626],"luv":[42.881611378965772,132.057963211529,18.6054188736068511],"rgb":[0.8,0,0.2],"xyz":[0.254987613259756274,0.130787154800467209,0.0431396218412762461],"hpluv":[8.01952044887972626,394.639788400466045,42.881611378965772],"hsluv":[8.01952044887972626,99.9999999999966604,42.881611378965772]},"#cc0044":{"lch":[43.1480085091585153,127.29097956278504,4.82801781999359658],"luv":[43.1480085091585153,126.839328429887985,10.7134607624411853],"rgb":[0.8,0,0.266666666666666663],"xyz":[0.259445608503975134,0.132570352898154803,0.0666183967941628846],"hpluv":[4.82801781999359658,374.34858804079829,43.1480085091585153],"hsluv":[4.82801781999359658,99.9999999999967741,43.1480085091585153]},"#cc0055":{"lch":[43.5005971125795,120.485699890795146,0.473888563816867114],"luv":[43.5005971125795,120.481578818580687,0.996515708296922487],"rgb":[0.8,0,0.333333333333333315],"xyz":[0.265408022543337119,0.134955318513899636,0.0980204440681367861],"hpluv":[0.473888563816867114,351.463000970195878,43.5005971125795],"hsluv":[0.473888563816867114,99.999999999997,43.5005971125795]},"#cc0066":{"lch":[43.9431844272177372,113.726547538665841,354.863826263116096],"luv":[43.9431844272177372,113.269906269789104,-10.1811565500985228],"rgb":[0.8,0,0.4],"xyz":[0.272993018316845304,0.137989316823302927,0.137968088475280748],"hpluv":[354.863826263116096,328.404920869645196,43.9431844272177372],"hsluv":[354.863826263116096,99.9999999999972857,43.9431844272177372]},"#cc0077":{"lch":[44.4778741065655,107.874648109024193,348.012259047653401],"luv":[44.4778741065655,105.522124609829902,-22.4058234053856609],"rgb":[0.8,0,0.466666666666666674],"xyz":[0.28230703133704721,0.14171492203138375,0.187021890381678657],"hpluv":[348.012259047653401,307.761788629886667,44.4778741065655],"hsluv":[348.012259047653401,99.9999999999975273,44.4778741065655]},"#cc0088":{"lch":[45.1052440924579,103.725434836726933,340.1176986346278],"luv":[45.1052440924579,97.5426962017022703,-35.2758876538989838],"rgb":[0.8,0,0.533333333333333326],"xyz":[0.293447448438991065,0.146171088872161348,0.245694753785250825],"hpluv":[340.1176986346278,291.808241377507443,45.1052440924579],"hsluv":[340.1176986346278,99.9999999999978,45.1052440924579]},"#cc0099":{"lch":[45.8245205562958589,101.850048541314862,331.598662995615],"luv":[45.8245205562958589,89.5911194129305102,-48.4444394147173441],"rgb":[0.8,0,0.6],"xyz":[0.306504412548063765,0.151393874515790505,0.314461431426368732],"hpluv":[331.598662995615,282.034759885138044,45.8245205562958589],"hsluv":[331.598662995615,99.9999999999981,45.8245205562958589]},"#cc00aa":{"lch":[46.633760692471931,102.477609530343315,323.022725489580409],"luv":[46.633760692471931,81.8667129915779,-61.640098629123905],"rgb":[0.8,0,0.66666666666666663],"xyz":[0.321562105513316321,0.1574169517018916,0.393765281043367332],"hpluv":[323.022725489580409,278.848217687739293,46.633760692471931],"hsluv":[323.022725489580409,99.9999999999983658,46.633760692471931]},"#cc00bb":{"lch":[47.5300446684938933,105.484027274260768,314.937463984289479],"luv":[47.5300446684938933,74.5070162947061903,-74.6698368342758414],"rgb":[0.8,0,0.733333333333333282],"xyz":[0.33869969762065294,0.164271988544826358,0.484023266142009079],"hpluv":[314.937463984289479,281.616311803476265,47.5300446684938933],"hsluv":[314.937463984289479,99.9999999999986,47.5300446684938933]},"#cc00cc":{"lch":[48.5096711653281147,110.497164945278598,307.715012949243601],"luv":[48.5096711653281147,67.5949102529980621,-87.4102486487325],"rgb":[0.8,0,0.8],"xyz":[0.357992073064374694,0.17198893872231516,0.585629776812279235],"hpluv":[307.715012949243601,289.042783730483393,48.5096711653281147],"hsluv":[307.715012949243601,99.9999999999988,48.5096711653281147]},"#cc00dd":{"lch":[49.5683488162236614,117.049051317219835,301.506761454082039],"luv":[49.5683488162236614,61.1697383356450075,-99.7935044289451],"rgb":[0.8,0,0.866666666666666696],"xyz":[0.379510398615008238,0.180596268942568694,0.698959624712285232],"hpluv":[301.506761454082039,299.64205877637869,49.5683488162236614],"hsluv":[301.506761454082039,99.9999999999990337,49.5683488162236614]},"#cc00ee":{"lch":[50.7013760136427862,124.695255359169607,296.294949026353493],"luv":[50.7013760136427862,55.2390203059142522,-111.792474454818787],"rgb":[0.8,0,0.933333333333333348],"xyz":[0.403322578881182947,0.190121141049038739,0.824370440780808456],"hpluv":[296.294949026353493,312.082566880879938,50.7013760136427862],"hsluv":[296.294949026353493,99.99999999999919,50.7013760136427862]},"#cc00ff":{"lch":[51.9038030272213,133.072735088441448,291.971633700566258],"luv":[51.9038030272213,49.7888328026579075,-123.407556300526],"rgb":[0.8,0,1],"xyz":[0.429493627291014368,0.200589560412971435,0.962204629072590301],"hpluv":[291.971633700566258,325.333832743425603,51.9038030272213],"hsluv":[291.971633700566258,99.9999999999993321,51.9038030272213]},"#cc1100":{"lch":[43.1235624482234172,140.134259476931788,12.8715382160273855],"luv":[43.1235624482234172,136.61296213687416,31.2171307992428524],"rgb":[0.8,0.0666666666666666657,0],"xyz":[0.251017239150112814,0.132406045574095299,0.0123406102432397219],"hpluv":[12.8715382160273855,412.352867097941,43.1235624482234172],"hsluv":[12.8715382160273855,100.000000000002245,43.1235624482234172]},"#cc1111":{"lch":[43.1837333530957892,138.41807101963343,12.1770506300617676],"luv":[43.1837333530957892,135.303728142340162,29.196978192614182],"rgb":[0.8,0.0666666666666666657,0.0666666666666666657],"xyz":[0.252028904649749919,0.132810711773950152,0.0176687152079953516],"hpluv":[12.1770506300617676,406.735363437937394,43.1837333530957892],"hsluv":[12.1770506300617676,95.3107026807431197,43.1837333530957892]},"#cc1122":{"lch":[43.294951674171287,135.375047793376126,10.8766574447476163],"luv":[43.294951674171287,132.943125696930394,25.5446451333550044],"rgb":[0.8,0.0666666666666666657,0.133333333333333331],"xyz":[0.253904262788227,0.13356085502934098,0.0275456014039745511],"hpluv":[10.8766574447476163,396.771701832449367,43.294951674171287],"hsluv":[10.8766574447476163,95.396390587568618,43.294951674171287]},"#cc1133":{"lch":[43.4771672841157724,130.73841758888139,8.7012157385065958],"luv":[43.4771672841157724,129.233706917218683,19.7783424502448213],"rgb":[0.8,0.0666666666666666657,0.2],"xyz":[0.256992013520684681,0.134795955322324079,0.0438077552615856944],"hpluv":[8.7012157385065958,381.576227833431062,43.4771672841157724],"hsluv":[8.7012157385065958,95.5308510527687389,43.4771672841157724]},"#cc1144":{"lch":[43.7382910834512586,124.807582872189826,5.49437317543092796],"luv":[43.7382910834512586,124.234167693991893,11.9500761411646046],"rgb":[0.8,0.0666666666666666657,0.266666666666666663],"xyz":[0.261450008764903596,0.136579153420011673,0.0672865302144723398],"hpluv":[5.49437317543092796,362.091632024479338,43.7382910834512586],"hsluv":[5.49437317543092796,95.7116850897169229,43.7382910834512586]},"#cc1155":{"lch":[44.0840061747103107,118.151091154502552,1.11194247693657511],"luv":[44.0840061747103107,118.128842001262925,2.29282106589917234],"rgb":[0.8,0.0666666666666666657,0.333333333333333315],"xyz":[0.267412422804265582,0.138964119035756506,0.0986885774884462413],"hpluv":[1.11194247693657511,340.091681007194666,44.0840061747103107],"hsluv":[1.11194247693657511,95.9318436200579754,44.0840061747103107]},"#cc1166":{"lch":[44.5181325219627837,111.53522478210337,355.453854482233226],"luv":[44.5181325219627837,111.184314904818763,-8.84050260677650712],"rgb":[0.8,0.0666666666666666657,0.4],"xyz":[0.274997418577773767,0.141998117345159797,0.138636221895590217],"hpluv":[355.453854482233226,317.917500588946211,44.5181325219627837],"hsluv":[355.453854482233226,96.1812476973727115,44.5181325219627837]},"#cc1177":{"lch":[45.0428415016287857,105.814757555455103,348.528515458334311],"luv":[45.0428415016287857,103.700981473984271,-21.0444614531261323],"rgb":[0.8,0.0666666666666666657,0.466666666666666674],"xyz":[0.284311431597975672,0.14572372255324062,0.187690023801988126],"hpluv":[348.528515458334311,298.098498005115459,45.0428415016287857],"hsluv":[348.528515458334311,96.4486017572014589,45.0428415016287857]},"#cc1188":{"lch":[45.6588256994622341,101.788242110562607,340.533613155211185],"luv":[45.6588256994622341,95.9697371205835594,-33.9213176183443323],"rgb":[0.8,0.0666666666666666657,0.533333333333333326],"xyz":[0.295451848699919473,0.150179889394018218,0.246362887205560266],"hpluv":[340.533613155211185,282.886487347344485,45.6588256994622341],"hsluv":[340.533613155211185,96.7230145871901215,45.6588256994622341]},"#cc1199":{"lch":[46.3654632546324876,100.035938879036408,331.896400713626349],"luv":[46.3654632546324876,88.2414291467186,-47.1236591273953138],"rgb":[0.8,0.0666666666666666657,0.6],"xyz":[0.308508812808992228,0.155402675037647375,0.315129564846678201],"hpluv":[331.896400713626349,273.779405248492822,46.3654632546324876],"hsluv":[331.896400713626349,96.9951405388504355,46.3654632546324876]},"#cc11aa":{"lch":[47.1609900317596882,100.794975336059878,323.201580807901109],"luv":[47.1609900317596882,80.7113646178594735,-60.3763420100941488],"rgb":[0.8,0.0666666666666666657,0.66666666666666663],"xyz":[0.323566505774244728,0.16142575222374847,0.394433414463676801],"hpluv":[323.201580807901109,271.203503720358924,47.1609900317596882],"hsluv":[323.201580807901109,97.2577546113476075,47.1609900317596882]},"#cc11bb":{"lch":[48.0426807208370548,103.942897448445919,315.013990059648165],"luv":[48.0426807208370548,73.5166718264647727,-73.4807790754699681],"rgb":[0.8,0.0666666666666666657,0.733333333333333282],"xyz":[0.340704097881581403,0.168280789066683228,0.484691399562318548],"hpluv":[315.013990059648165,274.540811344802705,48.0426807208370548],"hsluv":[315.013990059648165,97.5058443216483,48.0426807208370548]},"#cc11cc":{"lch":[49.0070341259591515,109.103198367120783,307.715012949243601],"luv":[49.0070341259591515,66.7421730285370387,-86.3075328888743769],"rgb":[0.8,0.0666666666666666657,0.8],"xyz":[0.359996473325303157,0.17599773924417203,0.586297910232588704],"hpluv":[307.715012949243601,282.499958642668389,49.0070341259591515],"hsluv":[307.715012949243601,97.7363817897909541,49.0070341259591515]},"#cc11dd":{"lch":[50.0499556366759037,115.801352096543823,301.456118533327128],"luv":[50.0499556366759037,60.4304023076134555,-98.7831950502093292],"rgb":[0.8,0.0666666666666666657,0.866666666666666696],"xyz":[0.381514798875936645,0.184605069464425564,0.699627758132594701],"hpluv":[301.456118533327128,293.595408819402792,50.0499556366759037],"hsluv":[301.456118533327128,97.9479403979501342,50.0499556366759037]},"#cc11ee":{"lch":[51.1669298024285837,123.587345912593733,296.214453457233276],"luv":[51.1669298024285837,54.5925079172689109,-110.876012505059137],"rgb":[0.8,0.0666666666666666657,0.933333333333333348],"xyz":[0.40532697914211141,0.194129941570895609,0.825038574201117925],"hpluv":[296.214453457233276,306.495409047480564,51.1669298024285837],"hsluv":[296.214453457233276,98.1402788193950215,51.1669298024285837]},"#cc11ff":{"lch":[52.3531771468210678,132.094610043027387,291.87590029388349],"luv":[52.3531771468210678,49.2181193296501576,-122.582881072651375],"rgb":[0.8,0.0666666666666666657,1],"xyz":[0.431498027551942775,0.204598360934828305,0.96287276249289977],"hpluv":[291.87590029388349,320.170549145207644,52.3531771468210678],"hsluv":[291.87590029388349,99.9999999999991189,52.3531771468210678]},"#cc2200":{"lch":[44.2095884480383674,135.132222138307952,14.1797238149512133],"luv":[44.2095884480383674,131.015027118873576,33.102569825888537],"rgb":[0.8,0.133333333333333331,0],"xyz":[0.254732862884880729,0.139837293043631267,0.0135791514881623328],"hpluv":[14.1797238149512133,387.866054960954045,44.2095884480383674],"hsluv":[14.1797238149512133,100.00000000000226,44.2095884480383674]},"#cc2211":{"lch":[44.2676114068871129,133.490625771231663,13.482935392010976],"luv":[44.2676114068871129,129.81154471696064,31.1241068464871375],"rgb":[0.8,0.133333333333333331,0.0666666666666666657],"xyz":[0.255744528384517833,0.14024195924348612,0.0189072564529179643],"hpluv":[13.482935392010976,382.652016671578622,44.2676114068871129],"hsluv":[13.482935392010976,95.5414705532830197,44.2676114068871129]},"#cc2222":{"lch":[44.3748759613401162,130.576558981694717,12.1770506300617747],"luv":[44.3748759613401162,127.638646515421286,27.5429423121666019],"rgb":[0.8,0.133333333333333331,0.133333333333333331],"xyz":[0.25761988652299489,0.140992102498876948,0.0287841426488971604],"hpluv":[12.1770506300617747,373.394050741154899,44.3748759613401162],"hsluv":[12.1770506300617747,87.4977996802062847,44.3748759613401162]},"#cc2233":{"lch":[44.5506596541482907,126.128431434884163,9.98899557195718657],"luv":[44.5506596541482907,124.216461430809,21.8781152257824267],"rgb":[0.8,0.133333333333333331,0.2],"xyz":[0.260707637255452596,0.142227202791860047,0.0450462965065083071],"hpluv":[9.98899557195718657,359.251162664680805,44.5506596541482907],"hsluv":[9.98899557195718657,87.8457930667704829,44.5506596541482907]},"#cc2244":{"lch":[44.8026641682027602,120.425301369152351,6.75586226508684629],"luv":[44.8026641682027602,119.589119356054482,14.1667124448306829],"rgb":[0.8,0.133333333333333331,0.266666666666666663],"xyz":[0.265165632499671511,0.144010400889547641,0.0685250714593949456],"hpluv":[6.75586226508684629,341.077623618219945,44.8026641682027602],"hsluv":[6.75586226508684629,88.3153597242729,44.8026641682027602]},"#cc2255":{"lch":[45.136480402373536,114.008772215671115,2.323188749975583],"luv":[45.136480402373536,113.915065115628011,4.62148047999889577],"rgb":[0.8,0.133333333333333331,0.333333333333333315],"xyz":[0.271128046539033496,0.146395366505292474,0.0999271187333688471],"hpluv":[2.323188749975583,320.51614012782295,45.136480402373536],"hsluv":[2.323188749975583,88.8894607126765663,45.136480402373536]},"#cc2266":{"lch":[45.5559407124691731,107.622008592458101,356.577515499379103],"luv":[45.5559407124691731,107.430062323442542,-6.42483016556681452],"rgb":[0.8,0.133333333333333331,0.4],"xyz":[0.278713042312541681,0.149429364814695764,0.139874763140512809],"hpluv":[356.577515499379103,299.774992396016216,45.5559407124691731],"hsluv":[356.577515499379103,89.543058875786258,45.5559407124691731]},"#cc2277":{"lch":[46.0633224094211542,102.110102175352239,349.514816334356908],"luv":[46.0633224094211542,100.405067655344695,-18.5821246198201955],"rgb":[0.8,0.133333333333333331,0.466666666666666674],"xyz":[0.288027055332743587,0.153154970022776588,0.188928565046910718],"hpluv":[349.514816334356908,281.289018816444,46.0633224094211542],"hsluv":[349.514816334356908,90.2475430222303174,46.0633224094211542]},"#cc2288":{"lch":[46.6595045299101443,98.2790088680822294,341.330158110485115],"luv":[46.6595045299101443,93.107459692013677,-31.4605234189234864],"rgb":[0.8,0.133333333333333331,0.533333333333333326],"xyz":[0.299167472434687387,0.157611136863554185,0.247601428450482886],"hpluv":[341.330158110485115,267.276005324070297,46.6595045299101443],"hsluv":[341.330158110485115,90.9748001704168,46.6595045299101443]},"#cc2299":{"lch":[47.3441166442187154,96.727251962869147,332.467163788405],"luv":[47.3441166442187154,85.772509513995189,-44.7128380217581167],"rgb":[0.8,0.133333333333333331,0.6],"xyz":[0.312224436543760087,0.162833922507183343,0.31636810609160082],"hpluv":[332.467163788405,259.252025571181889,47.3441166442187154],"hsluv":[332.467163788405,91.7002075152857259,47.3441166442187154]},"#cc22aa":{"lch":[48.1156936783416285,97.7076198445846131,323.544141865814368],"luv":[48.1156936783416285,78.5876931080813534,-58.0581903579838254],"rgb":[0.8,0.133333333333333331,0.66666666666666663],"xyz":[0.327282129509012643,0.168856999693284437,0.395671955708599421],"hpluv":[323.544141865814368,257.680176436907345,48.1156936783416285],"hsluv":[323.544141865814368,92.4042695013683328,48.1156936783416285]},"#cc22bb":{"lch":[48.9718390817589295,101.100583268181566,315.160199675634601],"luv":[48.9718390817589295,71.6885121422158846,-71.2887450022924867],"rgb":[0.8,0.133333333333333331,0.733333333333333282],"xyz":[0.344419721616349317,0.175712036536219196,0.485929940807241167],"hpluv":[315.160199675634601,261.96699229126267,48.9718390817589295],"hsluv":[315.160199675634601,93.0730408422972602,48.9718390817589295]},"#cc22cc":{"lch":[49.9093929354593513,106.520702596514482,307.715012949243658],"luv":[49.9093929354593513,65.1623716831421405,-84.2646153393173876],"rgb":[0.8,0.133333333333333331,0.8],"xyz":[0.363712097060071,0.183428986713708,0.587536451477511323],"hpluv":[307.715012949243658,270.826440261226253,49.9093929354593513],"hsluv":[307.715012949243658,93.6976999618693327,49.9093929354593513]},"#cc22dd":{"lch":[50.9245991417877377,113.480326695625976,301.360030221234524],"luv":[50.9245991417877377,59.0567580516805819,-96.9024451465042347],"rgb":[0.8,0.133333333333333331,0.866666666666666696],"xyz":[0.385230422610704615,0.192036316933961532,0.700866299377517321],"hpluv":[301.360030221234524,282.769318292038,50.9245991417877377],"hsluv":[301.360030221234524,94.2736696463096848,50.9245991417877377]},"#cc22ee":{"lch":[52.0132654143591964,121.518329969744158,296.062236941936249],"luv":[52.0132654143591964,53.3887372455597244,-109.162022947361166],"rgb":[0.8,0.133333333333333331,0.933333333333333348],"xyz":[0.409042602876879324,0.201561189040431576,0.826277115446040544],"hpluv":[296.062236941936249,296.460610812118318,52.0132654143591964],"hsluv":[296.062236941936249,94.7995997265514,52.0132654143591964]},"#cc22ff":{"lch":[53.170910599170611,130.261070707018604,291.695402941657903],"luv":[53.170910599170611,48.1538976563848422,-121.033667556747687],"rgb":[0.8,0.133333333333333331,1],"xyz":[0.435213651286710745,0.212029608404364273,0.964111303737822389],"hpluv":[291.695402941657903,310.870757963074425,53.170910599170611],"hsluv":[291.695402941657903,99.9999999999990621,53.170910599170611]},"#cc3300":{"lch":[45.9167915379707807,127.686226573765651,16.3911473443809399],"luv":[45.9167915379707807,122.496750231663356,36.0321889333482446],"rgb":[0.8,0.2,0],"xyz":[0.260850584973891519,0.15207273722165307,0.0156183921844992128],"hpluv":[16.3911473443809399,352.867650162608584,45.9167915379707807],"hsluv":[16.3911473443809399,100.000000000002288,45.9167915379707807]},"#cc3311":{"lch":[45.9716631772740811,126.14350976506573,15.6923563051461095],"luv":[45.9716631772740811,121.44186843726601,34.118289029712578],"rgb":[0.8,0.2,0.0666666666666666657],"xyz":[0.261862250473528624,0.152477403421507923,0.020946497149254846],"hpluv":[15.6923563051461095,348.188177538365835,45.9716631772740811],"hsluv":[15.6923563051461095,95.8756509753329595,45.9716631772740811]},"#cc3322":{"lch":[46.0731243265426613,123.399991281457972,14.3806932854006604],"luv":[46.0731243265426613,119.533487768482047,30.6480529588105668],"rgb":[0.8,0.2,0.133333333333333331],"xyz":[0.263737608612005681,0.153227546676898752,0.0308233833452340386],"hpluv":[14.3806932854006604,339.865273437066321,46.0731243265426613],"hsluv":[14.3806932854006604,88.4197842587317524,46.0731243265426613]},"#cc3333":{"lch":[46.2394596481243951,119.199958247304309,12.1770506300617924],"luv":[46.2394596481243951,116.518014060345578,25.1432385661076303],"rgb":[0.8,0.2,0.2],"xyz":[0.266825359344463386,0.154462646969881851,0.0470855372028451818],"hpluv":[12.1770506300617924,327.11667224844831,46.2394596481243951],"hsluv":[12.1770506300617924,76.6535755019082,46.2394596481243951]},"#cc3344":{"lch":[46.4780522046582405,113.793717346871745,8.90746564227168669],"luv":[46.4780522046582405,112.421330819758609,17.6197186224449389],"rgb":[0.8,0.2,0.266666666666666663],"xyz":[0.271283354588682302,0.156245845067569444,0.0705643121557318204],"hpluv":[8.90746564227168669,310.677421508065,46.4780522046582405],"hsluv":[8.90746564227168669,77.4930753906613887,46.4780522046582405]},"#cc3355":{"lch":[46.7943405275181661,107.68493286266704,4.39945159143432907],"luv":[46.7943405275181661,107.367637754253522,8.26045572038872855],"rgb":[0.8,0.2,0.333333333333333315],"xyz":[0.277245768628044287,0.158630810683314277,0.101966359429705736],"hpluv":[4.39945159143432907,292.012160158640199,46.7943405275181661],"hsluv":[4.39945159143432907,78.5258346284665265,46.7943405275181661]},"#cc3366":{"lch":[47.192153202602185,101.584765682520938,358.514989280316684],"luv":[47.192153202602185,101.55064731932022,-2.63261235272558647],"rgb":[0.8,0.2,0.4],"xyz":[0.284830764401552472,0.161664808992717568,0.141914003836849684],"hpluv":[358.514989280316684,273.148057687163259,47.192153202602185],"hsluv":[358.514989280316684,79.7102211537212781,47.192153202602185]},"#cc3377":{"lch":[47.6738975277608859,96.3272258277819589,351.225603296168742],"luv":[47.6738975277608859,95.1998742335289876,-14.6941614798792699],"rgb":[0.8,0.2,0.466666666666666674],"xyz":[0.294144777421754378,0.165390414200798391,0.190967805743247593],"hpluv":[351.225603296168742,256.39391915093114,47.6738975277608859],"hsluv":[351.225603296168742,80.9972134637005894,47.6738975277608859]},"#cc3388":{"lch":[48.2406991607903279,92.7347249941698095,342.718318936463845],"luv":[48.2406991607903279,88.5482927213948301,-27.5486674064369161],"rgb":[0.8,0.2,0.533333333333333326],"xyz":[0.305285194523698178,0.169846581041576,0.24964066914681976],"hpluv":[342.718318936463845,243.93163202064531,48.2406991607903279],"hsluv":[342.718318936463845,82.3372641433758758,48.2406991607903279]},"#cc3399":{"lch":[48.8925304323200436,91.4400639314067405,333.463846826874658],"luv":[48.8925304323200436,81.8070942553503926,-40.8519843003490877],"rgb":[0.8,0.2,0.6],"xyz":[0.318342158632770933,0.175069366685205147,0.318407346787937695],"hpluv":[333.463846826874658,237.319449797121564,48.8925304323200436],"hsluv":[333.463846826874658,83.6856508008112,48.8925304323200436]},"#cc33aa":{"lch":[49.6283419748853873,92.7248127600779242,324.141487451800515],"luv":[49.6283419748853873,75.1503095778714254,-54.3168654447363792],"rgb":[0.8,0.2,0.66666666666666663],"xyz":[0.333399851598023433,0.181092443871306241,0.397711196404936296],"hpluv":[324.141487451800515,237.085790295602294,49.6283419748853873],"hsluv":[324.141487451800515,85.0057245198840263,49.6283419748853873]},"#cc33bb":{"lch":[50.4462014889725054,96.4744776262418355,315.414049480091705],"luv":[50.4462014889725054,68.7089492450233905,-67.7230029377097],"rgb":[0.8,0.2,0.733333333333333282],"xyz":[0.350537443705360108,0.187947480714241,0.487969181503578042],"hpluv":[315.414049480091705,242.674024226837219,50.4462014889725054],"hsluv":[315.414049480091705,86.2701296035756258,50.4462014889725054]},"#cc33cc":{"lch":[51.3434379695087273,102.286811532428814,307.715012949243771],"luv":[51.3434379695087273,62.5723551280607779,-80.915339628518268],"rgb":[0.8,0.2,0.8],"xyz":[0.369829819149081862,0.195664430891729801,0.589575692173848198],"hpluv":[307.715012949243771,252.798225898109365,51.3434379695087273],"hsluv":[307.715012949243771,87.4604868647498,51.3434379695087273]},"#cc33dd":{"lch":[52.3167871114961827,109.649949983538605,301.195256028086874],"luv":[52.3167871114961827,56.7938698017029751,-93.7953510806358],"rgb":[0.8,0.2,0.866666666666666696],"xyz":[0.39134814469971535,0.204271761111983335,0.702905540073854196],"hpluv":[301.195256028086874,265.954105752122757,52.3167871114961827],"hsluv":[301.195256028086874,88.5661577004671,52.3167871114961827]},"#cc33ee":{"lch":[53.3625327970638494,118.082474280319559,295.802769884900215],"luv":[53.3625327970638494,51.3983045372134626,-106.309383512755787],"rgb":[0.8,0.2,0.933333333333333348],"xyz":[0.415160324965890115,0.21379663321845338,0.828316356142377419],"hpluv":[295.802769884900215,280.794331636146467,53.3625327970638494],"hsluv":[295.802769884900215,89.5826266077864375,53.3625327970638494]},"#cc33ff":{"lch":[54.4766398815527566,127.197777570935344,291.389330811727291],"luv":[54.4766398815527566,46.3894624378335,-118.436870921660102],"rgb":[0.8,0.2,1],"xyz":[0.441331373375721481,0.224265052582386076,0.966150544434159264],"hpluv":[291.389330811727291,296.284230666095709,54.4766398815527566],"hsluv":[291.389330811727291,99.9999999999990195,54.4766398815527566]},"#cc4400":{"lch":[48.2269914221542848,118.435883841274119,19.7039935064818295],"luv":[48.2269914221542848,111.501113106022,39.9319465764175447],"rgb":[0.8,0.266666666666666663,0],"xyz":[0.26968315545685756,0.1697378781875854,0.0185625823454878096],"hpluv":[19.7039935064818295,311.625122342549162,48.2269914221542848],"hsluv":[19.7039935064818295,100.000000000002174,48.2269914221542848]},"#cc4411":{"lch":[48.2779913635395,116.996103035931512,19.0066631306561966],"luv":[48.2779913635395,110.617558299276112,38.1030697123021],"rgb":[0.8,0.266666666666666663,0.0666666666666666657],"xyz":[0.270694820956494664,0.170142544387440253,0.0238906873102434428],"hpluv":[19.0066631306561966,307.511619232155283,48.2779913635395],"hsluv":[19.0066631306561966,96.278384876640132,48.2779913635395]},"#cc4422":{"lch":[48.3723181772035389,114.428966114904512,17.6946931608209894],"luv":[48.3723181772035389,109.015290220227484,34.7800917814421453],"rgb":[0.8,0.266666666666666663,0.133333333333333331],"xyz":[0.272570179094971721,0.170892687642831081,0.0337675735062226354],"hpluv":[17.6946931608209894,300.177682052924467,48.3723181772035389],"hsluv":[17.6946931608209894,89.5341066932624869,48.3723181772035389]},"#cc4433":{"lch":[48.5270263662828114,110.48209503335984,15.4815426750504042],"luv":[48.5270263662828114,106.473417017787412,29.4907577304601034],"rgb":[0.8,0.266666666666666663,0.2],"xyz":[0.275657929827429427,0.17212778793581418,0.0500297273638337786],"hpluv":[15.4815426750504042,288.900004133964501,48.5270263662828114],"hsluv":[15.4815426750504042,78.8475327486048,48.5270263662828114]},"#cc4444":{"lch":[48.7490888960709725,105.371058014361893,12.1770506300618457],"luv":[48.7490888960709725,103.000257716521162,22.2262632351064191],"rgb":[0.8,0.266666666666666663,0.266666666666666663],"xyz":[0.280115925071648342,0.173910986033501774,0.0735085023167204171],"hpluv":[12.1770506300618457,274.28001464324592,48.7490888960709725],"hsluv":[12.1770506300618457,64.2723089184284788,48.7490888960709725]},"#cc4455":{"lch":[49.0437296069087,99.5540950311582691,7.58056168126664254],"luv":[49.0437296069087,98.6840273694228074,13.1331861946711772],"rgb":[0.8,0.266666666666666663,0.333333333333333315],"xyz":[0.286078339111010327,0.176295951649246607,0.104910549590694333],"hpluv":[7.58056168126664254,257.581676799067395,49.0437296069087],"hsluv":[7.58056168126664254,65.7689369270132858,49.0437296069087]},"#cc4466":{"lch":[49.4147368002801244,93.7049448509207679,1.51289058041819868],"luv":[49.4147368002801244,93.6722802728102835,2.47398423725391092],"rgb":[0.8,0.266666666666666663,0.4],"xyz":[0.293663334884518512,0.179329949958649898,0.14485819399783828],"hpluv":[1.51289058041819868,240.627550105868352,49.4147368002801244],"hsluv":[1.51289058041819868,67.500804726855,49.4147368002801244]},"#cc4477":{"lch":[49.8646356184384132,88.6490107187132566,353.900159994018],"luv":[49.8646356184384132,88.1471013723349586,-9.41995865499641383],"rgb":[0.8,0.266666666666666663,0.466666666666666674],"xyz":[0.302977347904720418,0.183055555166730721,0.19391199590423619],"hpluv":[353.900159994018,225.590377060975072,49.8646356184384132],"hsluv":[353.900159994018,69.4017616341687784,49.8646356184384132]},"#cc4488":{"lch":[50.3948096201307436,85.2405150759366279,344.907000147604322],"luv":[50.3948096201307436,82.3000967091543743,-22.1954835963269055],"rgb":[0.8,0.266666666666666663,0.533333333333333326],"xyz":[0.314117765006664218,0.187511722007508319,0.252584859307808385],"hpluv":[344.907000147604322,214.634525667930632,50.3948096201307436],"hsluv":[344.907000147604322,71.4025087995354824,50.3948096201307436]},"#cc4499":{"lch":[51.0056074652318046,84.1718897613591679,335.041688295241613],"luv":[51.0056074652318046,76.3115014820887581,-35.5170630478867793],"rgb":[0.8,0.266666666666666663,0.6],"xyz":[0.327174729115737,0.192734507651137477,0.321351536948926264],"hpluv":[335.041688295241613,209.40569084337892,51.0056074652318046],"hsluv":[335.041688295241613,73.4381222823911344,51.0056074652318046]},"#cc44aa":{"lch":[51.6964496814969152,85.7749410926589348,325.085448007895536],"luv":[51.6964496814969152,70.3360122964612913,-49.093644127128691],"rgb":[0.8,0.266666666666666663,0.66666666666666663],"xyz":[0.342232422080989473,0.198757584837238571,0.400655386565924865],"hpluv":[325.085448007895536,210.542141790665795,51.6964496814969152],"hsluv":[325.085448007895536,75.4531429469973602,51.6964496814969152]},"#cc44bb":{"lch":[52.465940673938249,89.9444778306290829,315.812454406659811],"luv":[52.465940673938249,64.4957791941851326,-62.692133145710109],"rgb":[0.8,0.266666666666666663,0.733333333333333282],"xyz":[0.359370014188326148,0.20561262168017333,0.490913371664566611],"hpluv":[315.812454406659811,217.538619181736436,52.465940673938249],"hsluv":[315.812454406659811,77.4040753157756143,52.465940673938249]},"#cc44cc":{"lch":[53.3119860408958175,96.2498903650287758,307.715012949243885],"luv":[53.3119860408958175,58.8793631430003828,-76.1397530279337502],"rgb":[0.8,0.266666666666666663,0.8],"xyz":[0.378662389632047902,0.213329571857662131,0.592519882334836767],"hpluv":[307.715012949243885,229.094523932317799,53.3119860408958175],"hsluv":[307.715012949243885,79.2597279113993,53.3119860408958175]},"#cc44dd":{"lch":[54.2319126329379486,104.138844540210442,300.941773361922515],"luv":[54.2319126329379486,53.5447276840333259,-89.31887303035586],"rgb":[0.8,0.266666666666666663,0.866666666666666696],"xyz":[0.40018071518268139,0.221936902077915665,0.705849730234842765],"hpluv":[300.941773361922515,243.66724889744043,54.2319126329379486],"hsluv":[300.941773361922515,81.0000946003390538,54.2319126329379486]},"#cc44ee":{"lch":[55.2225876682288401,113.096616320403683,295.407423092027],"luv":[55.2225876682288401,48.5243479249087528,-102.157879194837463],"rgb":[0.8,0.266666666666666663,0.933333333333333348],"xyz":[0.423992895448856155,0.23146177418438571,0.831260546303366],"hpluv":[295.407423092027,259.879597148300718,55.2225876682288401],"hsluv":[295.407423092027,86.8652077390175634,55.2225876682288401]},"#cc44ff":{"lch":[56.2805330741479537,122.715491745326418,290.92682559337851],"luv":[56.2805330741479537,43.8309487146615382,-114.62085259266739],"rgb":[0.8,0.266666666666666663,1],"xyz":[0.450163943858687521,0.241930193548318406,0.969094734595147833],"hpluv":[290.92682559337851,276.681751484143376,56.2805330741479537],"hsluv":[290.92682559337851,99.9999999999989768,56.2805330741479537]},"#cc5500":{"lch":[51.07852272981998,108.355754132896138,24.3337665629108457],"luv":[51.07852272981998,98.7294936728878838,44.6481414260866],"rgb":[0.8,0.333333333333333315,0],"xyz":[0.281496412171203525,0.193364391616277664,0.0225003345836030169],"hpluv":[24.3337665629108457,269.186315008697875,51.07852272981998],"hsluv":[24.3337665629108457,100.000000000002217,51.07852272981998]},"#cc5511":{"lch":[51.1252833166066,107.003417336388864,23.6474066829241423],"luv":[51.1252833166066,98.0184651549503201,42.91983003616388],"rgb":[0.8,0.333333333333333315,0.0666666666666666657],"xyz":[0.282508077670840629,0.193769057816132517,0.0278284395483586466],"hpluv":[23.6474066829241423,265.583595811902,51.1252833166066],"hsluv":[23.6474066829241423,96.7082849697218307,51.1252833166066]},"#cc5522":{"lch":[51.2117930688627467,104.583581473170284,22.351909846807331],"luv":[51.2117930688627467,96.7257518395109486,39.7725337995530808],"rgb":[0.8,0.333333333333333315,0.133333333333333331],"xyz":[0.284383435809317686,0.194519201071523345,0.0377053257443378462],"hpluv":[22.351909846807331,259.139045481141636,51.2117930688627467],"hsluv":[22.351909846807331,90.7274756498525079,51.2117930688627467]},"#cc5533":{"lch":[51.3537468781662625,100.840694749975015,20.1540565840537802],"luv":[51.3537468781662625,94.6661789932146718,34.7442120716858369],"rgb":[0.8,0.333333333333333315,0.2],"xyz":[0.287471186541775392,0.195754301364506444,0.0539674796019489894],"hpluv":[20.1540565840537802,249.174169543579183,51.3537468781662625],"hsluv":[20.1540565840537802,81.2092815218714321,51.3537468781662625]},"#cc5544":{"lch":[51.5576456995760424,95.9504499860225764,16.842752904303623],"luv":[51.5576456995760424,91.8345174188591074,27.8012636936791502],"rgb":[0.8,0.333333333333333315,0.266666666666666663],"xyz":[0.291929181785994307,0.197537499462194038,0.0774462545548356279],"hpluv":[16.842752904303623,236.152889903020736,51.5576456995760424],"hsluv":[16.842752904303623,68.1451659970290109,51.5576456995760424]},"#cc5555":{"lch":[51.8284441386287114,90.3192908744292851,12.1770506300618919],"luv":[51.8284441386287114,88.2871484081680364,19.0513445723360242],"rgb":[0.8,0.333333333333333315,0.333333333333333315],"xyz":[0.297891595825356292,0.199922465077938871,0.108848301828809529],"hpluv":[12.1770506300618919,221.132040760117775,51.8284441386287114],"hsluv":[12.1770506300618919,51.8180912815801,51.8284441386287114]},"#cc5566":{"lch":[52.1698415772242612,84.57836719340618,5.91246023067467696],"luv":[52.1698415772242612,84.1284474176031836,8.71232071300305577],"rgb":[0.8,0.333333333333333315,0.4],"xyz":[0.305476591598864478,0.202956463387342162,0.148795946235953491],"hpluv":[5.91246023067467696,205.721226704565879,52.1698415772242612],"hsluv":[5.91246023067467696,54.0130370973951415,52.1698415772242612]},"#cc5577":{"lch":[52.5844387621358607,79.5477054283049654,357.892334615122479],"luv":[52.5844387621358607,79.493890006545314,-2.92555815796844554],"rgb":[0.8,0.333333333333333315,0.466666666666666674],"xyz":[0.314790604619066383,0.206682068595422985,0.1978497481423514],"hpluv":[357.892334615122479,191.959557587962337,52.5844387621358607],"hsluv":[357.892334615122479,56.4492590331968884,52.5844387621358607]},"#cc5588":{"lch":[53.0738428910491962,76.1348505840982,348.222799824086337],"luv":[53.0738428910491962,74.5321119975331072,-15.5396188708133902],"rgb":[0.8,0.333333333333333315,0.533333333333333326],"xyz":[0.325931021721010183,0.211138235436200583,0.256522611545923596],"hpluv":[348.222799824086337,182.029716109510787,53.0738428910491962],"hsluv":[348.222799824086337,59.0443947768825339,53.0738428910491962]},"#cc5599":{"lch":[53.6387547547300443,75.1322702050955655,337.451566852479516],"luv":[53.6387547547300443,69.3888374020903314,-28.8105409556599774],"rgb":[0.8,0.333333333333333315,0.6],"xyz":[0.338987985830082938,0.216361021079829741,0.325289289187041475],"hpluv":[337.451566852479516,177.740808472615271,53.6387547547300443],"hsluv":[337.451566852479516,61.7180151219793274,53.6387547547300443]},"#cc55aa":{"lch":[54.2790527162633651,76.9604755372169507,326.525055670409472],"luv":[54.2790527162633651,64.1948187783047359,-42.449264268479169],"rgb":[0.8,0.333333333333333315,0.66666666666666663],"xyz":[0.354045678795335439,0.222384098265930835,0.404593138804040076],"hpluv":[326.525055670409472,179.918080614224607,54.2790527162633651],"hsluv":[326.525055670409472,64.3982563598392517,54.2790527162633651]},"#cc55bb":{"lch":[54.9938795911038767,81.534325182187132,316.414019967357433],"luv":[54.9938795911038767,59.0586208757266817,-56.2132144888709888],"rgb":[0.8,0.333333333333333315,0.733333333333333282],"xyz":[0.371183270902672113,0.229239135108865594,0.494851123902681822],"hpluv":[316.414019967357433,188.133202867989326,54.9938795911038767],"hsluv":[316.414019967357433,67.0257727218245378,54.9938795911038767]},"#cc55cc":{"lch":[55.7817339145568667,88.3780574248019,307.715012949244169],"luv":[55.7817339145568667,54.0638926159085145,-69.9126351198200382],"rgb":[0.8,0.333333333333333315,0.8],"xyz":[0.390475646346393868,0.236956085286354395,0.596457634572952],"hpluv":[307.715012949244169,201.044301715196383,55.7817339145568667],"hsluv":[307.715012949244169,69.5552053299685156,55.7817339145568667]},"#cc55dd":{"lch":[56.6405645837994882,96.8744721490496232,300.570417552325068],"luv":[56.6405645837994882,49.2700598324241312,-83.4093793183137],"rgb":[0.8,0.333333333333333315,0.866666666666666696],"xyz":[0.411993971897027356,0.245563415506607929,0.709787482472958],"hpluv":[300.570417552325068,217.030665421015726,56.6405645837994882],"hsluv":[300.570417552325068,72.1703256475756234,56.6405645837994882]},"#cc55ee":{"lch":[57.5678665910353118,106.457154357221242,294.836459829444038],"luv":[57.5678665910353118,44.7151619549172707,-96.6109724885468],"rgb":[0.8,0.333333333333333315,0.933333333333333348],"xyz":[0.435806152163202121,0.255088287613077946,0.835198298541481199],"hpluv":[294.836459829444038,234.657286550118499,57.5678665910353118],"hsluv":[294.836459829444038,85.8995510844284809,57.5678665910353118]},"#cc55ff":{"lch":[58.560775097021633,116.686665261471418,290.266986003053091],"luv":[58.560775097021633,40.4196983751927874,-109.462440284789551],"rgb":[0.8,0.333333333333333315,1],"xyz":[0.461977200573033486,0.26555670697701067,0.973032486833263],"hpluv":[290.266986003053091,252.844632524376181,58.560775097021633],"hsluv":[290.266986003053091,99.9999999999988,58.560775097021633]},"#cc6600":{"lch":[54.388060759003551,98.5584029412379579,30.482787603130209],"luv":[54.388060759003551,84.9358174587045482,49.9966569177284157],"rgb":[0.8,0.4,0],"xyz":[0.29652446987705,0.223420507027971,0.0275096871522183678],"hpluv":[30.482787603130209,229.947880001204965,54.388060759003551],"hsluv":[30.482787603130209,100.000000000002359,54.388060759003551]},"#cc6611":{"lch":[54.430531479182676,97.2669366851907711,29.8266301777559697],"luv":[54.430531479182676,84.3824110244092367,48.3783596438383583],"rgb":[0.8,0.4,0.0666666666666666657],"xyz":[0.297536135376687105,0.223825173227825858,0.032837792116974],"hpluv":[29.8266301777559697,226.757672191171366,54.430531479182676],"hsluv":[29.8266301777559697,97.1300271864182463,54.430531479182676]},"#cc6622":{"lch":[54.5091256699603548,94.945229062596681,28.5830621108902889],"luv":[54.5091256699603548,83.3737269438019695,45.4248629854764],"rgb":[0.8,0.4,0.133333333333333331],"xyz":[0.299411493515164162,0.224575316483216686,0.0427146783129532],"hpluv":[28.5830621108902889,221.025945543219876,54.5091256699603548],"hsluv":[28.5830621108902889,91.902111940908739,54.5091256699603548]},"#cc6633":{"lch":[54.6381494647888388,91.324965774397,26.4577509745500876],"luv":[54.6381494647888388,81.7598754062496624,40.688722605278663],"rgb":[0.8,0.4,0.2],"xyz":[0.302499244247621868,0.225810416776199785,0.0589768321705643403],"hpluv":[26.4577509745500876,212.096187894217309,54.6381494647888388],"hsluv":[26.4577509745500876,83.5463344335908289,54.6381494647888388]},"#cc6644":{"lch":[54.8236025158742137,86.5353782352002,23.2174871910251],"luv":[54.8236025158742137,79.5273159773273903,34.1141861950638798],"rgb":[0.8,0.4,0.266666666666666663],"xyz":[0.306957239491840783,0.227593614873887379,0.0824556071234509858],"hpluv":[23.2174871910251,200.292852977212362,54.8236025158742137],"hsluv":[23.2174871910251,72.0055590941951635,54.8236025158742137]},"#cc6655":{"lch":[55.0701314820163077,80.921365039871,18.5706632184066578],"luv":[55.0701314820163077,76.7079190692017505,25.7713498286149552],"rgb":[0.8,0.4,0.333333333333333315],"xyz":[0.312919653531202768,0.229978580489632212,0.113857654397424887],"hpluv":[18.5706632184066578,186.460314881725708,55.0701314820163077],"hsluv":[18.5706632184066578,57.463707489477386,55.0701314820163077]},"#cc6666":{"lch":[55.3812986167643686,75.0592421503045841,12.1770506300619576],"luv":[55.3812986167643686,73.3704437553848834,15.8324923911544637],"rgb":[0.8,0.4,0.4],"xyz":[0.320504649304710953,0.233012578799035502,0.153805298804568835],"hpluv":[12.1770506300619576,171.980959079196282,55.3812986167643686],"hsluv":[12.1770506300619576,45.9214429163451925,55.3812986167643686]},"#cc6677":{"lch":[55.7597240294908403,69.7578535305897702,3.7339069954147126],"luv":[55.7597240294908403,69.6097753289024,4.54283037928401079],"rgb":[0.8,0.4,0.466666666666666674],"xyz":[0.329818662324912859,0.236738184007116326,0.202859100710966744],"hpluv":[3.7339069954147126,158.749300244695775,55.7597240294908403],"hsluv":[3.7339069954147126,47.4001946683844935,55.7597240294908403]},"#cc6688":{"lch":[56.2071770412836855,65.9988703650454198,353.20230012342131],"luv":[56.2071770412836855,65.534915505775615,-7.81189727997758432],"rgb":[0.8,0.4,0.533333333333333326],"xyz":[0.340959079426856659,0.241194350847893924,0.26153196411453894],"hpluv":[353.20230012342131,148.999240608904586,56.2071770412836855],"hsluv":[353.20230012342131,48.9818497710332537,56.2071770412836855]},"#cc6699":{"lch":[56.7246474757154573,64.7364860461136544,341.13073016495332],"luv":[56.7246474757154573,61.2574795353059756,-20.9364234428957907],"rgb":[0.8,0.4,0.6],"xyz":[0.354016043535929414,0.246417136491523081,0.330298641755656819],"hpluv":[341.13073016495332,144.81603174775961,56.7246474757154573],"hsluv":[341.13073016495332,50.615240188358726,56.7246474757154573]},"#cc66aa":{"lch":[57.3124110050500661,66.5536753014576874,328.724652687595039],"luv":[57.3124110050500661,56.882247269492467,-34.5514347271451925],"rgb":[0.8,0.4,0.66666666666666663],"xyz":[0.369073736501181915,0.252440213677624203,0.40960249137265542],"hpluv":[328.724652687595039,147.354258527000582,57.3124110050500661],"hsluv":[328.724652687595039,52.5782983823555057,57.3124110050500661]},"#cc66bb":{"lch":[57.9700950113726634,71.4140361316817831,317.320615294889421],"luv":[57.9700950113726634,52.5006394421278628,-48.4112323204526405],"rgb":[0.8,0.4,0.733333333333333282],"xyz":[0.386211328608518589,0.259295250520558962,0.499860476471297166],"hpluv":[317.320615294889421,156.321564636453559,57.9700950113726634],"hsluv":[317.320615294889421,55.7867325729046044,57.9700950113726634]},"#cc66cc":{"lch":[58.6967474031167882,78.7715159072838844,307.71501294924451],"luv":[58.6967474031167882,48.1872412824568599,-62.3132529717215391],"rgb":[0.8,0.4,0.8],"xyz":[0.405503704052240344,0.267012200698047764,0.601466987141567322],"hpluv":[307.71501294924451,170.292097080892688,58.6967474031167882],"hsluv":[307.71501294924451,58.9158791245518429,58.6967474031167882]},"#cc66dd":{"lch":[59.4909085631812928,87.9045601549668589,300.035118747227784],"luv":[59.4909085631812928,43.9989332886277964,-76.1006278916348151],"rgb":[0.8,0.4,0.866666666666666696],"xyz":[0.427022029602873832,0.27561953091830127,0.71479683504157332],"hpluv":[300.035118747227784,187.499506963343748,59.4909085631812928],"hsluv":[300.035118747227784,69.8010448945604907,59.4909085631812928]},"#cc66ee":{"lch":[60.3506853352839272,98.1678970647401314,294.030303780460372],"luv":[60.3506853352839272,39.9759075841908498,-89.6597057040320919],"rgb":[0.8,0.4,0.933333333333333348],"xyz":[0.450834209869048597,0.285144403024771287,0.840207651110096543],"hpluv":[294.030303780460372,206.408039079415715,60.3506853352839272],"hsluv":[294.030303780460372,84.6650997716967169,60.3506853352839272]},"#cc66ff":{"lch":[61.2738253236974799,109.076950193692937,289.351384827957531],"luv":[61.2738253236974799,36.143813792667018,-102.914555763887847],"rgb":[0.8,0.4,1],"xyz":[0.477005258278879962,0.295612822388704,0.978041839401878388],"hpluv":[289.351384827957531,225.890163025573315,61.2738253236974799],"hsluv":[289.351384827957531,99.9999999999987,61.2738253236974799]},"#cc7700":{"lch":[58.0681687130694684,90.1274111260576,38.2527636780657616],"luv":[58.0681687130694684,70.775890411238,55.8007488550273862],"rgb":[0.8,0.466666666666666674,0],"xyz":[0.314978207930467602,0.260327983134806762,0.0336609331700240683],"hpluv":[38.2527636780657616,196.95095583694345,58.0681687130694684],"hsluv":[38.2527636780657616,100.00000000000226,58.0681687130694684]},"#cc7711":{"lch":[58.1065272060428,88.8714225311590837,37.658223554494576],"luv":[58.1065272060428,70.356768805075,54.2959927252558288],"rgb":[0.8,0.466666666666666674,0.0666666666666666657],"xyz":[0.315989873430104706,0.260732649334661615,0.0389890381347797],"hpluv":[37.658223554494576,194.078102813960953,58.1065272060428],"hsluv":[37.658223554494576,97.5201736027742925,58.1065272060428]},"#cc7722":{"lch":[58.1775287784180364,86.6008188207648573,36.5262538454337786],"luv":[58.1775287784180364,69.5910513475594286,51.5440335321973748],"rgb":[0.8,0.466666666666666674,0.133333333333333331],"xyz":[0.317865231568581763,0.261482792590052415,0.0488659243307589],"hpluv":[36.5262538454337786,188.888733728089306,58.1775287784180364],"hsluv":[36.5262538454337786,92.9922153048462832,58.1775287784180364]},"#cc7733":{"lch":[58.2941365993826111,83.0249283524691606,34.5753600294232513],"luv":[58.2941365993826111,68.3611064237300781,47.1157920070976459],"rgb":[0.8,0.466666666666666674,0.2],"xyz":[0.320952982301039469,0.262717892883035542,0.0651280781883700477],"hpluv":[34.5753600294232513,180.726967614303447,58.2941365993826111],"hsluv":[34.5753600294232513,85.7262720770138458,58.2941365993826111]},"#cc7744":{"lch":[58.4618482438389577,78.2181767747613321,31.5590767862408974],"luv":[58.4618482438389577,66.6497843857434447,40.9376284034837923],"rgb":[0.8,0.466666666666666674,0.266666666666666663],"xyz":[0.325410977545258384,0.264501090980723108,0.0886068531412566862],"hpluv":[31.5590767862408974,169.775287201810244,58.4618482438389577],"hsluv":[31.5590767862408974,75.6318325574838,58.4618482438389577]},"#cc7755":{"lch":[58.6849825995062133,72.4480337937475,27.1381330463907204],"luv":[58.6849825995062133,64.4721877935720187,33.0462494345479811],"rgb":[0.8,0.466666666666666674,0.333333333333333315],"xyz":[0.331373391584620369,0.266886056596467969,0.120008900415230588],"hpluv":[27.1381330463907204,156.653084219512607,58.6849825995062133],"hsluv":[27.1381330463907204,62.8141161752895059,58.6849825995062133]},"#cc7766":{"lch":[58.9669266929607829,66.2083874258113667,20.8554290651987451],"luv":[58.9669266929607829,61.8705265372573407,23.5709251309504673],"rgb":[0.8,0.466666666666666674,0.4],"xyz":[0.338958387358128554,0.269920054905871287,0.159956544822374536],"hpluv":[20.8554290651987451,142.476698671576116,58.9669266929607829],"hsluv":[20.8554290651987451,47.542957476979069,58.9669266929607829]},"#cc7777":{"lch":[59.3102652975897229,60.2635194006596251,12.177050630062082],"luv":[59.3102652975897229,58.907617956407762,12.7115820123061383],"rgb":[0.8,0.466666666666666674,0.466666666666666674],"xyz":[0.34827240037833046,0.273645660113952083,0.209010346728772445],"hpluv":[12.177050630062082,128.932959302114057,59.3102652975897229],"hsluv":[12.177050630062082,43.5373021749198443,59.3102652975897229]},"#cc7788":{"lch":[59.7168613687891963,55.6638868177661834,0.734433949810619269],"luv":[59.7168613687891963,55.6593138534775917,0.713496335773026069],"rgb":[0.8,0.466666666666666674,0.533333333333333326],"xyz":[0.35941281748027426,0.278101826954729681,0.26768321013234464],"hpluv":[0.734433949810619269,118.281243349182901,59.7168613687891963],"hsluv":[0.734433949810619269,45.0130000154657779,59.7168613687891963]},"#cc7799":{"lch":[60.187915321807921,53.6038783156568073,346.890122071781263],"luv":[60.187915321807921,52.2067938730354371,-12.1583898596044406],"rgb":[0.8,0.466666666666666674,0.6],"xyz":[0.37246978158934696,0.283324612598358838,0.336449887773462519],"hpluv":[346.890122071781263,113.012436406344946,60.187915321807921],"hsluv":[346.890122071781263,46.5549497102544,60.187915321807921]},"#cc77aa":{"lch":[60.7240163061688349,54.9761438743297148,332.197464335395125],"luv":[60.7240163061688349,48.6297161920954863,-25.6422912074417866],"rgb":[0.8,0.466666666666666674,0.66666666666666663],"xyz":[0.387527474554599516,0.28934768978445996,0.41575373739046112],"hpluv":[332.197464335395125,114.882297594683308,60.7240163061688349],"hsluv":[332.197464335395125,48.1189262345266471,60.7240163061688349]},"#cc77bb":{"lch":[61.3251919150652043,59.875823087291181,318.726648244723037],"luv":[61.3251919150652043,45.0009333565193046,-39.4972174643062743],"rgb":[0.8,0.466666666666666674,0.733333333333333282],"xyz":[0.40466506666193619,0.296202726627394719,0.506011722489102866],"hpluv":[318.726648244723037,123.894465684476771,61.3251919150652043],"hsluv":[318.726648244723037,49.6642191709372156,61.3251919150652043]},"#cc77cc":{"lch":[61.9909592768387228,67.6487625915650881,307.715012949244965],"luv":[61.9909592768387228,41.3830711255614219,-53.514451360232222],"rgb":[0.8,0.466666666666666674,0.8],"xyz":[0.423957442105657889,0.303919676804883521,0.607618233159373],"hpluv":[307.715012949244965,138.474825543749517,61.9909592768387228],"hsluv":[307.715012949244965,51.1553628289834066,61.9909592768387228]},"#cc77dd":{"lch":[62.7203784873954362,77.3966796673740305,299.257833182927357],"luv":[62.7203784873954362,37.8268934727942252,-67.5231231041040161],"rgb":[0.8,0.466666666666666674,0.866666666666666696],"xyz":[0.445475767656291488,0.312527007025137,0.720948081059379],"hpluv":[299.257833182927357,156.586020071329443,62.7203784873954362],"hsluv":[299.257833182927357,66.8390608629672158,62.7203784873954362]},"#cc77ee":{"lch":[63.5121081687847351,88.3507940057556453,292.894169444170245],"luv":[63.5121081687847351,34.371127600373157,-81.3909601179783],"rgb":[0.8,0.466666666666666674,0.933333333333333348],"xyz":[0.469287947922466198,0.322051879131607044,0.846358897127902243],"hpluv":[292.894169444170245,176.519730115921618,63.5121081687847351],"hsluv":[292.894169444170245,83.1130682001540322,63.5121081687847351]},"#cc77ff":{"lch":[64.3644622692190467,99.9639900757921112,288.092077643344339],"luv":[64.3644622692190467,31.0433170684360782,-95.0216384686225553],"rgb":[0.8,0.466666666666666674,1],"xyz":[0.495458996332297619,0.332520298495539768,0.984193085419684088],"hpluv":[288.092077643344339,197.077372703744913,64.3644622692190467],"hsluv":[288.092077643344339,99.9999999999984794,64.3644622692190467]},"#cc8800":{"lch":[62.03823759594124,83.9779445354575813,47.4964941193052752],"luv":[62.03823759594124,56.738465406715342,61.9115636346826221],"rgb":[0.8,0.533333333333333326,0],"xyz":[0.337050577655438111,0.304472722584748334,0.0410183897450140181],"hpluv":[47.4964941193052752,171.769129739761638,62.03823759594124],"hsluv":[47.4964941193052752,100.000000000002245,62.03823759594124]},"#cc8811":{"lch":[62.0727951053461879,82.7448035916202542,47.0033697453910904],"luv":[62.0727951053461879,56.4282611354359744,60.519037225048919],"rgb":[0.8,0.533333333333333326,0.0666666666666666657],"xyz":[0.338062243155075215,0.304877388784603187,0.0463464947097696478],"hpluv":[47.0033697453910904,169.152629782786704,62.0727951053461879],"hsluv":[47.0033697453910904,97.8669953021426,62.0727951053461879]},"#cc8822":{"lch":[62.1367747194074127,80.5023095814055836,46.0605806208152728],"luv":[62.1367747194074127,55.8603434591127268,57.9676105818622389],"rgb":[0.8,0.533333333333333326,0.133333333333333331],"xyz":[0.339937601293552272,0.305627532039994,0.0562233809057488473],"hpluv":[46.0605806208152728,164.398919884807611,62.1367747194074127],"hsluv":[46.0605806208152728,93.9640765124603,62.1367747194074127]},"#cc8833":{"lch":[62.2418885518498541,76.9329948636363241,44.4230175211057343],"luv":[62.2418885518498541,54.9448944756850963,53.8492736231801246],"rgb":[0.8,0.533333333333333326,0.2],"xyz":[0.34302535202601,0.306862632332977114,0.0724855347633599906],"hpluv":[44.4230175211057343,156.844467463147254,62.2418885518498541],"hsluv":[44.4230175211057343,87.678806867525978,62.2418885518498541]},"#cc8844":{"lch":[62.3931521103864668,72.0506908450526424,41.8566920827827929],"luv":[62.3931521103864668,53.6645163812677168,48.0772475586321661],"rgb":[0.8,0.533333333333333326,0.266666666666666663],"xyz":[0.347483347270228893,0.30864583043066468,0.0959643097162466291],"hpluv":[41.8566920827827929,146.534723453778,62.3931521103864668],"hsluv":[41.8566920827827929,78.900857077449,62.3931521103864668]},"#cc8855":{"lch":[62.5945538889838673,66.028576146577123,38.0101307109045408],"luv":[62.5945538889838673,52.0240395147187513,40.6604498316892062],"rgb":[0.8,0.533333333333333326,0.333333333333333315],"xyz":[0.353445761309590878,0.311030796046409541,0.127366356990220531],"hpluv":[38.0101307109045408,133.855034432196135,62.5945538889838673],"hsluv":[38.0101307109045408,67.6770944211119314,62.5945538889838673]},"#cc8866":{"lch":[62.8492816845599265,59.2369010326618337,32.3420191431213624],"luv":[62.8492816845599265,50.047464385327217,31.6900891849924626],"rgb":[0.8,0.533333333333333326,0.4],"xyz":[0.361030757083099063,0.31406479435581286,0.167314001397364492],"hpluv":[32.3420191431213624,119.60004374597824,62.8492816845599265],"hsluv":[32.3420191431213624,54.1901780257147436,62.8492816845599265]},"#cc8877":{"lch":[63.1598410661450771,52.3169991415742,24.053169540805424],"luv":[63.1598410661450771,47.7741895619322392,21.3235834436907119],"rgb":[0.8,0.533333333333333326,0.466666666666666674],"xyz":[0.370344770103300969,0.317790399563893655,0.216367803303762402],"hpluv":[24.053169540805424,105.109295035123296,63.1598410661450771],"hsluv":[24.053169540805424,38.7316682482548558,63.1598410661450771]},"#cc8888":{"lch":[63.5281271999152182,46.2961098245983322,12.1770506300622312],"luv":[63.5281271999152182,45.2544686659219906,9.76539045078869528],"rgb":[0.8,0.533333333333333326,0.533333333333333326],"xyz":[0.381485187205244769,0.322246566404671253,0.275040666707334569],"hpluv":[12.1770506300622312,92.4736018048895403,63.5281271999152182],"hsluv":[12.1770506300622312,40.0703189706204199,63.5281271999152182]},"#cc8899":{"lch":[63.9554753143552119,42.6335463086933615,356.296984030050055],"luv":[63.9554753143552119,42.5445368433351,-2.7534806412255004],"rgb":[0.8,0.533333333333333326,0.6],"xyz":[0.394542151314317469,0.327469352048300411,0.343807344348452504],"hpluv":[356.296984030050055,84.588837176407921,63.9554753143552119],"hsluv":[356.296984030050055,41.5088242950414781,63.9554753143552119]},"#cc88aa":{"lch":[64.442701858069384,42.8028595258545153,338.056731442080661],"luv":[64.442701858069384,39.701977128446444,-15.9949303118941444],"rgb":[0.8,0.533333333333333326,0.66666666666666663],"xyz":[0.40959984427957,0.333492429234401533,0.423111193965451104],"hpluv":[338.056731442080661,84.28268641071584,64.442701858069384],"hsluv":[338.056731442080661,42.9831867606486924,64.442701858069384]},"#cc88bb":{"lch":[64.9901424985427099,47.2946673003310707,321.051918945199532],"luv":[64.9901424985427099,36.7818149859187784,-29.7301806484697622],"rgb":[0.8,0.533333333333333326,0.733333333333333282],"xyz":[0.426737436386906699,0.340347466077336291,0.513369179064092851],"hpluv":[321.051918945199532,92.3430068912496296,64.9901424985427099],"hsluv":[321.051918945199532,44.4548878388224864,64.9901424985427099]},"#cc88cc":{"lch":[65.5976900795525637,55.3077284551996158,307.715012949245761],"luv":[65.5976900795525637,33.8336367550969399,-43.751912538747959],"rgb":[0.8,0.533333333333333326,0.8],"xyz":[0.446029811830628398,0.348064416254825093,0.614975689734363],"hpluv":[307.715012949245761,106.988377595373095,65.5976900795525637],"hsluv":[307.715012949245761,45.8886814173124122,65.5976900795525637]},"#cc88dd":{"lch":[66.2648339334855905,65.6132669537387727,298.095232643272539],"luv":[66.2648339334855905,30.8998122908772608,-57.8817967994354774],"rgb":[0.8,0.533333333333333326,0.866666666666666696],"xyz":[0.467548137381262,0.356671746475078599,0.728305537634369],"hpluv":[298.095232643272539,125.645770778198369,66.2648339334855905],"hsluv":[298.095232643272539,63.1276078601331037,66.2648339334855905]},"#cc88ee":{"lch":[66.9907009061042,77.2337728548956193,291.267726386147558],"luv":[66.9907009061042,28.0147259973813227,-71.9738202174461463],"rgb":[0.8,0.533333333333333326,0.933333333333333348],"xyz":[0.491360317647436706,0.366196618581548616,0.853716353702892228],"hpluv":[291.267726386147558,146.295866424915545,66.9907009061042],"hsluv":[291.267726386147558,81.1585487563552874,66.9907009061042]},"#cc88ff":{"lch":[67.7740978167257,89.535143384050329,286.350196506734335],"luv":[67.7740978167257,25.2048126805589376,-85.914255618845857],"rgb":[0.8,0.533333333333333326,1],"xyz":[0.517531366057268127,0.37666503794548134,0.991550541994674073],"hpluv":[286.350196506734335,167.63670457649863,67.7740978167257],"hsluv":[286.350196506734335,99.9999999999982379,67.7740978167257]},"#cc9900":{"lch":[66.2294666531998217,80.7116888085701163,57.6888018595631422],"luv":[66.2294666531998217,43.1418134232290527,68.2140795209226383],"rgb":[0.8,0.6,0],"xyz":[0.362920178107905556,0.356211923489684,0.0496415898958362731],"hpluv":[57.6888018595631422,154.64094800189136,66.2294666531998217],"hsluv":[57.6888018595631422,100.000000000002331,66.2294666531998217]},"#cc9911":{"lch":[66.2605931548954459,79.5070460268624,57.3307205104302042],"luv":[66.2605931548954459,42.9170325725223805,66.9290570909725915],"rgb":[0.8,0.6,0.0666666666666666657],"xyz":[0.36393184360754266,0.356616589689538854,0.0549696948605919],"hpluv":[57.3307205104302042,152.261332222626407,66.2605931548954459],"hsluv":[57.3307205104302042,98.1673920986410877,66.2605931548954459]},"#cc9922":{"lch":[66.318231165714252,77.3048675578901339,56.6444543825244],"luv":[66.318231165714252,42.5047546114663533,64.5708013235236535],"rgb":[0.8,0.6,0.133333333333333331],"xyz":[0.365807201746019717,0.357366732944929655,0.0648465810565711],"hpluv":[56.6444543825244,147.915345655385721,66.318231165714252],"hsluv":[56.6444543825244,94.8079930897652901,66.318231165714252]},"#cc9933":{"lch":[66.4129558628457772,73.7662990604099207,55.446788144651876],"luv":[66.4129558628457772,41.8381333944198062,60.7539091017242114],"rgb":[0.8,0.6,0.2],"xyz":[0.368894952478477423,0.358601833237912782,0.0811087349141822456],"hpluv":[55.446788144651876,140.943324602767206,66.4129558628457772],"hsluv":[55.446788144651876,89.3812598244831804,66.4129558628457772]},"#cc9944":{"lch":[66.5493334014023361,68.8491039809152596,53.5533094328142383],"luv":[66.5493334014023361,40.9015039610359423,55.3829043360877122],"rgb":[0.8,0.6,0.266666666666666663],"xyz":[0.373352947722696338,0.360385031335600348,0.104587509867068884],"hpluv":[53.5533094328142383,131.278591794008349,66.5493334014023361],"hsluv":[53.5533094328142383,81.7675495661837459,66.5493334014023361]},"#cc9955":{"lch":[66.7310322275847341,62.6300376921671571,50.6698876242401539],"luv":[66.7310322275847341,39.6941340540006422,48.4447865412296466],"rgb":[0.8,0.6,0.333333333333333315],"xyz":[0.379315361762058323,0.362769996951345208,0.135989557141042799],"hpluv":[50.6698876242401539,119.095172229338388,66.7310322275847341],"hsluv":[50.6698876242401539,71.9728873324543912,66.7310322275847341]},"#cc9966":{"lch":[66.9610303820851,55.3290996264574488,46.2964172073191236],"luv":[66.9610303820851,38.2284030091626121,39.9987308404091877],"rgb":[0.8,0.6,0.4],"xyz":[0.386900357535566508,0.365803995260748527,0.175937201548186761],"hpluv":[46.2964172073191236,104.850571413887963,66.9610303820851],"hsluv":[46.2964172073191236,60.1139469393688586,66.9610303820851]},"#cc9977":{"lch":[67.2417240975963608,47.3725698769106316,39.5497292985384448],"luv":[67.2417240975963608,36.5276723895038842,30.1643751227811094],"rgb":[0.8,0.6,0.466666666666666674],"xyz":[0.396214370555768414,0.369529600468829322,0.22499100345458467],"hpluv":[39.5497292985384448,89.3979234879296598,67.2417240975963608],"hsluv":[39.5497292985384448,46.4000360859745484,67.2417240975963608]},"#cc9988":{"lch":[67.5749927230407508,39.5461637624335367,28.8927829606528306],"luv":[67.5749927230407508,34.6236706423047593,19.1076031876950658],"rgb":[0.8,0.6,0.533333333333333326],"xyz":[0.407354787657712214,0.37398576730960692,0.28366386685815681],"hpluv":[28.8927829606528306,74.2604675709266076,67.5749927230407508],"hsluv":[28.8927829606528306,33.7758353105824227,67.5749927230407508]},"#cc9999":{"lch":[67.962242737641,33.3028609095241,12.177050630062606],"luv":[67.962242737641,32.5535618700051401,7.02468179598591647],"rgb":[0.8,0.6,0.6],"xyz":[0.420411751766784914,0.379208552953236078,0.352430544499274745],"hpluv":[12.177050630062606,62.1803508213615217,67.962242737641],"hsluv":[12.177050630062606,35.0991912912463349,67.962242737641]},"#cc99aa":{"lch":[68.4044417972397838,30.9200145018949506,349.049331623372325],"luv":[68.4044417972397838,30.3569952347367966,-5.87368173427548168],"rgb":[0.8,0.6,0.66666666666666663],"xyz":[0.43546944473203747,0.3852316301393372,0.431734394116273346],"hpluv":[349.049331623372325,57.3580941092039609,68.4044417972397838],"hsluv":[349.049331623372325,36.4663034143199312,68.4044417972397838]},"#cc99bb":{"lch":[68.9021485343020856,34.1112448474386483,325.385883063702067],"luv":[68.9021485343020856,28.0734328763681233,-19.3767745401024669],"rgb":[0.8,0.6,0.733333333333333282],"xyz":[0.452607036839374144,0.392086666982271959,0.521992379214915],"hpluv":[325.385883063702067,62.8208966420876678,68.9021485343020856],"hsluv":[325.385883063702067,37.8410036888738404,68.9021485343020856]},"#cc99cc":{"lch":[69.4555411877739601,42.0770553751994854,307.715012949247],"luv":[69.4555411877739601,25.7399796927440505,-33.285613025220492],"rgb":[0.8,0.6,0.8],"xyz":[0.471899412283095843,0.39980361715976076,0.623598889885185192],"hpluv":[307.715012949247,76.8736967911951581,69.4555411877739601],"hsluv":[307.715012949247,39.1886552488513473,69.4555411877739601]},"#cc99dd":{"lch":[70.0644466506374215,52.8759829560521695,296.254085335195782],"luv":[70.0644466506374215,23.3898305690433475,-47.4213601610093534],"rgb":[0.8,0.6,0.866666666666666696],"xyz":[0.493417737833729442,0.408410947380014266,0.73692873778519119],"hpluv":[296.254085335195782,95.7635162234915498,70.0644466506374215],"hsluv":[296.254085335195782,58.3905887561973813,70.0644466506374215]},"#cc99ee":{"lch":[70.7283706212672,65.1265075826905218,288.858843135035954],"luv":[70.7283706212672,21.0513451251656711,-61.6303728557552191],"rgb":[0.8,0.6,0.933333333333333348],"xyz":[0.517229918099904151,0.417935819486484283,0.862339553853714413],"hpluv":[288.858843135035954,116.843205481858362,70.7283706212672],"hsluv":[288.858843135035954,78.6530020758075494,70.7283706212672]},"#cc99ff":{"lch":[71.4465289765693115,78.0706881495843561,283.894640570210413],"luv":[71.4465289765693115,18.7476796475605703,-75.7862576987549517],"rgb":[0.8,0.6,1],"xyz":[0.543400966509735572,0.428404238850417,1.00017374214549637],"hpluv":[283.894640570210413,138.658404713871533,71.4465289765693115],"hsluv":[283.894640570210413,99.9999999999978,71.4465289765693115]},"#990000":{"lch":[31.2857235930303546,105.214874065330946,12.1770506300617765],"luv":[31.2857235930303546,102.847587834444283,22.1933188419334826],"rgb":[0.6,0,0],"xyz":[0.131365760434599882,0.067735470224092,0.00615777002037173893],"hpluv":[12.1770506300617765,426.746789183125316,31.2857235930303546],"hsluv":[12.1770506300617765,100.000000000002217,31.2857235930303546]},"#990011":{"lch":[31.379701704172021,102.819321078199806,10.8595456684147944],"luv":[31.379701704172021,100.978030711674904,19.3713732237542438],"rgb":[0.6,0,0.0666666666666666657],"xyz":[0.132377425934237014,0.0681401364239468538,0.0114858749851273704],"hpluv":[10.8595456684147944,415.781582167217948,31.379701704172021],"hsluv":[10.8595456684147944,99.9999999999964473,31.379701704172021]},"#990022":{"lch":[31.5529326060038784,98.7447775317108807,8.37468971343924729],"luv":[31.5529326060038784,97.6918390895904309,14.3817824027706251],"rgb":[0.6,0,0.133333333333333331],"xyz":[0.134252784072714015,0.0688902796793376682,0.0213627611811065682],"hpluv":[8.37468971343924729,397.112659756655944,31.5529326060038784],"hsluv":[8.37468971343924729,99.999999999996632,31.5529326060038784]},"#990033":{"lch":[31.8354354483696653,92.9837515463916162,4.18138532137367758],"luv":[31.8354354483696653,92.7362491408617586,6.7798338419980837],"rgb":[0.6,0,0.2],"xyz":[0.137340534805171777,0.070125379972320781,0.0376249150387177114],"hpluv":[4.18138532137367758,370.62575576901952,31.8354354483696653],"hsluv":[4.18138532137367758,99.9999999999969,31.8354354483696653]},"#990044":{"lch":[32.2375108843075537,86.4821897260425771,357.977822115898675],"luv":[32.2375108843075537,86.4283323676992552,-3.05163955108307716],"rgb":[0.6,0,0.266666666666666663],"xyz":[0.141798530049390636,0.071908578070008361,0.0611036899916043499],"hpluv":[357.977822115898675,340.411718586576399,32.2375108843075537],"hsluv":[357.977822115898675,99.9999999999971294,32.2375108843075537]},"#990055":{"lch":[32.7650133258702,80.5606445545256804,349.629319937368109],"luv":[32.7650133258702,79.244583226626645,-14.502188809930411],"rgb":[0.6,0,0.333333333333333315],"xyz":[0.147760944088752622,0.0742935436857532,0.0925057372655782584],"hpluv":[349.629319937368109,311.998071704954214,32.7650133258702],"hsluv":[349.629319937368109,99.9999999999974847,32.7650133258702]},"#990066":{"lch":[33.4199981031921354,76.5714397631706589,339.419101050621862],"luv":[33.4199981031921354,71.6844038684648268,-26.9171252073414813],"rgb":[0.6,0,0.4],"xyz":[0.155345939862260807,0.0773275419951565124,0.13245338167272222],"hpluv":[339.419101050621862,290.7366076723265,33.4199981031921354],"hsluv":[339.419101050621862,99.9999999999978257,33.4199981031921354]},"#990077":{"lch":[34.2012599030024091,75.4745938555541187,328.234093427391315],"luv":[34.2012599030024091,64.1689603650959413,-39.7335984190155429],"rgb":[0.6,0,0.466666666666666674],"xyz":[0.164659952882462712,0.0810531472032373218,0.181507183579120129],"hpluv":[328.234093427391315,280.025774017920355,34.2012599030024091],"hsluv":[328.234093427391315,99.9999999999982094,34.2012599030024091]},"#990088":{"lch":[35.1048906557013396,77.5195253213057214,317.327493504651898],"luv":[35.1048906557013396,56.9954501323273419,-52.5432723595889613],"rgb":[0.6,0,0.533333333333333326],"xyz":[0.175800369984406568,0.0855093140440149196,0.240180046982692297],"hpluv":[317.327493504651898,280.209468657326,35.1048906557013396],"hsluv":[317.327493504651898,99.9999999999985505,35.1048906557013396]},"#990099":{"lch":[36.1248689761228263,82.286593786153162,307.715012949243601],"luv":[36.1248689761228263,50.3375351282041592,-65.0939019735657922],"rgb":[0.6,0,0.6],"xyz":[0.188857334093479268,0.0907320996876440772,0.308946724623810232],"hpluv":[307.715012949243601,289.042783730483336,36.1248689761228263],"hsluv":[307.715012949243601,99.9999999999988205,36.1248689761228263]},"#9900aa":{"lch":[37.2536516336468,89.0432435337247,299.813571633796073],"luv":[37.2536516336468,44.2704748017611038,-77.2581664281054685],"rgb":[0.6,0,0.66666666666666663],"xyz":[0.203915027058731824,0.0967551768737451856,0.388250574240808777],"hpluv":[299.813571633796073,303.299328566743952,37.2536516336468],"hsluv":[299.813571633796073,99.9999999999990905,37.2536516336468]},"#9900bb":{"lch":[38.4827280957899163,97.0854614833978786,293.557760104203282],"luv":[38.4827280957899163,38.802472411223853,-88.9941288300556579],"rgb":[0.6,0,0.733333333333333282],"xyz":[0.221052619166068443,0.103610213716679944,0.478508559339450579],"hpluv":[293.557760104203282,320.130957524774431,38.4827280957899163],"hsluv":[293.557760104203282,99.9999999999993179,38.4827280957899163]},"#9900cc":{"lch":[39.8031058181596933,105.884836559305498,288.673688741635],"luv":[39.8031058181596933,33.9019931565070394,-100.310784431221492],"rgb":[0.6,0,0.8],"xyz":[0.240344994609790197,0.111327163894168746,0.580115070009720735],"hpluv":[288.673688741635,337.564008898092311,39.8031058181596933],"hsluv":[288.673688741635,99.9999999999995879,39.8031058181596933]},"#9900dd":{"lch":[41.2057071388761145,115.092674624289529,284.860629917023232],"luv":[41.2057071388761145,29.5176685469448401,-111.243116621772529],"rgb":[0.6,0,0.866666666666666696],"xyz":[0.26186332016042374,0.11993449411442228,0.693444917909726732],"hpluv":[284.860629917023232,354.429316861661562,41.2057071388761145],"hsluv":[284.860629917023232,99.9999999999996732,41.2057071388761145]},"#9900ee":{"lch":[42.6816722484951754,124.494824438150232,281.862271937449748],"luv":[42.6816722484951754,25.5911328567321625,-121.836181945245357],"rgb":[0.6,0,0.933333333333333348],"xyz":[0.285675500426598505,0.129459366220892297,0.81885573397825],"hpluv":[281.862271937449748,370.125661914021862,42.6816722484951754],"hsluv":[281.862271937449748,99.9999999999998437,42.6816722484951754]},"#9900ff":{"lch":[44.2225734052255817,133.965544030308308,279.479958267333473],"luv":[44.2225734052255817,22.0644732467518,-132.136013288126151],"rgb":[0.6,0,1],"xyz":[0.311846548836429871,0.139927785584825,0.956689922270031801],"hpluv":[279.479958267333473,384.404468177447882,44.2225734052255817],"hsluv":[279.479958267333473,99.9999999999999574,44.2225734052255817]},"#bb0000":{"lch":[38.8409426943877918,130.623313921981463,12.1770506300617818],"luv":[38.8409426943877918,127.684349491075153,27.5528044852332741],"rgb":[0.733333333333333282,0,0],"xyz":[0.20493059501477473,0.105667338054495463,0.00960612164131736251],"hpluv":[12.1770506300617818,426.746789183125145,38.8409426943877918],"hsluv":[12.1770506300617818,100.000000000002217,38.8409426943877918]},"#bb0011":{"lch":[38.9108602521517142,128.680110500437479,11.3344428162225856],"luv":[38.9108602521517142,126.170422440132384,25.2902222149853806],"rgb":[0.733333333333333282,0,0.0666666666666666657],"xyz":[0.205942260514411862,0.106072004254350316,0.014934226606072994],"hpluv":[11.3344428162225856,419.642938315359174,38.9108602521517142],"hsluv":[11.3344428162225856,99.9999999999964189,38.9108602521517142]},"#bb0022":{"lch":[39.0399998564474373,125.270257566289573,9.75441483214293292],"luv":[39.0399998564474373,123.459226352671962,21.2239689767074431],"rgb":[0.733333333333333282,0,0.133333333333333331],"xyz":[0.207817618652888864,0.10682214750974113,0.0248111128020521918],"hpluv":[9.75441483214293292,407.171610230013243,39.0399998564474373],"hsluv":[9.75441483214293292,99.9999999999965326,39.0399998564474373]},"#bb0033":{"lch":[39.2513155564018916,120.169209623826248,7.10634666793171554],"luv":[39.2513155564018916,119.246098647877318,14.866300779810846],"rgb":[0.733333333333333282,0,0.2],"xyz":[0.210905369385346597,0.108057247802724243,0.041073266659663335],"hpluv":[7.10634666793171554,388.488631169232178,39.2513155564018916],"hsluv":[7.10634666793171554,99.9999999999967173,39.2513155564018916]},"#bb0044":{"lch":[39.5535843326651886,113.833969399977519,3.19865110237705785],"luv":[39.5535843326651886,113.656624965458903,6.3517077086437],"rgb":[0.733333333333333282,0,0.266666666666666663],"xyz":[0.215363364629565485,0.109840445900411823,0.0645520416125499735],"hpluv":[3.19865110237705785,365.195452768261646,39.5535843326651886],"hsluv":[3.19865110237705785,99.9999999999968878,39.5535843326651886]},"#bb0055":{"lch":[39.9527871554326666,107.03859947839959,357.869864695501747],"luv":[39.9527871554326666,106.964633924407806,-3.97855095665153691],"rgb":[0.733333333333333282,0,0.333333333333333315],"xyz":[0.221325778668927498,0.112225411516156656,0.095954088886523875],"hpluv":[357.869864695501747,339.963790558847222,39.9527871554326666],"hsluv":[357.869864695501747,99.9999999999971436,39.9527871554326666]},"#bb0066":{"lch":[40.452535568346093,100.749762000256624,351.053086521713055],"luv":[40.452535568346093,99.5239253968718884,-15.6685295004423661],"rgb":[0.733333333333333282,0,0.4],"xyz":[0.228910774442435655,0.115259409825559975,0.135901733293667837],"hpluv":[351.053086521713055,316.036764522848955,40.452535568346093],"hsluv":[351.053086521713055,99.999999999997442,40.452535568346093]},"#bb0077":{"lch":[41.0543478797665813,95.9494038996296581,342.883287985183927],"luv":[41.0543478797665813,91.699536963203,-28.2397420212797314],"rgb":[0.733333333333333282,0,0.466666666666666674],"xyz":[0.238224787462637588,0.118985015033640784,0.184955535200065746],"hpluv":[342.883287985183927,296.56674422547627,41.0543478797665813],"hsluv":[342.883287985183927,99.9999999999977,41.0543478797665813]},"#bb0088":{"lch":[41.7578935904565398,93.4210879643116243,333.788939203308246],"luv":[41.7578935904565398,83.8148890966975699,-41.2621381189091565],"rgb":[0.733333333333333282,0,0.533333333333333326],"xyz":[0.249365204564581389,0.123441181874418382,0.243628398603637913],"hpluv":[333.788939203308246,283.887103643995431,41.7578935904565398],"hsluv":[333.788939203308246,99.9999999999980531,41.7578935904565398]},"#bb0099":{"lch":[42.5612451572515,93.5592166386053918,324.452137443226093],"luv":[42.5612451572515,76.1225984195714318,-54.3937223205229472],"rgb":[0.733333333333333282,0,0.6],"xyz":[0.262422168673654088,0.12866396751804754,0.31239507624475582],"hpluv":[324.452137443226093,278.940502109978524,42.5612451572515],"hsluv":[324.452137443226093,99.9999999999983089,42.5612451572515]},"#bb00aa":{"lch":[43.461144448190268,96.3048592888224562,315.591494301740738],"luv":[43.461144448190268,68.7971872487792,-67.3911934105362747],"rgb":[0.733333333333333282,0,0.66666666666666663],"xyz":[0.277479861638906644,0.134687044704148634,0.391698925861754421],"hpluv":[315.591494301740738,281.181257774391042,43.461144448190268],"hsluv":[315.591494301740738,99.9999999999985647,43.461144448190268]},"#bb00bb":{"lch":[44.4532771259814652,101.257357078489918,307.715012949243601],"luv":[44.4532771259814652,61.9426024872754866,-80.100976021670192],"rgb":[0.733333333333333282,0,0.733333333333333282],"xyz":[0.294617453746243319,0.141542081547083393,0.481956910960396168],"hpluv":[307.715012949243601,289.042783730483507,44.4532771259814652],"hsluv":[307.715012949243601,99.9999999999988205,44.4532771259814652]},"#bb00cc":{"lch":[45.5325428123826796,107.876917991024385,301.028560594476971],"luv":[45.5325428123826796,55.6068066637028551,-92.44085940701639],"rgb":[0.733333333333333282,0,0.8],"xyz":[0.313909829189965,0.149259031724572194,0.583563421630666324],"hpluv":[301.028560594476971,300.639438898355309,45.5325428123826796],"hsluv":[301.028560594476971,99.999999999999,45.5325428123826796]},"#bb00dd":{"lch":[46.6933085129957348,115.650155059812704,295.504945579136574],"luv":[46.6933085129957348,49.7976850024997,-104.379830109799173],"rgb":[0.733333333333333282,0,0.866666666666666696],"xyz":[0.335428154740598616,0.157866361944825728,0.696893269530672321],"hpluv":[295.504945579136574,314.290242754568055,46.6933085129957348],"hsluv":[295.504945579136574,99.9999999999992468,46.6933085129957348]},"#bb00ee":{"lch":[47.929635203682146,124.167261181765113,290.999747870951808],"luv":[47.929635203682146,44.4970566855085821,-115.920320460682433],"rgb":[0.733333333333333282,0,0.933333333333333348],"xyz":[0.359240335006773326,0.167391234051295773,0.822304085599195544],"hpluv":[290.999747870951808,328.732244305823656,47.929635203682146],"hsluv":[290.999747870951808,99.9999999999993889,47.929635203682146]},"#bb00ff":{"lch":[49.2354711183318727,133.13261796854033,287.33664116340708],"luv":[49.2354711183318727,39.6715752597668896,-127.084460433075606],"rgb":[0.733333333333333282,0,1],"xyz":[0.385411383416604747,0.177859653415228469,0.96013827389097739],"hpluv":[287.33664116340708,343.119737385630629,49.2354711183318727],"hsluv":[287.33664116340708,99.9999999999995595,49.2354711183318727]},"#991100":{"lch":[32.2007428060931531,101.551746681272988,13.5001929330929755],"luv":[32.2007428060931531,98.7457840078795,23.707116962774041],"rgb":[0.6,0.0666666666666666657,0],"xyz":[0.133370160695528289,0.071744270745948871,0.00682590344068119],"hpluv":[13.5001929330929755,400.185025755779861,32.2007428060931531],"hsluv":[13.5001929330929755,100.000000000002359,32.2007428060931531]},"#991111":{"lch":[32.2911967351305,99.2607003603350506,12.1770506300617907],"luv":[32.2911967351305,97.0273802968116854,20.9373854328113431],"rgb":[0.6,0.0666666666666666657,0.0666666666666666657],"xyz":[0.134381826195165421,0.0721489369458037239,0.0121540084054368204],"hpluv":[12.1770506300617907,390.060992150638072,32.2911967351305],"hsluv":[12.1770506300617907,91.4033806551417,32.2911967351305]},"#991122":{"lch":[32.4579836187547883,95.3555453821432337,9.67722696349737355],"luv":[32.4579836187547883,93.9986702773161085,16.0290368151797],"rgb":[0.6,0.0666666666666666657,0.133333333333333331],"xyz":[0.136257184333642423,0.0728990802011945382,0.0220308946014160165],"hpluv":[9.67722696349737355,372.789562407290305,32.4579836187547883],"hsluv":[9.67722696349737355,91.6870397393079,32.4579836187547883]},"#991133":{"lch":[32.7301206059751877,89.8170234432985382,5.44607482402752385],"luv":[32.7301206059751877,89.4115862394302,8.52443231910342547],"rgb":[0.6,0.0666666666666666657,0.2],"xyz":[0.139344935066100184,0.0741341804941776511,0.0382930484590271597],"hpluv":[5.44607482402752385,348.217328437078379,32.7301206059751877],"hsluv":[5.44607482402752385,92.1153976677825312,32.7301206059751877]},"#991144":{"lch":[33.1177416447746893,83.547386161100178,359.159050762907725],"luv":[33.1177416447746893,83.5383872622118275,-1.22620878349376072],"rgb":[0.6,0.0666666666666666657,0.266666666666666663],"xyz":[0.143802930310319044,0.0759173785918652311,0.0617718234119138],"hpluv":[359.159050762907725,320.119020896680809,33.1177416447746893],"hsluv":[359.159050762907725,92.6613616101701609,33.1177416447746893]},"#991155":{"lch":[33.6267967661613341,77.8365467514172451,350.652860745276428],"luv":[33.6267967661613341,76.8030661853154,-12.6418762341523276],"rgb":[0.6,0.0666666666666666657,0.333333333333333315],"xyz":[0.149765344349681029,0.078302344207610064,0.0931738706858877136],"hpluv":[350.652860745276428,293.722615948770908,33.6267967661613341],"hsluv":[350.652860745276428,93.2833986807069664,33.6267967661613341]},"#991166":{"lch":[34.2596587707945375,74.039902428482776,340.197584074025258],"luv":[34.2596587707945375,69.661662743272629,-25.0830599301957804],"rgb":[0.6,0.0666666666666666657,0.4],"xyz":[0.157350340123189214,0.0813363425170133825,0.133121515093031662],"hpluv":[340.197584074025258,274.234525914752396,34.2596587707945375],"hsluv":[340.197584074025258,93.9371476037906774,34.2596587707945375]},"#991177":{"lch":[35.0156115165229096,73.1458980715855773,328.71391057162549],"luv":[35.0156115165229096,62.509382661628635,-37.9855167657472848],"rgb":[0.6,0.0666666666666666657,0.466666666666666674],"xyz":[0.16666435314339112,0.0850619477250941919,0.182175316999429571],"hpluv":[328.71391057162549,265.074278305330154,35.0156115165229096],"hsluv":[328.71391057162549,94.5844210689808165,35.0156115165229096]},"#991188":{"lch":[35.8913494409224185,75.4242755669397269,317.528981112118743],"luv":[35.8913494409224185,55.6343762077295239,-50.9277677576239398],"rgb":[0.6,0.0666666666666666657,0.533333333333333326],"xyz":[0.177804770245334975,0.0895181145658717897,0.240848180403001738],"hpluv":[317.528981112118743,266.661726649655066,35.8913494409224185],"hsluv":[317.528981112118743,95.1976582537924116,35.8913494409224185]},"#991199":{"lch":[36.8815072257793,80.448343562419069,307.715012949243601],"luv":[36.8815072257793,49.2130143411107568,-63.6397297401445599],"rgb":[0.6,0.0666666666666666657,0.6],"xyz":[0.190861734354407675,0.0947409002095009473,0.309614858044119645],"hpluv":[307.715012949243601,276.788327826692239,36.8815072257793],"hsluv":[307.715012949243601,95.7603314825458511,36.8815072257793]},"#9911aa":{"lch":[37.9791974354050694,87.4639739592788,299.695850237394552],"luv":[37.9791974354050694,43.3292813921454609,-75.9771025690614152],"rgb":[0.6,0.0666666666666666657,0.66666666666666663],"xyz":[0.205919427319660231,0.100763977395602056,0.388918707661118246],"hpluv":[299.695850237394552,292.228621346341356,37.9791974354050694],"hsluv":[299.695850237394552,96.26500390067784,37.9791974354050694]},"#9911bb":{"lch":[39.176522525078866,95.7489617369993624,293.383950362709356],"luv":[39.176522525078866,38.0018814997404846,-87.8847010360338459],"rgb":[0.6,0.0666666666666666657,0.733333333333333282],"xyz":[0.22305701942699685,0.107619014238536814,0.47917669275976],"hpluv":[293.383950362709356,310.132668732371314,39.176522525078866],"hsluv":[293.383950362709356,96.7106400677762537,39.176522525078866]},"#9911cc":{"lch":[40.465031277763515,104.765415075180798,288.480743990765689],"luv":[40.465031277763515,33.2091620218187842,-99.3626879350770622],"rgb":[0.6,0.0666666666666666657,0.8],"xyz":[0.242349394870718604,0.115335964416025616,0.580783203430030204],"hpluv":[288.480743990765689,328.531778006508034,40.465031277763515],"hsluv":[288.480743990765689,97.1001366995766,40.465031277763515]},"#9911dd":{"lch":[41.8361001822542917,114.161763941518927,284.668123617886636],"luv":[41.8361001822542917,28.9080153835727351,-110.441092863219225],"rgb":[0.6,0.0666666666666666657,0.866666666666666696],"xyz":[0.263867720421352148,0.12394329463627915,0.694113051330036201],"hpluv":[284.668123617886636,346.265164959266087,41.8361001822542917],"hsluv":[284.668123617886636,97.4384492036098,41.8361001822542917]},"#9911ee":{"lch":[43.2812320372341617,123.724619665436521,281.679545129349094],"luv":[43.2812320372341617,25.0465268392882301,-121.162919264293635],"rgb":[0.6,0.0666666666666666657,0.933333333333333348],"xyz":[0.287679900687526913,0.133468166742749167,0.819523867398559425],"hpluv":[281.679545129349094,362.740326129136179,43.2812320372341617],"hsluv":[281.679545129349094,97.7313369542794561,43.2812320372341617]},"#9911ff":{"lch":[44.7922739406791948,133.33068560825987,279.310828677429186],"luv":[44.7922739406791948,21.5716156333953251,-131.574074664174219],"rgb":[0.6,0.0666666666666666657,1],"xyz":[0.313850949097358278,0.143936586106681863,0.95735805569034127],"hpluv":[279.310828677429186,377.716823123197173,44.7922739406791948],"hsluv":[279.310828677429186,99.9999999999993179,44.7922739406791948]},"#bb1100":{"lch":[39.5258701457598747,127.514079962112703,13.0219609303782402],"luv":[39.5258701457598747,124.2348987579322,28.7320469022032583],"rgb":[0.733333333333333282,0.0666666666666666657,0],"xyz":[0.206934995275703137,0.109676138576352333,0.0102742550616268143],"hpluv":[13.0219609303782402,409.370014873310311,39.5258701457598747],"hsluv":[13.0219609303782402,100.000000000002203,39.5258701457598747]},"#bb1111":{"lch":[39.5940766091873897,125.63034182067031,12.177050630061796],"luv":[39.5940766091873897,122.803716963532779,26.4996204863200759],"rgb":[0.733333333333333282,0.0666666666666666657,0.0666666666666666657],"xyz":[0.20794666077534027,0.110080804776207186,0.0156023600263824457],"hpluv":[12.177050630061796,402.627698793753552,39.5940766091873897],"hsluv":[12.177050630061796,94.3481495348726753,39.5940766091873897]},"#bb1122":{"lch":[39.7200723855077413,122.321798686612851,10.5915831721034426],"luv":[39.7200723855077413,120.23772406897838,22.4835972353282152],"rgb":[0.733333333333333282,0.0666666666666666657,0.133333333333333331],"xyz":[0.209822018913817271,0.110830948031598,0.0254792462223616401],"hpluv":[10.5915831721034426,390.780742551338619,39.7200723855077413],"hsluv":[10.5915831721034426,94.4721603032542561,39.7200723855077413]},"#bb1133":{"lch":[39.9262897734852,117.365304386249704,7.93115519261489421],"luv":[39.9262897734852,116.242655940639409,16.194431559742192],"rgb":[0.733333333333333282,0.0666666666666666657,0.2],"xyz":[0.212909769646275,0.112066048324581113,0.0417414000799727902],"hpluv":[7.93115519261489421,373.009679290071517,39.9262897734852],"hsluv":[7.93115519261489421,94.6648992051481173,39.9262897734852]},"#bb1144":{"lch":[40.2213637516280755,111.198866264944101,3.99799547396429888],"luv":[40.2213637516280755,110.928262725239179,7.75295991020434627],"rgb":[0.733333333333333282,0.0666666666666666657,0.266666666666666663],"xyz":[0.217367764890493892,0.113849246422268693,0.0652201750328594287],"hpluv":[3.99799547396429888,350.818828640487084,40.2213637516280755],"hsluv":[3.99799547396429888,94.920595316052,40.2213637516280755]},"#bb1155":{"lch":[40.6112374139617245,104.574630781207446,358.621384873601698],"luv":[40.6112374139617245,104.544360517453882,-2.51596641918957786],"rgb":[0.733333333333333282,0.0666666666666666657,0.333333333333333315],"xyz":[0.223330178929855905,0.116234212038013526,0.0966222223068333302],"hpluv":[358.621384873601698,326.752894857139097,40.6112374139617245],"hsluv":[358.621384873601698,95.2265760165129791,40.6112374139617245]},"#bb1166":{"lch":[41.0995768863194755,98.4443929415329251,351.723860164231496],"luv":[41.0995768863194755,97.4191751888273672,-14.1704907168206535],"rgb":[0.733333333333333282,0.0666666666666666657,0.4],"xyz":[0.230915174703364062,0.119268210347416845,0.136569866713977306],"hpluv":[351.723860164231496,303.943570446579713,41.0995768863194755],"hsluv":[351.723860164231496,95.5663396203906643,41.0995768863194755]},"#bb1177":{"lch":[41.688035181331955,93.7889310063258,343.43446060875408],"luv":[41.688035181331955,89.8961490854954093,-26.7403432832812094],"rgb":[0.733333333333333282,0.0666666666666666657,0.466666666666666674],"xyz":[0.240229187723566,0.122993815555497654,0.185623668620375215],"hpluv":[343.43446060875408,285.48249634694713,41.688035181331955],"hsluv":[343.43446060875408,95.9227087501184883,41.688035181331955]},"#bb1188":{"lch":[42.3764815581906475,91.4027083669889606,334.189166164708297],"luv":[42.3764815581906475,82.2840505377722309,-39.7968607294366805],"rgb":[0.733333333333333282,0.0666666666666666657,0.533333333333333326],"xyz":[0.251369604825509796,0.127449982396275252,0.244296532023947383],"hpluv":[334.189166164708297,273.699179760613617,42.3764815581906475],"hsluv":[334.189166164708297,96.2803174994205,42.3764815581906475]},"#bb1199":{"lch":[43.1632358766101092,91.692942572352564,324.693570122963422],"luv":[43.1632358766101092,74.8281105443768269,-52.9938637007650755],"rgb":[0.733333333333333282,0.0666666666666666657,0.6],"xyz":[0.264426568934582495,0.13267276803990441,0.31306320966506529],"hpluv":[324.693570122963422,269.563595898888195,43.1632358766101092],"hsluv":[324.693570122963422,96.6270445785018239,43.1632358766101092]},"#bb11aa":{"lch":[44.0453166933651,94.6050581990027553,315.694091730478135],"luv":[44.0453166933651,67.7013389352867847,-66.0806003544619784],"rgb":[0.733333333333333282,0.0666666666666666657,0.66666666666666663],"xyz":[0.279484261899835051,0.138695845226005504,0.39236705928206389],"hpluv":[315.694091730478135,272.554870225691275,44.0453166933651],"hsluv":[315.694091730478135,96.9544350138240105,44.0453166933651]},"#bb11bb":{"lch":[45.0186979872658242,99.7328976909900717,307.715012949243601],"luv":[45.0186979872658242,61.0100383302365472,-78.8950321933172205],"rgb":[0.733333333333333282,0.0666666666666666657,0.733333333333333282],"xyz":[0.296621854007171726,0.145550882068940263,0.482625044380705637],"hpluv":[307.715012949243601,281.115526817766181,45.0186979872658242],"hsluv":[307.715012949243601,97.2574105430315115,45.0186979872658242]},"#bb11cc":{"lch":[46.0785638011469771,106.527215460047387,300.962972083371881],"luv":[46.0785638011469771,54.8065495444917161,-91.3470840295328372],"rgb":[0.733333333333333282,0.0666666666666666657,0.8],"xyz":[0.315914229450893425,0.153267832246429064,0.584231555050975793],"hpluv":[300.962972083371881,293.360047474541318,46.0785638011469771],"hsluv":[300.962972083371881,97.5336183018287528,46.0785638011469771]},"#bb11dd":{"lch":[47.2195492447565,114.4666153484132,295.402801066287566],"luv":[47.2195492447565,49.1038079522977853,-103.3993330438134],"rgb":[0.733333333333333282,0.0666666666666666657,0.866666666666666696],"xyz":[0.337432555001527,0.161875162466682598,0.69756140295098179],"hpluv":[295.402801066287566,307.607082675331128,47.2195492447565],"hsluv":[295.402801066287566,97.7826899351839813,47.2195492447565]},"#bb11ee":{"lch":[48.4359581768354701,123.136484869400022,290.880608651701721],"luv":[48.4359581768354701,43.8885280811888,-115.049515465553711],"rgb":[0.733333333333333282,0.0666666666666666657,0.933333333333333348],"xyz":[0.361244735267701733,0.171400034573152643,0.822972219019505],"hpluv":[290.880608651701721,322.595409245987128,48.4359581768354701],"hsluv":[290.880608651701721,98.0055710342431325,48.4359581768354701]},"#bb11ff":{"lch":[49.7219510368964,132.239138283310353,287.21247838519713],"luv":[49.7219510368964,39.1316890181496575,-126.316667975763593],"rgb":[0.733333333333333282,0.0666666666666666657,1],"xyz":[0.387415783677533154,0.181868453937085339,0.960806407311286859],"hpluv":[287.21247838519713,337.482436204013879,49.7219510368964],"hsluv":[287.21247838519713,99.9999999999991758,49.7219510368964]},"#992200":{"lch":[33.8105832897308716,95.4307991554818358,16.0266852535062476],"luv":[33.8105832897308716,91.7217107848809263,26.3470149760569932],"rgb":[0.6,0.133333333333333331,0],"xyz":[0.137085784430296231,0.0791755182154848525,0.0080644446856038],"hpluv":[16.0266852535062476,358.158468302090569,33.8105832897308716],"hsluv":[16.0266852535062476,100.000000000002331,33.8105832897308716]},"#992211":{"lch":[33.8952997814050718,93.2922690289088195,14.6972380002076104],"luv":[33.8952997814050718,90.239744522062125,23.669304365681274],"rgb":[0.6,0.133333333333333331,0.0666666666666666657],"xyz":[0.138097449929933364,0.0795801844153397,0.0133925496503594314],"hpluv":[14.6972380002076104,349.257308780581,33.8952997814050718],"hsluv":[14.6972380002076104,92.1483909924374274,33.8952997814050718]},"#992222":{"lch":[34.0515850466810335,89.6330213591727,12.1770506300618084],"luv":[34.0515850466810335,87.6163196410811338,18.9065874902323579],"rgb":[0.6,0.133333333333333331,0.133333333333333331],"xyz":[0.139972808068410365,0.0803303276707305197,0.0232694358463386292],"hpluv":[12.1770506300618084,334.018122077437397,34.0515850466810335],"hsluv":[12.1770506300618084,78.2707991117683,34.0515850466810335]},"#992233":{"lch":[34.3068003204445446,84.4135643942939282,7.88651435003668233],"luv":[34.3068003204445446,83.6151628365757773,11.58250394183076],"rgb":[0.6,0.133333333333333331,0.2],"xyz":[0.143060558800868098,0.0815654279637136326,0.0395315897039497724],"hpluv":[7.88651435003668233,312.227643050581207,34.3068003204445446],"hsluv":[7.88651435003668233,79.3008398259009226,34.3068003204445446]},"#992244":{"lch":[34.6707661525426,78.4682482149262199,1.45557545410962708],"luv":[34.6707661525426,78.4429281517087134,1.99323879782018309],"rgb":[0.6,0.133333333333333331,0.266666666666666663],"xyz":[0.147518554045086986,0.0833486260614012126,0.0630103646568364],"hpluv":[1.45557545410962708,287.190351340663,34.6707661525426],"hsluv":[1.45557545410962708,80.6267396657693212,34.6707661525426]},"#992255":{"lch":[35.149531709850983,73.0418005898087443,352.659616011821072],"luv":[35.149531709850983,72.4431965063170082,-9.33209051330535821],"rgb":[0.6,0.133333333333333331,0.333333333333333315],"xyz":[0.153480968084449,0.0857335916771460455,0.0944124119308103193],"hpluv":[352.659616011821072,263.688538908073838,35.149531709850983],"hsluv":[352.659616011821072,82.1555178352066804,35.149531709850983]},"#992266":{"lch":[35.7459223236079495,69.5043059181480203,341.734006615383123],"luv":[35.7459223236079495,66.0021002604389793,-21.7846574995905513],"rgb":[0.6,0.133333333333333331,0.4],"xyz":[0.161065963857957156,0.0887675899865493639,0.134360056337954281],"hpluv":[341.734006615383123,246.731460763727796,35.7459223236079495],"hsluv":[341.734006615383123,83.7834402291280753,35.7459223236079495]},"#992277":{"lch":[36.4599553630224946,68.9051746310403104,329.662355423262511],"luv":[36.4599553630224946,59.4695672743266783,-34.8036443370302],"rgb":[0.6,0.133333333333333331,0.466666666666666674],"xyz":[0.17037997687815909,0.0924931951946301734,0.18341385824435219],"hpluv":[329.662355423262511,239.814275331209444,36.4599553630224946],"hsluv":[329.662355423262511,85.4170781092293225,36.4599553630224946]},"#992288":{"lch":[37.2892540647929,71.5563678213307242,317.925484235555643],"luv":[37.2892540647929,53.1144286836587369,-47.9496740488411],"rgb":[0.6,0.133333333333333331,0.533333333333333326],"xyz":[0.18152039398010289,0.0969493620354077712,0.242086721647924358],"hpluv":[317.925484235555643,243.502777039008038,37.2892540647929],"hsluv":[317.925484235555643,86.9852623869732,37.2892540647929]},"#992299":{"lch":[38.2294870734457888,77.015786119064046,307.715012949243771],"luv":[38.2294870734457888,47.1132010795059841,-60.9243596238766827],"rgb":[0.6,0.133333333333333331,0.6],"xyz":[0.194577358089175617,0.102172147679036929,0.310853399289042265],"hpluv":[307.715012949243771,255.635172818446421,38.2294870734457888],"hsluv":[307.715012949243771,88.441984096309227,38.2294870734457888]},"#9922aa":{"lch":[39.2748221448681178,84.484081905089468,299.468150353755561],"luv":[39.2748221448681178,41.5610713460956234,-73.5543162833468],"rgb":[0.6,0.133333333333333331,0.66666666666666663],"xyz":[0.209635051054428145,0.108195224865138023,0.390157248906040865],"hpluv":[299.468150353755561,272.960615272696657,39.2748221448681178],"hsluv":[299.468150353755561,89.7633288768494708,39.2748221448681178]},"#9922bb":{"lch":[40.4183688993281436,93.2013493596814726,293.05045530637],"luv":[40.4183688993281436,36.4922039393154094,-85.7601922462677919],"rgb":[0.6,0.133333333333333331,0.733333333333333282],"xyz":[0.22677264316176482,0.115050261708072782,0.480415234004682612],"hpluv":[293.05045530637,292.605673863240838,40.4183688993281436],"hsluv":[293.05045530637,90.9419133161227222,40.4183688993281436]},"#9922cc":{"lch":[41.6525852773545182,102.609691310931794,288.11294916137831],"luv":[41.6525852773545182,31.900454524651952,-97.5249186210648702],"rgb":[0.6,0.133333333333333331,0.8],"xyz":[0.246065018605486546,0.122767211885561583,0.582021744674952712],"hpluv":[288.11294916137831,312.597676326075884,41.6525852773545182],"hsluv":[288.11294916137831,91.9812251551093851,41.6525852773545182]},"#9922dd":{"lch":[42.969628845807982,112.350489371469905,284.303043907998301],"luv":[42.969628845807982,27.7562437333976213,-108.867917201630149],"rgb":[0.6,0.133333333333333331,0.866666666666666696],"xyz":[0.267583344156120062,0.131374542105815117,0.69535159257495871],"hpluv":[284.303043907998301,331.781902020401162,42.969628845807982],"hsluv":[284.303043907998301,92.8910125551507235,42.969628845807982]},"#9922ee":{"lch":[44.361642902098545,122.210344632057584,281.334390799049743],"luv":[44.361642902098545,24.018574136526297,-119.826860225637532],"rgb":[0.6,0.133333333333333331,0.933333333333333348],"xyz":[0.291395524422294827,0.140899414212285162,0.820762408643481933],"hpluv":[281.334390799049743,349.574442537581717,44.361642902098545],"hsluv":[281.334390799049743,93.6839973987951566,44.361642902098545]},"#9922ff":{"lch":[45.8209755847726612,132.069283427413211,278.992348895848238],"luv":[45.8209755847726612,20.6427685166220094,-130.446049127597433],"rgb":[0.6,0.133333333333333331,1],"xyz":[0.317566572832126193,0.151367833576217858,0.958596596935263889],"hpluv":[278.992348895848238,365.74366826955071,45.8209755847726612],"hsluv":[278.992348895848238,99.9999999999993179,45.8209755847726612]},"#bb2200":{"lch":[40.7526421249889452,122.145166616692975,14.6188079362681389],"luv":[40.7526421249889452,118.190884669319914,30.8278528104570881],"rgb":[0.733333333333333282,0.133333333333333331,0],"xyz":[0.21065061901047108,0.117107386045888315,0.0115127963065494235],"hpluv":[14.6188079362681389,380.329350781024857,40.7526421249889452],"hsluv":[14.6188079362681389,100.000000000002217,40.7526421249889452]},"#bb2211":{"lch":[40.8179368215716849,120.355879944515436,13.7706881972771793],"luv":[40.8179368215716849,116.896392622501153,28.6491052053056343],"rgb":[0.733333333333333282,0.133333333333333331,0.0666666666666666657],"xyz":[0.211662284510108212,0.117512052245743168,0.0168409012713050532],"hpluv":[13.7706881972771793,374.158477594779924,40.8179368215716849],"hsluv":[13.7706881972771793,94.6800257514418,40.8179368215716849]},"#bb2222":{"lch":[40.9385803904414161,117.208042434762348,12.1770506300618102],"luv":[40.9385803904414161,114.570915436608942,24.7230772236478238],"rgb":[0.733333333333333282,0.133333333333333331,0.133333333333333331],"xyz":[0.213537642648585213,0.118262195501133982,0.0267177874672842527],"hpluv":[12.1770506300618102,363.298797482753,40.9385803904414161],"hsluv":[12.1770506300618102,85.1321689328196101,40.9385803904414161]},"#bb2233":{"lch":[41.136111673530813,112.480172956632245,9.49666640172232235],"luv":[41.136111673530813,110.938654987290519,18.5581286223806821],"rgb":[0.733333333333333282,0.133333333333333331,0.2],"xyz":[0.216625393381042974,0.119497295794117095,0.042979941324895396],"hpluv":[9.49666640172232235,346.970109935861444,41.136111673530813],"hsluv":[9.49666640172232235,85.6217357677037398,41.136111673530813]},"#bb2244":{"lch":[41.4189140922405201,106.57909239531196,5.51995404221549],"luv":[41.4189140922405201,106.084859394728952,10.2520994439692306],"rgb":[0.733333333333333282,0.133333333333333331,0.266666666666666663],"xyz":[0.221083388625261834,0.121280493891804675,0.0664587162777820345],"hpluv":[5.51995404221549,326.522141050690152,41.4189140922405201],"hsluv":[5.51995404221549,86.2742612371986297,41.4189140922405201]},"#bb2255":{"lch":[41.7928521194743823,100.22104851316422,0.0579838467833058424],"luv":[41.7928521194743823,100.220997191859041,0.101424589714973798],"rgb":[0.733333333333333282,0.133333333333333331,0.333333333333333315],"xyz":[0.227045802664623819,0.123665459507549508,0.097860763551755936],"hpluv":[0.0579838467833058424,304.296010337655673,41.7928521194743823],"hsluv":[0.0579838467833058424,87.0597094656736772,41.7928521194743823]},"#bb2266":{"lch":[42.2616671880265216,94.3342448936905,353.011685321171171],"luv":[42.2616671880265216,93.6334344607092106,-11.4773564358193614],"rgb":[0.733333333333333282,0.133333333333333331,0.4],"xyz":[0.234630798438132,0.126699457816952826,0.137808407958899898],"hpluv":[353.011685321171171,283.244886623536,42.2616671880265216],"hsluv":[353.011685321171171,87.937804292381287,42.2616671880265216]},"#bb2277":{"lch":[42.8272221099346666,89.9002723684957,344.496654306277264],"luv":[42.8272221099346666,86.6292371691086771,-24.0298614109202155],"rgb":[0.733333333333333282,0.133333333333333331,0.466666666666666674],"xyz":[0.24394481145833391,0.13042506302503365,0.186862209865297807],"hpluv":[344.496654306277264,266.367005402095344,42.8272221099346666],"hsluv":[344.496654306277264,88.8655868844719805,42.8272221099346666]},"#bb2288":{"lch":[43.4897067779173554,87.7363054907772693,334.961981200390596],"luv":[43.4897067779173554,79.4914755013727898,-37.1317199141871441],"rgb":[0.733333333333333282,0.133333333333333331,0.533333333333333326],"xyz":[0.255085228560277766,0.13488122986581122,0.245535073268869974],"hpluv":[334.961981200390596,255.995416581420926,43.4897067779173554],"hsluv":[334.961981200390596,89.8036443318747786,43.4897067779173554]},"#bb2299":{"lch":[44.2478449340908639,88.2751432264235092,325.159464012784042],"luv":[44.2478449340908639,72.4514028672968635,-50.4310929309115],"rgb":[0.733333333333333282,0.133333333333333331,0.6],"xyz":[0.268142192669350465,0.140104015509440405,0.314301750909987909],"hpluv":[325.159464012784042,253.154489640486645,44.2478449340908639],"hsluv":[325.159464012784042,90.7199745934293844,44.2478449340908639]},"#bb22aa":{"lch":[45.0991127685299062,91.4705260319517919,315.891475419905078],"luv":[45.0991127685299062,65.6779186933914758,-63.6652819727222195],"rgb":[0.733333333333333282,0.133333333333333331,0.66666666666666663],"xyz":[0.283199885634603,0.146127092695541499,0.39360560052698651],"hpluv":[315.891475419905078,257.366789521381691,45.0991127685299062],"hsluv":[315.891475419905078,91.5914304646717,45.0991127685299062]},"#bb22bb":{"lch":[46.0399667792549678,96.9048462314552,307.715012949243658],"luv":[46.0399667792549678,59.2800221375787615,-76.6578645574617497],"rgb":[0.733333333333333282,0.133333333333333331,0.733333333333333282],"xyz":[0.30033747774193964,0.152982129538476258,0.483863585625628256],"hpluv":[307.715012949243658,267.0851991180906,46.0399667792549678],"hsluv":[307.715012949243658,92.4033444706684,46.0399667792549678]},"#bb22cc":{"lch":[47.066072507765945,104.009692587178989,300.837938637053412],"luv":[47.066072507765945,53.3165662395356,-89.3048706202785496],"rgb":[0.733333333333333282,0.133333333333333331,0.8],"xyz":[0.319629853185661394,0.16069907971596506,0.585470096295898412],"hpluv":[300.837938637053412,280.417543020287,47.066072507765945],"hsluv":[300.837938637053412,93.1481326309998,47.066072507765945]},"#bb22dd":{"lch":[48.1725242595717589,112.247547842848149,295.20893392435471],"luv":[48.1725242595717589,47.808517424121824,-101.557164486017044],"rgb":[0.733333333333333282,0.133333333333333331,0.866666666666666696],"xyz":[0.341148178736294938,0.169306409936218594,0.69879994419590441],"hpluv":[295.20893392435471,295.676483579310798,48.1725242595717589],"hsluv":[295.20893392435471,93.8235497257627316,48.1725242595717589]},"#bb22ee":{"lch":[49.3540469689012724,121.194036197623419,290.655339197387],"luv":[49.3540469689012724,42.7506603945962169,-113.403595382583688],"rgb":[0.733333333333333282,0.133333333333333331,0.933333333333333348],"xyz":[0.364960359002469703,0.178831282042688611,0.824210760264427633],"hpluv":[290.655339197387,311.600255956968681,49.3540469689012724],"hsluv":[290.655339197387,94.4310255689598,49.3540469689012724]},"#bb22ff":{"lch":[50.6051737457033397,130.547024148317973,286.97844412333734],"luv":[50.6051737457033397,38.1212848334983647,-124.85709093449519],"rgb":[0.733333333333333282,0.133333333333333331,1],"xyz":[0.391131407412301069,0.189299701406621335,0.962044948556209478],"hpluv":[286.97844412333734,327.349274436557835,50.6051737457033397],"hsluv":[286.97844412333734,99.9999999999991616,50.6051737457033397]},"#993300":{"lch":[36.2545465004255476,86.9834057059747749,20.3835344027483316],"luv":[36.2545465004255476,81.5366895093473,30.2965531383769893],"rgb":[0.6,0.2,0],"xyz":[0.14320350651930705,0.0914109623935066423,0.0101036853819406816],"hpluv":[20.3835344027483316,304.448092478673459,36.2545465004255476],"hsluv":[20.3835344027483316,100.00000000000226,36.2545465004255476]},"#993311":{"lch":[36.3315413581227133,85.0112276295678839,19.0571063974297203],"luv":[36.3315413581227133,80.3520694714869279,27.7570487396543],"rgb":[0.6,0.2,0.0666666666666666657],"xyz":[0.144215172018944182,0.0918156285933615,0.0154317903466963131],"hpluv":[19.0571063974297203,296.914762557758195,36.3315413581227133],"hsluv":[19.0571063974297203,93.1288353931581,36.3315413581227133]},"#993322":{"lch":[36.4736730302835852,81.6150828115545863,16.5278497598068661],"luv":[36.4736730302835852,78.2428757472059573,23.217970134019108],"rgb":[0.6,0.2,0.133333333333333331],"xyz":[0.146090530157421183,0.0925657718487523096,0.0253086765426755109],"hpluv":[16.5278497598068661,283.942401799749632,36.4736730302835852],"hsluv":[16.5278497598068661,80.9121244795507124,36.4736730302835852]},"#993333":{"lch":[36.7060271438600836,76.7221326388105638,12.1770506300618369],"luv":[36.7060271438600836,74.9959199734098121,16.1832513417159589],"rgb":[0.6,0.2,0.2],"xyz":[0.149178280889878945,0.0938008721417354224,0.0415708304002866541],"hpluv":[12.1770506300618369,265.229979343802,36.7060271438600836],"hsluv":[12.1770506300618369,62.1516051360361459,36.7060271438600836]},"#993344":{"lch":[37.0379214664673668,71.077614272095758,5.55118145677439934],"luv":[37.0379214664673668,70.7442733159460744,6.87568495580995354],"rgb":[0.6,0.2,0.266666666666666663],"xyz":[0.153636276134097804,0.095584070239423,0.0650496053531732926],"hpluv":[5.55118145677439934,243.514912685509444,37.0379214664673668],"hsluv":[5.55118145677439934,64.3097526797848644,37.0379214664673668]},"#993355":{"lch":[37.4754277574064858,65.8722356173568073,356.298722520573506],"luv":[37.4754277574064858,65.7348379379961614,-4.25235305377523254],"rgb":[0.6,0.2,0.333333333333333315],"xyz":[0.15959869017345979,0.0979690358551678353,0.0964516526271472],"hpluv":[356.298722520573506,223.046355214908289,37.4754277574064858],"hsluv":[356.298722520573506,66.8387430740197885,37.4754277574064858]},"#993366":{"lch":[38.0218512407041942,62.5198646461221941,344.559385799457459],"luv":[38.0218512407041942,60.2633303059628602,-16.6452544529622166],"rgb":[0.6,0.2,0.4],"xyz":[0.167183685946967975,0.101003034164571154,0.136399297034291156],"hpluv":[344.559385799457459,208.652742449272864,38.0218512407041942],"hsluv":[344.559385799457459,69.5808124884664778,38.0218512407041942]},"#993377":{"lch":[38.6780657603296234,62.1964572713534949,331.414072321130675],"luv":[38.6780657603296234,54.6147414507713478,-29.7595247504508862],"rgb":[0.6,0.2,0.466666666666666674],"xyz":[0.17649769896716988,0.104728639372651963,0.185453098940689065],"hpluv":[331.414072321130675,204.051704505442274,38.6780657603296234],"hsluv":[331.414072321130675,72.3848063102254571,38.6780657603296234]},"#993388":{"lch":[39.4428302118465908,65.3028355433768155,318.6521895607018],"luv":[39.4428302118465908,49.0236963230770257,-43.1409031990296086],"rgb":[0.6,0.2,0.533333333333333326],"xyz":[0.187638116069113736,0.109184806213429561,0.244125962344261233],"hpluv":[318.6521895607018,210.08899125401652,39.4428302118465908],"hsluv":[318.6521895607018,75.1271370389489306,39.4428302118465908]},"#993399":{"lch":[40.3131218316236897,71.3679900272828149,307.715012949243942],"luv":[40.3131218316236897,43.6582502656979656,-56.4565955781255226],"rgb":[0.6,0.2,0.6],"xyz":[0.200695080178186436,0.114407591857058719,0.31289263998537914],"hpluv":[307.715012949243942,224.64479534599792,40.3131218316236897],"hsluv":[307.715012949243942,77.7202573427554313,40.3131218316236897]},"#9933aa":{"lch":[41.2844862133256925,79.5040030135899372,299.063916375798101],"luv":[41.2844862133256925,38.6218522191785354,-69.4927264276258825],"rgb":[0.6,0.2,0.66666666666666663],"xyz":[0.215752773143439,0.120430669043159827,0.39219648960237774],"hpluv":[299.063916375798101,244.366370382710016,41.2844862133256925],"hsluv":[299.063916375798101,80.1114582016200814,41.2844862133256925]},"#9933bb":{"lch":[42.3513893410192637,88.8787943355742,292.467029257400327],"luv":[42.3513893410192637,33.9651845170614,-82.1328577566084],"rgb":[0.6,0.2,0.733333333333333282],"xyz":[0.232890365250775611,0.127285705886094586,0.482454474701019487],"hpluv":[292.467029257400327,266.299173904300574,42.3513893410192637],"hsluv":[292.467029257400327,82.2764131802073848,42.3513893410192637]},"#9933cc":{"lch":[43.5075532005759911,98.8962106119506785,287.477062230467],"luv":[43.5075532005759911,29.700902070050418,-94.3308904316533],"rgb":[0.6,0.2,0.8],"xyz":[0.252182740694497365,0.135002656063583387,0.584060985371289698],"hpluv":[287.477062230467,288.439223502221068,43.5075532005759911],"hsluv":[287.477062230467,84.2111914011780129,43.5075532005759911]},"#9933dd":{"lch":[44.7462588110156716,109.182503226938962,283.677602435208257],"luv":[44.7462588110156716,25.8171133061496079,-106.086265234656878],"rgb":[0.6,0.2,0.866666666666666696],"xyz":[0.273701066245130908,0.143609986283836921,0.697390833271295696],"hpluv":[283.677602435208257,309.624731809924413,44.7462588110156716],"hsluv":[283.677602435208257,85.9249592908513478,44.7462588110156716]},"#9933ee":{"lch":[46.0606056636097208,119.52114969179982,280.747238708189116],"luv":[46.0606056636097208,22.2879081330132465,-117.42467532296601],"rgb":[0.6,0.2,0.933333333333333348],"xyz":[0.297513246511305618,0.153134858390306938,0.822801649339818919],"hpluv":[280.747238708189116,329.271729063034456,46.0606056636097208],"hsluv":[280.747238708189116,90.0471632149093324,46.0606056636097208]},"#9933ff":{"lch":[47.4437223771408512,129.794782591236896,278.453521985212944],"luv":[47.4437223771408512,19.0807517890999456,-128.38461940228359],"rgb":[0.6,0.2,1],"xyz":[0.323684294921137039,0.163603277754239662,0.960635837631600764],"hpluv":[278.453521985212944,347.150508646733101,47.4437223771408512],"hsluv":[278.453521985212944,99.999999999999261,47.4437223771408512]},"#bb3300":{"lch":[42.6640590509798585,114.303280915030754,17.3320761189885637],"luv":[42.6640590509798585,109.113245500432,34.0520143942012652],"rgb":[0.733333333333333282,0.2,0],"xyz":[0.216768341099481898,0.129342830223910105,0.0135520370028863052],"hpluv":[17.3320761189885637,339.966286272656077,42.6640590509798585],"hsluv":[17.3320761189885637,100.000000000002302,42.6640590509798585]},"#bb3311":{"lch":[42.7251747888925806,112.6335820513806,16.4819551739351198],"luv":[42.7251747888925806,108.005370801027979,31.9556518296457135],"rgb":[0.733333333333333282,0.2,0.0666666666666666657],"xyz":[0.21778000659911903,0.129747496423764958,0.0188801419676419349],"hpluv":[16.4819551739351198,334.52099084556113,42.7251747888925806],"hsluv":[16.4819551739351198,95.1490253673008368,42.7251747888925806]},"#bb3322":{"lch":[42.8381318005571785,109.688338781622747,14.8808580240480524],"luv":[42.8381318005571785,106.009603708482885,28.1690536980292627],"rgb":[0.733333333333333282,0.2,0.133333333333333331],"xyz":[0.219655364737596032,0.130497639679155786,0.0287570281636211345],"hpluv":[14.8808580240480524,324.914627119009424,42.8381318005571785],"hsluv":[14.8808580240480524,86.4181297836030211,42.8381318005571785]},"#bb3333":{"lch":[43.023174549414108,105.246046554892928,12.1770506300618351],"luv":[43.023174549414108,102.878058957341324,22.1998941575065203],"rgb":[0.733333333333333282,0.2,0.2],"xyz":[0.222743115470053765,0.131732739972138885,0.0450191820212322777],"hpluv":[12.1770506300618351,310.414975564112126,43.023174549414108],"hsluv":[12.1770506300618351,72.7398502888125762,43.023174549414108]},"#bb3344":{"lch":[43.2883038991094082,99.6704509181560496,8.14070356751482116],"luv":[43.2883038991094082,98.6661026897846085,14.1137863891102171],"rgb":[0.733333333333333282,0.2,0.266666666666666663],"xyz":[0.227201110714272653,0.133515938069826479,0.0684979569741189231],"hpluv":[8.14070356751482116,292.169703441320848,43.2883038991094082],"hsluv":[8.14070356751482116,73.8775464962187556,43.2883038991094082]},"#bb3355":{"lch":[43.6392404977582515,93.6285749325397632,2.54995992142812078],"luv":[43.6392404977582515,93.5358645919991289,4.16558266337591299],"rgb":[0.733333333333333282,0.2,0.333333333333333315],"xyz":[0.233163524753634666,0.135900903685571312,0.0999000042480928246],"hpluv":[2.54995992142812078,272.251672456619758,43.6392404977582515],"hsluv":[2.54995992142812078,75.2585830443305781,43.6392404977582515]},"#bb3366":{"lch":[44.0797950159491521,88.0182600678664784,355.263953050872033],"luv":[44.0797950159491521,87.7177339493983794,-7.26727295188107547],"rgb":[0.733333333333333282,0.2,0.4],"xyz":[0.240748520527142823,0.138934901994974602,0.1398476486552368],"hpluv":[355.263953050872033,253.380121177946961,44.0797950159491521],"hsluv":[355.263953050872033,76.8177075569623753,44.0797950159491521]},"#bb3377":{"lch":[44.6120878205181057,83.829516929164356,346.367941021132197],"luv":[44.6120878205181057,81.4679789337245239,-19.757437005625782],"rgb":[0.733333333333333282,0.2,0.466666666666666674],"xyz":[0.250062533547344756,0.142660507203055426,0.188901450561634709],"hpluv":[346.367941021132197,238.442541154787421,44.6120878205181057],"hsluv":[346.367941021132197,78.4827471040858597,44.6120878205181057]},"#bb3388":{"lch":[45.2367248685103078,81.924239827592,336.329010851829594],"luv":[45.2367248685103078,75.03162551729379,-32.8912791414593499],"rgb":[0.733333333333333282,0.2,0.533333333333333326],"xyz":[0.261202950649288557,0.147116674043833023,0.247574313965206849],"hpluv":[336.329010851829594,229.805591899252,45.2367248685103078],"hsluv":[336.329010851829594,80.18501002925629,45.2367248685103078]},"#bb3399":{"lch":[45.9529692994627226,82.7837935230449347,325.982908927834501],"luv":[45.9529692994627226,68.6170634488305495,-46.3125800806357404],"rgb":[0.733333333333333282,0.2,0.6],"xyz":[0.274259914758361312,0.152339459687462181,0.316340991606324784],"hpluv":[325.982908927834501,228.597286714525296,45.9529692994627226],"hsluv":[325.982908927834501,81.8663863744617402,45.9529692994627226]},"#bb33aa":{"lch":[46.7589216358443664,86.3774619636168524,316.238480868355282],"luv":[46.7589216358443664,62.3839556422166126,-59.7436859735489136],"rgb":[0.733333333333333282,0.2,0.66666666666666663],"xyz":[0.289317607723613812,0.158362536873563275,0.395644841223323385],"hpluv":[316.238480868355282,234.409537876970433,46.7589216358443664],"hsluv":[316.238480868355282,83.4827024616804181,46.7589216358443664]},"#bb33bb":{"lch":[47.6517090930198108,92.2657594707273461,307.715012949243828],"luv":[47.6517090930198108,56.4421334605023191,-72.9880534138084585],"rgb":[0.733333333333333282,0.2,0.733333333333333282],"xyz":[0.306455199830950487,0.165217573716498034,0.485902826321965131],"hpluv":[307.715012949243828,245.697877980233102,47.6517090930198108],"hsluv":[307.715012949243828,85.0039827354176,47.6517090930198108]},"#bb33cc":{"lch":[48.6276786348411179,99.8443429984049402,300.621719827817344],"luv":[48.6276786348411179,50.8574804969275078,-85.9209491700817551],"rgb":[0.733333333333333282,0.2,0.8],"xyz":[0.325747575274672241,0.172934523893986836,0.587509336992235287],"hpluv":[300.621719827817344,260.542905615006589,48.6276786348411179],"hsluv":[300.621719827817344,86.4127454729900535,48.6276786348411179]},"#bb33dd":{"lch":[49.6825862492002273,108.545865187730342,294.87630802524211],"luv":[49.6825862492002273,45.6609809337446322,-98.4747666639588459],"rgb":[0.733333333333333282,0.2,0.866666666666666696],"xyz":[0.347265900825305729,0.18154185411424037,0.700839184892241285],"hpluv":[294.87630802524211,277.235228758227834,49.6825862492002273],"hsluv":[294.87630802524211,87.70141038259,49.6825862492002273]},"#bb33ee":{"lch":[50.8117750205940695,117.927813495206621,290.271422146528892],"luv":[50.8117750205940695,40.8581913283156268,-110.623584271795281],"rgb":[0.733333333333333282,0.2,0.933333333333333348],"xyz":[0.371078081091480494,0.191066726220710414,0.826250000960764508],"hpluv":[290.271422146528892,294.504005794210514,50.8117750205940695],"hsluv":[290.271422146528892,88.8695912604113687,50.8117750205940695]},"#bb33ff":{"lch":[52.0103359867018611,127.679308171663493,286.581788346289272],"luv":[52.0103359867018611,36.4375993761859931,-122.36955130625914],"rgb":[0.733333333333333282,0.2,1],"xyz":[0.39724912950131186,0.201535145584643111,0.964084189252546353],"hpluv":[286.581788346289272,311.508705442628695,52.0103359867018611],"hsluv":[286.581788346289272,99.9999999999991616,52.0103359867018611]},"#994400":{"lch":[39.4244247356725168,77.6708634712958315,27.0445710144404678],"luv":[39.4244247356725168,69.1777945884316097,35.3156589667733627],"rgb":[0.6,0.266666666666666663,0],"xyz":[0.152036077002273062,0.109076103359438958,0.0130478755429292749],"hpluv":[27.0445710144404678,249.995444431237956,39.4244247356725168],"hsluv":[27.0445710144404678,100.000000000002302,39.4244247356725168]},"#994411":{"lch":[39.4928806474909351,75.8240556098730849,25.7566327743493559],"luv":[39.4928806474909351,68.2907795083206395,32.9493071744317447],"rgb":[0.6,0.266666666666666663,0.0666666666666666657],"xyz":[0.153047742501910194,0.109480769559293811,0.0183759805076849081],"hpluv":[25.7566327743493559,243.628181561178451,39.4928806474909351],"hsluv":[25.7566327743493559,94.1783894720599,39.4928806474909351]},"#994422":{"lch":[39.6193348047394807,72.6128884539244268,23.2788782073808527],"luv":[39.6193348047394807,66.7016282141236161,28.6971141964989123],"rgb":[0.6,0.266666666666666663,0.133333333333333331],"xyz":[0.154923100640387196,0.110230912814684626,0.0282528667036641],"hpluv":[23.2788782073808527,232.565805292122405,39.6193348047394807],"hsluv":[23.2788782073808527,83.7619004180350402,39.6193348047394807]},"#994433":{"lch":[39.8262957210095,67.9099451463512764,18.9473520481579776],"luv":[39.8262957210095,64.2304033034813671,22.0503047882012062],"rgb":[0.6,0.266666666666666663,0.2],"xyz":[0.158010851372844929,0.111466013107667739,0.0445150205612752509],"hpluv":[18.9473520481579776,216.372863201479333,39.8262957210095],"hsluv":[18.9473520481579776,67.5996848307310358,39.8262957210095]},"#994444":{"lch":[40.1224193460439267,62.3513134554678956,12.1770506300619097],"luv":[40.1224193460439267,60.9484376060972082,13.1519672672071142],"rgb":[0.6,0.266666666666666663,0.266666666666666663],"xyz":[0.162468846617063817,0.113249211205355318,0.0679937955141618894],"hpluv":[12.1770506300619097,197.195872414250289,40.1224193460439267],"hsluv":[12.1770506300619097,46.2091051210312429,40.1224193460439267]},"#994455":{"lch":[40.5136546800823041,57.0624194645929776,2.37288379618767387],"luv":[40.5136546800823041,57.0134905267935324,2.36254377830001205],"rgb":[0.6,0.266666666666666663,0.333333333333333315],"xyz":[0.16843126065642583,0.115634176821100151,0.0993958427881357909],"hpluv":[2.37288379618767387,178.726144329621945,40.5136546800823041],"hsluv":[2.37288379618767387,49.5312591923758063,40.5136546800823041]},"#994466":{"lch":[41.0036603670202382,53.5416261730848646,349.413399835018254],"luv":[41.0036603670202382,52.6302589877717111,-9.83674601372026558],"rgb":[0.6,0.266666666666666663,0.4],"xyz":[0.176016256429934,0.11866817513050347,0.139343487195279753],"hpluv":[349.413399835018254,165.694562401887765,41.0036603670202382],"hsluv":[349.413399835018254,53.2076295784804643,41.0036603670202382]},"#994477":{"lch":[41.594070304433572,53.2098960104776424,334.460192523955527],"luv":[41.594070304433572,48.0105420863306946,-22.9408125841809181],"rgb":[0.6,0.266666666666666663,0.466666666666666674],"xyz":[0.18533026945013592,0.122393780338584279,0.188397289101677662],"hpluv":[334.460192523955527,162.330570569563577,41.594070304433572],"hsluv":[334.460192523955527,57.0495308436177666,41.594070304433572]},"#994488":{"lch":[42.2847251453823887,56.6612659292255287,319.901700116735],"luv":[42.2847251453823887,43.3424978513170416,-36.4955742071691631],"rgb":[0.6,0.266666666666666663,0.533333333333333326],"xyz":[0.196470686552079721,0.126849947179361877,0.247070152505249829],"hpluv":[319.901700116735,170.036472949794188,42.2847251453823887],"hsluv":[319.901700116735,60.8903164523640683,42.2847251453823887]},"#994499":{"lch":[43.0739091348830314,63.3829857303906,307.715012949244226],"luv":[43.0739091348830314,38.7735489334465555,-50.1399519665159232],"rgb":[0.6,0.266666666666666663,0.6],"xyz":[0.209527650661152448,0.132072732822991035,0.315836830146367764],"hpluv":[307.715012949244226,186.722963823125951,43.0739091348830314],"hsluv":[307.715012949244226,64.600458594127474,43.0739091348830314]},"#9944aa":{"lch":[43.9586008361636686,72.3252063731545,298.405725418599673],"luv":[43.9586008361636686,34.4059763632637896,-63.6173267861038099],"rgb":[0.6,0.266666666666666663,0.66666666666666663],"xyz":[0.224585343626404976,0.138095810009092129,0.395140679763366365],"hpluv":[298.405725418599673,208.77819920337123,43.9586008361636686],"hsluv":[298.405725418599673,68.0913106207235,43.9586008361636686]},"#9944bb":{"lch":[44.9347323991438827,82.5300732915554676,291.540124858279853],"luv":[44.9347323991438827,30.3011407548278626,-76.7662286846607316],"rgb":[0.6,0.266666666666666663,0.733333333333333282],"xyz":[0.241722935733741651,0.144950846852026888,0.485398664862008111],"hpluv":[291.540124858279853,233.060888419388505,44.9347323991438827],"hsluv":[291.540124858279853,71.3111773355981882,44.9347323991438827]},"#9944cc":{"lch":[45.9974464532923903,93.3382836250318206,286.486143775676851],"luv":[45.9974464532923903,26.4878609436744341,-89.5009967134190561],"rgb":[0.6,0.266666666666666663,0.8],"xyz":[0.261015311177463349,0.152667797029515689,0.587005175532278267],"hpluv":[286.486143775676851,257.492992496327645,45.9974464532923903],"hsluv":[286.486143775676851,74.2376853125076792,45.9974464532923903]},"#9944dd":{"lch":[47.1413389271288139,104.350309752399141,282.717215233582351],"luv":[47.1413389271288139,22.9716047676972792,-101.790434323753402],"rgb":[0.6,0.266666666666666663,0.866666666666666696],"xyz":[0.282533636728096949,0.161275127249769223,0.700335023432284265],"hpluv":[282.717215233582351,280.886686990529654,47.1413389271288139],"hsluv":[282.717215233582351,78.691216526215527,47.1413389271288139]},"#9944ee":{"lch":[48.3606780479664593,115.341161543855208,279.855683836472622],"luv":[48.3606780479664593,19.7426125181249787,-113.638958096441911],"rgb":[0.6,0.266666666666666663,0.933333333333333348],"xyz":[0.306345816994271658,0.170799999356239268,0.825745839500807488],"hpluv":[279.855683836472622,302.643440789384783,48.3606780479664593],"hsluv":[279.855683836472622,89.2619995530309325,48.3606780479664593]},"#9944ff":{"lch":[49.6495929972458185,126.19285787586071,277.642335930208503],"luv":[49.6495929972458185,16.7822322716138856,-125.071955525044785],"rgb":[0.6,0.266666666666666663,1],"xyz":[0.332516865404103079,0.181268418720171964,0.963580027792589333],"hpluv":[277.642335930208503,322.521305960549284,49.6495929972458185],"hsluv":[277.642335930208503,99.9999999999991616,49.6495929972458185]},"#bb4400":{"lch":[45.2216387767487547,104.837609625168909,21.4216552556228201],"luv":[45.2216387767487547,97.5952013308911,38.2896992558330354],"rgb":[0.733333333333333282,0.266666666666666663,0],"xyz":[0.225600911582447911,0.147007971189842435,0.0164962271638749],"hpluv":[21.4216552556228201,294.177965476355098,45.2216387767487547],"hsluv":[21.4216552556228201,100.000000000002373,45.2216387767487547]},"#bb4411":{"lch":[45.2777618800582076,103.283777149094803,20.576768268141489],"luv":[45.2777618800582076,96.6944911384892123,36.3003306548646947],"rgb":[0.733333333333333282,0.266666666666666663,0.0666666666666666657],"xyz":[0.226612577082085043,0.147412637389697287,0.0218243321286305317],"hpluv":[20.576768268141489,289.458620037032802,45.2777618800582076],"hsluv":[20.576768268141489,95.6967439910137614,45.2777618800582076]},"#bb4422":{"lch":[45.3815280810129238,100.53232916519147,18.9799525675269258],"luv":[45.3815280810129238,95.0666309197234,32.6968636561903381],"rgb":[0.733333333333333282,0.266666666666666663,0.133333333333333331],"xyz":[0.228487935220562044,0.148162780645088116,0.0317012183246097243],"hpluv":[18.9799525675269258,281.103307599105051,45.3815280810129238],"hsluv":[18.9799525675269258,87.925891065222288,45.3815280810129238]},"#bb4433":{"lch":[45.5516172521931111,96.3559005693685862,16.2666991179303722],"luv":[45.5516172521931111,92.4986058403436147,26.9901369416087924],"rgb":[0.733333333333333282,0.266666666666666663,0.2],"xyz":[0.231575685953019805,0.149397880938071215,0.0479633721822208675],"hpluv":[16.2666991179303722,268.419362556396,45.5516172521931111],"hsluv":[16.2666991179303722,75.6846484949249572,45.5516172521931111]},"#bb4444":{"lch":[45.7955406359936816,91.066890863790789,12.177050630061844],"luv":[45.7955406359936816,89.0179277419259734,19.2090382927107299],"rgb":[0.733333333333333282,0.266666666666666663,0.266666666666666663],"xyz":[0.236033681197238665,0.151181079035758809,0.0714421471351075],"hpluv":[12.177050630061844,252.334507458167678,45.7955406359936816],"hsluv":[12.177050630061844,59.1297963696904461,45.7955406359936816]},"#bb4455":{"lch":[46.1187996938414813,85.2741675307746,6.43569277192082279],"luv":[46.1187996938414813,84.7367941199702273,9.55820957796975],"rgb":[0.733333333333333282,0.266666666666666663,0.333333333333333315],"xyz":[0.24199609523660065,0.153566044651503641,0.102844194409081421],"hpluv":[6.43569277192082279,234.627449284537505,46.1187996938414813],"hsluv":[6.43569277192082279,61.0765315010866274,46.1187996938414813]},"#bb4466":{"lch":[46.5252276318027427,79.8426568240615637,358.82639812637143],"luv":[46.5252276318027427,79.8259079304732779,-1.63532009113408461],"rgb":[0.733333333333333282,0.266666666666666663,0.4],"xyz":[0.249581091010108835,0.156600042960906932,0.142791838816225369],"hpluv":[358.82639812637143,217.763856882437722,46.5252276318027427],"hsluv":[358.82639812637143,63.3003300169989842,46.5252276318027427]},"#bb4477":{"lch":[47.0171837667790697,75.785442181693,349.367581794189107],"luv":[47.0171837667790697,74.484290362097866,-13.9829802234512588],"rgb":[0.733333333333333282,0.266666666666666663,0.466666666666666674],"xyz":[0.258895104030310741,0.160325648168987756,0.191845640722623278],"hpluv":[349.367581794189107,204.535408840651428,47.0171837667790697],"hsluv":[349.367581794189107,65.7062458495858266,47.0171837667790697]},"#bb4488":{"lch":[47.5956997014540235,74.0450948660102,338.538246495536782],"luv":[47.5956997014540235,68.9109568360576219,-27.0916241974425098],"rgb":[0.733333333333333282,0.266666666666666663,0.533333333333333326],"xyz":[0.270035521132254597,0.164781815009765353,0.250518504126195474],"hpluv":[338.538246495536782,197.409434601059019,47.5956997014540235],"hsluv":[338.538246495536782,68.1997676790361,47.5956997014540235]},"#bb4499":{"lch":[48.2606154557730633,75.1911240047971,327.313188255720945],"luv":[48.2606154557730633,63.2834900243205496,-40.6067115074158309],"rgb":[0.733333333333333282,0.266666666666666663,0.6],"xyz":[0.283092485241327296,0.170004600653394511,0.319285181767313353],"hpluv":[327.313188255720945,197.702903480158483,48.2606154557730633],"hsluv":[327.313188255720945,70.6969578310621074,48.2606154557730633]},"#bb44aa":{"lch":[49.0107199856960278,79.2228796099941093,316.794363507436401],"luv":[49.0107199856960278,57.7456584584256944,-54.2374739723603838],"rgb":[0.733333333333333282,0.266666666666666663,0.66666666666666663],"xyz":[0.298150178206579852,0.176027677839495605,0.398589031384311954],"hpluv":[316.794363507436401,205.115683333718124,49.0107199856960278],"hsluv":[316.794363507436401,73.1302855273877128,49.0107199856960278]},"#bb44bb":{"lch":[49.8438993628519427,85.6636869410227746,307.715012949243942],"luv":[49.8438993628519427,52.4034189799077268,-67.7653963284049752],"rgb":[0.733333333333333282,0.266666666666666663,0.733333333333333282],"xyz":[0.315287770313916471,0.182882714682430364,0.4888470164829537],"hpluv":[307.715012949243942,218.084137693810391,49.8438993628519427],"hsluv":[307.715012949243942,75.450469608388417,49.8438993628519427]},"#bb44cc":{"lch":[50.757290285110841,93.8478600934752905,300.284565440631638],"luv":[50.757290285110841,47.3270085455435918,-81.0405769121528152],"rgb":[0.733333333333333282,0.266666666666666663,0.8],"xyz":[0.334580145757638225,0.190599664859919166,0.590453527153223856],"hpluv":[300.284565440631638,234.620130462749955,50.757290285110841],"hsluv":[300.284565440631638,77.6254237907312898,50.757290285110841]},"#bb44dd":{"lch":[51.7474340276366291,103.158361374368454,294.364201848969515],"luv":[51.7474340276366291,42.5564715489483518,-93.971241615445],"rgb":[0.733333333333333282,0.266666666666666663,0.866666666666666696],"xyz":[0.356098471308271769,0.1992069950801727,0.703783375053229854],"hpluv":[294.364201848969515,252.961799427415912,51.7474340276366291],"hsluv":[294.364201848969515,79.6375689955678467,51.7474340276366291]},"#bb44ee":{"lch":[52.8104252671910217,113.122924260907325,289.686672533024307],"luv":[52.8104252671910217,38.1084271425454304,-106.510768347901248],"rgb":[0.733333333333333282,0.266666666666666663,0.933333333333333348],"xyz":[0.379910651574446478,0.208731867186642744,0.829194191121753077],"hpluv":[289.686672533024307,271.813038246621943,52.8104252671910217],"hsluv":[289.686672533024307,87.7449679178180872,52.8104252671910217]},"#bb44ff":{"lch":[53.942050711908152,123.415863319803691,285.982908620336502],"luv":[53.942050711908152,33.9826318144238115,-118.645084406973112],"rgb":[0.733333333333333282,0.266666666666666663,1],"xyz":[0.4060816999842779,0.219200286550575441,0.967028379413534922],"hpluv":[285.982908620336502,290.323946696930363,53.942050711908152],"hsluv":[285.982908620336502,99.9999999999990621,53.942050711908152]},"#995500":{"lch":[43.167672396478018,69.2675138179999,36.3951762413548678],"luv":[43.167672396478018,55.7564526526882105,41.099956911356287],"rgb":[0.6,0.333333333333333315,0],"xyz":[0.163849333716619028,0.132702616788131222,0.0169856277810444857],"hpluv":[36.3951762413548678,203.615246511519132,43.167672396478018],"hsluv":[36.3951762413548678,100.000000000002288,43.167672396478018]},"#995511":{"lch":[43.2277537555276865,67.4837391190291385,35.2266717066771307],"luv":[43.2277537555276865,55.1258789529511333,38.9254738590266101],"rgb":[0.6,0.333333333333333315,0.0666666666666666657],"xyz":[0.16486099921625616,0.133107282987986075,0.0223137327458001189],"hpluv":[35.2266717066771307,198.096040704981476,43.2277537555276865],"hsluv":[35.2266717066771307,95.1659583326808303,43.2277537555276865]},"#995522":{"lch":[43.3388072781739,64.3407602415628475,32.9528815923873708],"luv":[43.3388072781739,53.9895016234129059,34.998101990218963],"rgb":[0.6,0.333333333333333315,0.133333333333333331],"xyz":[0.166736357354733161,0.133857426243376904,0.0321906189417793115],"hpluv":[32.9528815923873708,188.385971738918272,43.3388072781739],"hsluv":[32.9528815923873708,86.4646465379692302,43.3388072781739]},"#995533":{"lch":[43.5207548807750584,59.6262244551406582,28.8908620435756234],"luv":[43.5207548807750584,52.2052395636471,28.8079781462883915],"rgb":[0.6,0.333333333333333315,0.2],"xyz":[0.169824108087190895,0.13509252653636,0.0484527727993904617],"hpluv":[28.8908620435756234,173.852210644027934,43.5207548807750584],"hsluv":[28.8908620435756234,72.8304069554253601,43.5207548807750584]},"#995544":{"lch":[43.7814988718974831,53.8284560366537335,22.2989672577237812],"luv":[43.7814988718974831,49.8029788080235036,20.4246415179685634],"rgb":[0.6,0.333333333333333315,0.266666666666666663],"xyz":[0.174282103331409782,0.136875724634047596,0.0719315477522771],"hpluv":[22.2989672577237812,156.01294104827457,43.7814988718974831],"hsluv":[22.2989672577237812,54.5318604429391058,43.7814988718974831]},"#995555":{"lch":[44.1267187000120629,47.9518139182857226,12.1770506300620411],"luv":[44.1267187000120629,46.8729201797035,10.1146335514957979],"rgb":[0.6,0.333333333333333315,0.333333333333333315],"xyz":[0.180244517370771795,0.139260690249792429,0.103333595026251],"hpluv":[12.1770506300620411,137.893162706519348,44.1267187000120629],"hsluv":[12.1770506300620411,32.3126421104369754,44.1267187000120629]},"#995566":{"lch":[44.5602350881765048,43.578232165907,357.727809148728397],"luv":[44.5602350881765048,43.5439690351937116,-1.72773822316436432],"rgb":[0.6,0.333333333333333315,0.4],"xyz":[0.187829513144279953,0.14229468855919572,0.143281239433394963],"hpluv":[357.727809148728397,124.097051059849122,44.5602350881765048],"hsluv":[357.727809148728397,36.5660257696708157,44.5602350881765048]},"#995577":{"lch":[45.0842241078155226,42.5628566452735342,339.858530865537546],"luv":[45.0842241078155226,39.9599368331855729,-14.6560640723873874],"rgb":[0.6,0.333333333333333315,0.466666666666666674],"xyz":[0.197143526164481886,0.146020293767276543,0.192335041339792873],"hpluv":[339.858530865537546,119.796876557388956,45.0842241078155226],"hsluv":[339.858530865537546,41.1101378179314167,45.0842241078155226]},"#995588":{"lch":[45.699386409692309,45.957423726275,322.088602167082399],"luv":[45.699386409692309,36.2586549471185506,-28.2381787122006145],"rgb":[0.6,0.333333333333333315,0.533333333333333326],"xyz":[0.208283943266425686,0.150476460608054141,0.25100790474336504],"hpluv":[322.088602167082399,127.609977655436467,45.699386409692309],"hsluv":[322.088602167082399,45.7577454208568852,45.699386409692309]},"#995599":{"lch":[46.4051108942887964,53.2218555896971921,307.715012949244795],"luv":[46.4051108942887964,32.5576366947089113,-42.1018551285561102],"rgb":[0.6,0.333333333333333315,0.6],"xyz":[0.221340907375498414,0.155699246251683299,0.319774582384483],"hpluv":[307.715012949244795,145.533684272522947,46.4051108942887964],"hsluv":[307.715012949244795,50.3502223422482516,46.4051108942887964]},"#9955aa":{"lch":[47.1996461355186625,63.0010233462712037,297.353030705211779],"luv":[47.1996461355186625,28.9471952899390068,-55.9570266143899246],"rgb":[0.6,0.333333333333333315,0.66666666666666663],"xyz":[0.236398600340750942,0.161722323437784393,0.399078432001481576],"hpluv":[297.353030705211779,169.374563019623821,47.1996461355186625],"hsluv":[297.353030705211779,54.7667714505238337,47.1996461355186625]},"#9955bb":{"lch":[48.0802807126223541,74.1194144420538,290.114722102094788],"luv":[48.0802807126223541,25.4897394646759068,-69.5985688017783701],"rgb":[0.6,0.333333333333333315,0.733333333333333282],"xyz":[0.253536192448087616,0.168577360280719152,0.489336417100123322],"hpluv":[290.114722102094788,195.615971831826613,48.0802807126223541],"hsluv":[290.114722102094788,58.9252289891592866,48.0802807126223541]},"#9955cc":{"lch":[49.0435277691913,85.8237639836856658,285.007043429489613],"luv":[49.0435277691913,22.2230153813451068,-82.8966588692685491],"rgb":[0.6,0.333333333333333315,0.8],"xyz":[0.272828567891809315,0.176294310458207953,0.590942927770393478],"hpluv":[285.007043429489613,222.057364979540267,49.0435277691913],"hsluv":[285.007043429489613,65.256702758776143,49.0435277691913]},"#9955dd":{"lch":[50.0853068419578875,97.6800340866365104,281.315028513382344],"luv":[50.0853068419578875,19.1651498984824649,-95.7814496055220843],"rgb":[0.6,0.333333333333333315,0.866666666666666696],"xyz":[0.294346893442442914,0.184901640678461487,0.704272775670399476],"hpluv":[281.315028513382344,247.476970093373268,50.0853068419578875],"hsluv":[281.315028513382344,76.6956878028438638,50.0853068419578875]},"#9955ee":{"lch":[51.2011159126469266,109.450459224116145,278.575243894560685],"luv":[51.2011159126469266,16.3199513369978568,-108.226901520499666],"rgb":[0.6,0.333333333333333315,0.933333333333333348],"xyz":[0.318159073708617623,0.194426512784931532,0.829683591738922699],"hpluv":[278.575243894560685,271.254835109068836,51.2011159126469266],"hsluv":[278.575243894560685,88.2491190723243335,51.2011159126469266]},"#9955ff":{"lch":[52.3861878346365444,121.012399839465246,276.491711029928183],"luv":[52.3861878346365444,13.6815981187824764,-120.2364952409323],"rgb":[0.6,0.333333333333333315,1],"xyz":[0.344330122118449045,0.204894932148864228,0.967517780030704544],"hpluv":[276.491711029928183,293.124692446110771,52.3861878346365444],"hsluv":[276.491711029928183,99.9999999999991,52.3861878346365444]},"#bb5500":{"lch":[48.3398816318057811,94.9450628471467724,27.1627331553413143],"luv":[48.3398816318057811,84.4739036935134,43.344256295703957],"rgb":[0.733333333333333282,0.333333333333333315,0],"xyz":[0.237414168296793876,0.170634484618534699,0.0204339794019901093],"hpluv":[27.1627331553413143,249.233335779464397,48.3398816318057811],"hsluv":[27.1627331553413143,100.000000000002217,48.3398816318057811]},"#bb5511":{"lch":[48.3907029738951735,93.4795954244126364,26.3417432533787057],"luv":[48.3907029738951735,83.7729911103365907,41.4791600823755289],"rgb":[0.733333333333333282,0.333333333333333315,0.0666666666666666657],"xyz":[0.238425833796431,0.171039150818389551,0.0257620843667457425],"hpluv":[26.3417432533787057,245.128732426237889,48.3907029738951735],"hsluv":[26.3417432533787057,96.2613278044251786,48.3907029738951735]},"#bb5522":{"lch":[48.4847005727335869,90.8707197847641623,24.7826102649670759],"luv":[48.4847005727335869,82.5019575685759321,38.090874386840035],"rgb":[0.733333333333333282,0.333333333333333315,0.133333333333333331],"xyz":[0.240301191934908,0.17178929407378038,0.0356389705627249351],"hpluv":[24.7826102649670759,237.825586669453713,48.4847005727335869],"hsluv":[24.7826102649670759,89.48684037186257,48.4847005727335869]},"#bb5533":{"lch":[48.6388719159228629,86.8743588299812473,22.1104535643633149],"luv":[48.6388719159228629,80.4856161939384407,32.6989267102511363],"rgb":[0.733333333333333282,0.333333333333333315,0.2],"xyz":[0.243388942667365771,0.173024394366763479,0.0519011244203360783],"hpluv":[22.1104535643633149,226.64567974804504,48.6388719159228629],"hsluv":[22.1104535643633149,78.7542493880857393,48.6388719159228629]},"#bb5544":{"lch":[48.8601705631915,81.7431600256382751,18.0266646696809296],"luv":[48.8601705631915,77.730600917119915,25.2962031151029265],"rgb":[0.733333333333333282,0.333333333333333315,0.266666666666666663],"xyz":[0.24784693791158463,0.174807592464451073,0.0753798993732227168],"hpluv":[18.0266646696809296,212.293047020031764,48.8601705631915],"hsluv":[18.0266646696809296,64.1199207289341,48.8601705631915]},"#bb5555":{"lch":[49.1538097277392154,76.0172073873862075,12.1770506300619399],"luv":[49.1538097277392154,74.3068552156307,16.0345591439297159],"rgb":[0.733333333333333282,0.333333333333333315,0.333333333333333315],"xyz":[0.253809351950946616,0.177192558080195905,0.106781946647196632],"hpluv":[12.1770506300619399,196.242945408672853,49.1538097277392154],"hsluv":[12.1770506300619399,45.9858047870319879,49.1538097277392154]},"#bb5566":{"lch":[49.523574907380123,70.5220596563995,4.21567942747197],"luv":[49.523574907380123,70.3312550088346882,5.18415538569556134],"rgb":[0.733333333333333282,0.333333333333333315,0.4],"xyz":[0.261394347724454801,0.180226556389599196,0.14672959105434058],"hpluv":[4.21567942747197,180.697576197923894,49.523574907380123],"hsluv":[4.21567942747197,48.7291682320237527,49.523574907380123]},"#bb5577":{"lch":[49.971995559373525,66.3094111666939341,354.014227306533371],"luv":[49.971995559373525,65.9478803557508257,-6.91484532417379327],"rgb":[0.733333333333333282,0.333333333333333315,0.466666666666666674],"xyz":[0.270708360744656706,0.18395216159768002,0.195783392960738489],"hpluv":[354.014227306533371,168.378953180241098,49.971995559373525],"hsluv":[354.014227306533371,51.7390719561838495,49.971995559373525]},"#bb5588":{"lch":[50.5004659153875508,64.4571905510646275,342.016521446261379],"luv":[50.5004659153875508,61.308172080607541,-19.9006896832966476],"rgb":[0.733333333333333282,0.333333333333333315,0.533333333333333326],"xyz":[0.281848777846600562,0.188408328438457617,0.254456256364310685],"hpluv":[342.016521446261379,161.962814057843559,50.5004659153875508],"hsluv":[342.016521446261379,54.9055054808170055,50.5004659153875508]},"#bb5599":{"lch":[51.1093507584050286,65.6961991151429459,329.411862939203161],"luv":[51.1093507584050286,56.5544024759803,-33.4303774845774342],"rgb":[0.733333333333333282,0.333333333333333315,0.6],"xyz":[0.294905741955673262,0.193631114082086775,0.323222934005428564],"hpluv":[329.411862939203161,163.109481188372769,51.1093507584050286],"hsluv":[329.411862939203161,58.1255686218068561,51.1093507584050286]},"#bb55aa":{"lch":[51.7980911374347386,70.0901192661774246,317.660759061539352],"luv":[51.7980911374347386,51.8085124997667563,-47.2070212077450151],"rgb":[0.733333333333333282,0.333333333333333315,0.66666666666666663],"xyz":[0.309963434920925818,0.199654191268187869,0.402526783622427164],"hpluv":[317.660759061539352,171.704773930815691,51.7980911374347386],"hsluv":[317.660759061539352,61.3115173935257403,51.7980911374347386]},"#bb55bb":{"lch":[52.5653152299933737,77.1031380177621344,307.715012949244226],"luv":[52.5653152299933737,47.1666372355911179,-60.9934605025180332],"rgb":[0.733333333333333282,0.333333333333333315,0.733333333333333282],"xyz":[0.327101027028262437,0.206509228111122628,0.492784768721068911],"hpluv":[307.715012949244226,186.128169856082764,52.5653152299933737],"hsluv":[307.715012949244226,64.3946779967479,52.5653152299933737]},"#bb55cc":{"lch":[53.4089544864585,85.9678373228364308,299.780474196008072],"luv":[53.4089544864585,42.6983512805399883,-74.6144748148057175],"rgb":[0.733333333333333282,0.333333333333333315,0.8],"xyz":[0.346393402471984191,0.21422617828861143,0.594391279391339067],"hpluv":[299.780474196008072,204.249617293250537,53.4089544864585],"hsluv":[299.780474196008072,67.3259326792693855,53.4089544864585]},"#bb55dd":{"lch":[54.3263625650166944,95.9883710948233926,293.613183872979789],"luv":[54.3263625650166944,38.4490902963257213,-87.9513208588848698],"rgb":[0.733333333333333282,0.333333333333333315,0.866666666666666696],"xyz":[0.367911728022617734,0.222833508508864964,0.707721127291345065],"hpluv":[293.613183872979789,224.206046477737118,54.3263625650166944],"hsluv":[293.613183872979789,73.8407928406032283,54.3263625650166944]},"#bb55ee":{"lch":[55.314433433552054,106.647677925948784,288.842761327535072],"luv":[55.314433433552054,34.444226028074695,-100.932266893812525],"rgb":[0.733333333333333282,0.333333333333333315,0.933333333333333348],"xyz":[0.391723908288792444,0.232358380615335,0.833131943359868288],"hpluv":[288.842761327535072,244.653966901481454,55.314433433552054],"hsluv":[288.842761327535072,86.7715876359309135,55.314433433552054]},"#bb55ff":{"lch":[56.3697148536960526,117.598184211748716,285.129655441003138],"luv":[56.3697148536960526,30.6936185759692179,-113.521956944959783],"rgb":[0.733333333333333282,0.333333333333333315,1],"xyz":[0.417894956698623865,0.242826799979267705,0.970966131651650133],"hpluv":[285.129655441003138,264.724480425834031,56.3697148536960526],"hsluv":[285.129655441003138,99.9999999999989,56.3697148536960526]},"#996600":{"lch":[47.3343652017352454,63.4240894393546952,48.3260196362919672],"luv":[47.3343652017352454,42.1701199842588,47.3740023823666476],"rgb":[0.6,0.4,0],"xyz":[0.178877391422465504,0.162758732199824563,0.0219949803496598331],"hpluv":[48.3260196362919672,170.026654750900292,47.3343652017352454],"hsluv":[48.3260196362919672,100.000000000002288,47.3343652017352454]},"#996611":{"lch":[47.3868110627231189,61.667674323653,47.4017350737566616],"luv":[47.3868110627231189,41.7399921999205,45.3946594616449133],"rgb":[0.6,0.4,0.0666666666666666657],"xyz":[0.179889056922102636,0.163163398399679416,0.0273230853144154628],"hpluv":[47.4017350737566616,165.135107398016657,47.3868110627231189],"hsluv":[47.4017350737566616,96.0239926064661,47.3868110627231189]},"#996622":{"lch":[47.4838028017404099,58.5263777304533406,45.5834379771503322],"luv":[47.4838028017404099,40.9608465044279413,41.8036594557031336],"rgb":[0.6,0.4,0.133333333333333331],"xyz":[0.181764415060579637,0.163913541655070244,0.0371999715103946624],"hpluv":[45.5834379771503322,156.40314428015364,47.4838028017404099],"hsluv":[45.5834379771503322,88.8298219708016177,47.4838028017404099]},"#996633":{"lch":[47.642855645786625,53.6803525088045674,42.2629253198225712],"luv":[47.642855645786625,39.7270268335614887,36.1018501525199724],"rgb":[0.6,0.4,0.2],"xyz":[0.184852165793037371,0.165148641948053343,0.0534621253680058056],"hpluv":[42.2629253198225712,142.973945144987511,47.642855645786625],"hsluv":[42.2629253198225712,77.4596172761956865,47.642855645786625]},"#996644":{"lch":[47.8710980897590872,47.4159845831850149,36.6424092143452071],"luv":[47.8710980897590872,38.045445264132745,28.298757722676072],"rgb":[0.6,0.4,0.266666666666666663],"xyz":[0.189310161037256258,0.166931840045740937,0.0769409003208924441],"hpluv":[36.6424092143452071,125.687101185572914,47.8710980897590872],"hsluv":[36.6424092143452071,62.0095295256686185,47.8710980897590872]},"#996655":{"lch":[48.173837669734425,40.4765536471140521,27.3183313201514686],"luv":[48.173837669734425,35.9622216701857838,18.5760600691352664],"rgb":[0.6,0.4,0.333333333333333315],"xyz":[0.195272575076618271,0.16931680566148577,0.108342947594866346],"hpluv":[27.3183313201514686,106.618264590322553,48.173837669734425],"hsluv":[27.3183313201514686,42.9499413016611484,48.173837669734425]},"#996666":{"lch":[48.5548823199147819,34.3240193245421,12.1770506300621335],"luv":[48.5548823199147819,33.551744690774747,7.24007809326721219],"rgb":[0.6,0.4,0.4],"xyz":[0.202857570850126429,0.17235080397088906,0.148290592002010307],"hpluv":[12.1770506300621335,89.702502372613651,48.5548823199147819],"hsluv":[12.1770506300621335,21.0200766933302461,48.5548823199147819]},"#996677":{"lch":[49.0167186013709,31.3606600839303482,350.2076113500313],"luv":[49.0167186013709,30.9037509766054157,-5.33377694282222681],"rgb":[0.6,0.4,0.466666666666666674],"xyz":[0.212171583870328362,0.176076409178969884,0.197344393908408217],"hpluv":[350.2076113500313,81.185839798992177,49.0167186013709],"hsluv":[350.2076113500313,25.8881256225468483,49.0167186013709]},"#996688":{"lch":[49.5606396668562752,33.7929953796712823,326.289263208678278],"luv":[49.5606396668562752,28.1107077320421368,-18.7551232343109682],"rgb":[0.6,0.4,0.533333333333333326],"xyz":[0.223312000972272162,0.180532576019747482,0.256017257311980384],"hpluv":[326.289263208678278,86.5225105267045365,49.5606396668562752],"hsluv":[326.289263208678278,30.9767265160446463,49.5606396668562752]},"#996699":{"lch":[50.1868595811773304,41.2886932006772,307.715012949245818],"luv":[50.1868595811773304,25.2577114783499113,-32.6619686653465351],"rgb":[0.6,0.4,0.6],"xyz":[0.236368965081344889,0.185755361663376639,0.324783934953098319],"hpluv":[307.715012949245818,104.395179003902854,50.1868595811773304],"hsluv":[307.715012949245818,36.1175524455388413,50.1868595811773304]},"#9966aa":{"lch":[50.8946289106688141,51.8448774557822,295.617938374847199],"luv":[50.8946289106688141,22.4160699516755599,-46.7483810021979451],"rgb":[0.6,0.4,0.66666666666666663],"xyz":[0.251426658046597418,0.191778438849477734,0.40408778457009692],"hpluv":[295.617938374847199,129.262701065701,50.8946289106688141],"hsluv":[295.617938374847199,41.1705422178494445,50.8946289106688141]},"#9966bb":{"lch":[51.6823563026294,63.8712345518136,287.908782454232437],"luv":[51.6823563026294,19.6405628457828776,-60.776499523036378],"rgb":[0.6,0.4,0.733333333333333282],"xyz":[0.268564250153934092,0.198633475692412492,0.494345769668738666],"hpluv":[287.908782454232437,156.820318415219759,51.6823563026294],"hsluv":[287.908782454232437,49.349420166275209,51.6823563026294]},"#9966cc":{"lch":[52.5477355185796569,76.4825896496335389,282.819195018988751],"luv":[52.5477355185796569,16.9695880464031816,-74.5762670093482285],"rgb":[0.6,0.4,0.8],"xyz":[0.287856625597655791,0.206350425869901294,0.595952280339008822],"hpluv":[282.819195018988751,184.691924030055,52.5477355185796569],"hsluv":[282.819195018988751,61.7185051859638136,52.5477355185796569]},"#9966dd":{"lch":[53.4878747475352725,89.2117449852098758,279.306611445978092],"luv":[53.4878747475352725,14.4271177471338046,-88.0374563286358],"rgb":[0.6,0.4,0.866666666666666696],"xyz":[0.30937495114828939,0.214957756090154828,0.70928212823901482],"hpluv":[279.306611445978092,211.644028054176175,53.4878747475352725],"hsluv":[279.306611445978092,74.2596178074049362,53.4878747475352725]},"#9966ee":{"lch":[54.4994239962059339,101.810849438236403,276.783380903602506],"luv":[54.4994239962059339,12.0254847729914225,-101.098154183495325],"rgb":[0.6,0.4,0.933333333333333348],"xyz":[0.333187131414464099,0.224482628196624873,0.834692944307538],"hpluv":[276.783380903602506,237.050827216632513,54.4994239962059339],"hsluv":[276.783380903602506,86.9990828065156734,54.4994239962059339]},"#9966ff":{"lch":[55.5786963614876,114.151421142661491,274.908981870437117],"luv":[55.5786963614876,9.76829238934238475,-113.732701597586171],"rgb":[0.6,0.4,1],"xyz":[0.359358179824295521,0.234951047560557569,0.972527132599319888],"hpluv":[274.908981870437117,260.622732185953453,55.5786963614876],"hsluv":[274.908981870437117,99.999999999998991,55.5786963614876]},"#bb6600":{"lch":[51.9152024616159622,85.9194467179265899,34.7713476038742],"luv":[51.9152024616159622,70.5771984524152884,49.0001059480794936],"rgb":[0.733333333333333282,0.4,0],"xyz":[0.252442226002640324,0.200690600030228039,0.0254433319706054567],"hpluv":[34.7713476038742,210.008196913669821,51.9152024616159622],"hsluv":[34.7713476038742,100.000000000002217,51.9152024616159622]},"#bb6611":{"lch":[51.960819173128,84.5067938711160735,34.0102696578751846],"luv":[51.960819173128,70.0508360673827184,47.2681560528436],"rgb":[0.733333333333333282,0.4,0.0666666666666666657],"xyz":[0.253453891502277429,0.201095266230082892,0.0307714369353610864],"hpluv":[34.0102696578751846,206.373990798532162,51.960819173128],"hsluv":[34.0102696578751846,96.7960731817087492,51.960819173128]},"#bb6622":{"lch":[52.0452187907305586,81.9745670334704215,32.5563816919222901],"luv":[52.0452187907305586,69.0932729256005587,44.1129150788451909],"rgb":[0.733333333333333282,0.4,0.133333333333333331],"xyz":[0.255329249640754485,0.20184540948547372,0.040648323131340286],"hpluv":[32.5563816919222901,199.865401092535734,52.0452187907305586],"hsluv":[32.5563816919222901,90.9716633106406221,52.0452187907305586]},"#bb6633":{"lch":[52.1837271506259412,78.04817012610809,30.0375791414029081],"luv":[52.1837271506259412,67.5660884046363,39.0684086920722109],"rgb":[0.733333333333333282,0.4,0.2],"xyz":[0.258417000373212191,0.203080509778456819,0.0569104769889514292],"hpluv":[30.0375791414029081,189.787216830323956,52.1837271506259412],"hsluv":[30.0375791414029081,81.6941023093515639,52.1837271506259412]},"#bb6644":{"lch":[52.3827138306128859,72.9081368603095257,26.1184165145312406],"luv":[52.3827138306128859,65.4632041398932,32.0961886238895318],"rgb":[0.733333333333333282,0.4,0.266666666666666663],"xyz":[0.262874995617431106,0.204863707876144413,0.0803892519418380747],"hpluv":[26.1184165145312406,176.614896915735159,52.3827138306128859],"hsluv":[26.1184165145312406,68.9437006343278824,52.3827138306128859]},"#bb6655":{"lch":[52.6470547760809637,67.004522830646,20.3474245095699864],"luv":[52.6470547760809637,62.823537757634746,23.2982656731697979],"rgb":[0.733333333333333282,0.4,0.333333333333333315],"xyz":[0.268837409656793092,0.207248673491889246,0.111791299215811976],"hpluv":[20.3474245095699864,161.498824171429789,52.6470547760809637],"hsluv":[20.3474245095699864,52.9816895309479534,52.6470547760809637]},"#bb6666":{"lch":[52.9804174131186727,61.0960132663801261,12.1770506300620109],"luv":[52.9804174131186727,59.7213810933874498,12.8871826767560087],"rgb":[0.733333333333333282,0.4,0.4],"xyz":[0.276422405430301277,0.210282671801292537,0.151738943622955924],"hpluv":[12.1770506300620109,146.331162504643544,52.9804174131186727],"hsluv":[12.1770506300620109,34.2899270044314335,52.9804174131186727]},"#bb6677":{"lch":[53.3854132757716826,56.2661599102721226,1.17050216666979279],"luv":[53.3854132757716826,56.2544190111897535,1.14938799445880213],"rgb":[0.733333333333333282,0.4,0.466666666666666674],"xyz":[0.285736418450503182,0.21400827700937336,0.200792745529353833],"hpluv":[1.17050216666979279,133.74082367080041,53.3854132757716826],"hsluv":[1.17050216666979279,37.694842795415525,53.3854132757716826]},"#bb6688":{"lch":[53.8636991644475387,53.7950791600554297,347.554026547444039],"luv":[53.8636991644475387,52.5308766640911458,-11.5938578022448873],"rgb":[0.733333333333333282,0.4,0.533333333333333326],"xyz":[0.296876835552447,0.218464443850150958,0.259465608932926028],"hpluv":[347.554026547444039,126.731828674836166,53.8636991644475387],"hsluv":[347.554026547444039,41.3310399817098855,53.8636991644475387]},"#bb6699":{"lch":[54.4160596975863484,54.7145736516266723,332.78581188167891],"luv":[54.4160596975863484,48.6578429809048814,-25.0219680745716886],"rgb":[0.733333333333333282,0.4,0.6],"xyz":[0.309933799661519682,0.223687229493780115,0.328232286574043908],"hpluv":[332.78581188167891,127.589593839900076,54.4160596975863484],"hsluv":[332.78581188167891,45.0871489409768813,54.4160596975863484]},"#bb66aa":{"lch":[55.0424859024436,59.2427277394444332,319.03138367428437],"luv":[55.0424859024436,44.7323366642012274,-38.8422301956323963],"rgb":[0.733333333333333282,0.4,0.66666666666666663],"xyz":[0.324991492626772238,0.22971030667988121,0.407536136191042508],"hpluv":[319.03138367428437,136.57661144398341,55.0424859024436],"hsluv":[319.03138367428437,48.8627280546895548,55.0424859024436]},"#bb66bb":{"lch":[55.7422560614222,66.7541112543564168,307.715012949244738],"luv":[55.7422560614222,40.8357821803987235,-52.8067255477370452],"rgb":[0.733333333333333282,0.4,0.733333333333333282],"xyz":[0.342129084734108913,0.236565343522815968,0.497794121289684255],"hpluv":[307.715012949244738,151.961230908585406,55.7422560614222],"hsluv":[307.715012949244738,52.5739577191036176,55.7422560614222]},"#bb66cc":{"lch":[56.5140206008290704,76.3075420390205466,299.031845144425],"luv":[56.5140206008290704,37.0317190732607671,-66.7195080506142801],"rgb":[0.733333333333333282,0.4,0.8],"xyz":[0.361421460177830611,0.24428229370030477,0.599400631959954411],"hpluv":[299.031845144425,171.336773989457299,56.5140206008290704],"hsluv":[299.031845144425,57.7422914315118732,56.5140206008290704]},"#bb66dd":{"lch":[57.3558903641351208,87.0819801731049523,292.529347086481266],"luv":[57.3558903641351208,33.3660351201831276,-80.4361794917420809],"rgb":[0.733333333333333282,0.4,0.866666666666666696],"xyz":[0.38293978572846421,0.252889623920558304,0.712730479859960409],"hpluv":[292.529347086481266,192.659130793538424,57.3558903641351208],"hsluv":[292.529347086481266,71.4699790991907,57.3558903641351208]},"#bb66ee":{"lch":[58.2655263288606164,98.4965661150924916,287.652756970849339],"luv":[58.2655263288606164,29.8688319231142287,-93.8585447149780805],"rgb":[0.733333333333333282,0.4,0.933333333333333348],"xyz":[0.40675196599463892,0.262414496027028321,0.838141295928483632],"hpluv":[287.652756970849339,214.510592558062115,58.2655263288606164],"hsluv":[287.652756970849339,85.5420625539119186,58.2655263288606164]},"#bb66ff":{"lch":[59.2402283004695533,110.175409569553764,283.948158265715847],"luv":[59.2402283004695533,26.5571064878979755,-106.926801919861816],"rgb":[0.733333333333333282,0.4,1],"xyz":[0.432923014404470341,0.272882915390961045,0.975975484220265477],"hpluv":[283.948158265715847,235.997431668916079,59.2402283004695533],"hsluv":[283.948158265715847,99.9999999999988205,59.2402283004695533]},"#997700":{"lch":[51.799451349173637,61.2288227532233265,61.7368019650066202],"luv":[51.799451349173637,28.9932293289078338,53.9292257391759406],"rgb":[0.6,0.466666666666666674,0],"xyz":[0.197331129475883132,0.19966620830666032,0.028146226367465537],"hpluv":[61.7368019650066202,149.992683828924328,51.799451349173637],"hsluv":[61.7368019650066202,100.000000000002373,51.799451349173637]},"#997711":{"lch":[51.8452237949875752,59.5195003520895298,61.1595916745536812],"luv":[51.8452237949875752,28.7105152364728049,52.1371003894409952],"rgb":[0.6,0.466666666666666674,0.0666666666666666657],"xyz":[0.198342794975520265,0.200070874506515173,0.0334743313322211702],"hpluv":[61.1595916745536812,145.676617799321178,51.8452237949875752],"hsluv":[61.1595916745536812,96.7355174862457687,51.8452237949875752]},"#997722":{"lch":[51.9299107218419778,56.4237897442973448,60.0184197539949],"luv":[51.9299107218419778,28.1961842142201746,48.8735024820856836],"rgb":[0.6,0.466666666666666674,0.133333333333333331],"xyz":[0.200218153113997266,0.200821017761906,0.0433512175282003628],"hpluv":[60.0184197539949,137.874516690543771,51.9299107218419778],"hsluv":[60.0184197539949,90.8032063934702762,51.9299107218419778]},"#997733":{"lch":[52.0688882655341843,51.532107019520943,57.9108306747127841],"luv":[52.0688882655341843,27.375836028403171,43.6591531710973797],"rgb":[0.6,0.466666666666666674,0.2],"xyz":[0.203305903846455027,0.2020561180548891,0.0596133713858115061],"hpluv":[57.9108306747127841,125.585333003110208,52.0688882655341843],"hsluv":[57.9108306747127841,81.359583819486275,52.0688882655341843]},"#997744":{"lch":[52.2685439893789265,44.9234500117750244,54.2507061045172563],"luv":[52.2685439893789265,26.2460613351246792,36.4590266649196622],"rgb":[0.6,0.466666666666666674,0.266666666666666663],"xyz":[0.207763899090673887,0.203839316152576694,0.0830921463386981446],"hpluv":[54.2507061045172563,109.061640425204757,52.2685439893789265],"hsluv":[54.2507061045172563,68.3925961892813632,52.2685439893789265]},"#997755":{"lch":[52.5337646967731615,36.9638675487782962,47.8040559904272229],"luv":[52.5337646967731615,24.8274523779219614,27.3847605902560787],"rgb":[0.6,0.466666666666666674,0.333333333333333315],"xyz":[0.213726313130035872,0.206224281768321527,0.11449419361267206],"hpluv":[47.8040559904272229,89.2849392346346,52.5337646967731615],"hsluv":[47.8040559904272229,52.1784042692219217,52.5337646967731615]},"#997766":{"lch":[52.8682223623880958,28.5307109293219519,35.7342712802299047],"luv":[52.8682223623880958,23.1593577603421643,16.6627012894371447],"rgb":[0.6,0.466666666666666674,0.4],"xyz":[0.221311308903544057,0.209258280077724818,0.154441838019816],"hpluv":[35.7342712802299047,68.4789688439394695,52.8682223623880958],"hsluv":[35.7342712802299047,33.2180784313787072,52.8682223623880958]},"#997777":{"lch":[53.2745272921510349,21.7835186536615062,12.1770506300626185],"luv":[53.2745272921510349,21.2933995119794766,4.59486911213486],"rgb":[0.6,0.466666666666666674,0.466666666666666674],"xyz":[0.230625321923745963,0.212983885285805641,0.203495639926213917],"hpluv":[12.1770506300626185,51.8857087556556777,53.2745272921510349],"hsluv":[12.1770506300626185,12.1864056638809046,53.2745272921510349]},"#997788":{"lch":[53.7543298043441524,21.0694932264164443,336.259644884191403],"luv":[53.7543298043441524,19.28657717102978,-8.48242216845644492],"rgb":[0.6,0.466666666666666674,0.533333333333333326],"xyz":[0.241765739025689819,0.217440052126583239,0.262168503329786085],"hpluv":[336.259644884191403,49.7370433553737143,53.7543298043441524],"hsluv":[336.259644884191403,17.3594920402921318,53.7543298043441524]},"#997799":{"lch":[54.308403390094881,28.1087123643927,307.715012949247921],"luv":[54.308403390094881,17.1950646022419384,-22.235769923906151],"rgb":[0.6,0.466666666666666674,0.6],"xyz":[0.254822703134762518,0.222662837770212396,0.330935180970904],"hpluv":[307.715012949247921,65.67699031054849,54.308403390094881],"hsluv":[307.715012949247921,22.7222383700086681,54.308403390094881]},"#9977aa":{"lch":[54.9367240193748785,39.361724048309469,292.510155009375],"luv":[54.9367240193748785,15.0695247856183894,-36.3628208860492137],"rgb":[0.6,0.466666666666666674,0.66666666666666663],"xyz":[0.269880396100015074,0.228685914956313491,0.41023903058790262],"hpluv":[292.510155009375,90.9181689788077847,54.9367240193748785],"hsluv":[292.510155009375,30.8964586946041671,54.9367240193748785]},"#9977bb":{"lch":[55.6385517902762388,52.2405182414828104,284.355371582691191],"luv":[55.6385517902762388,12.9522722169503091,-50.6093903397058824],"rgb":[0.6,0.466666666666666674,0.733333333333333282],"xyz":[0.287017988207351693,0.235540951799248249,0.500497015686544366],"hpluv":[284.355371582691191,119.143673365147691,55.6385517902762388],"hsluv":[284.355371582691191,44.025050152294007,55.6385517902762388]},"#9977cc":{"lch":[56.4125166695819615,65.6830300518217172,279.531250686135081],"luv":[56.4125166695819615,10.8761592408186605,-64.7763042860340192],"rgb":[0.6,0.466666666666666674,0.8],"xyz":[0.306310363651073447,0.243257901976737051,0.602103526356814522],"hpluv":[279.531250686135081,147.746441920881637,56.4125166695819615],"hsluv":[279.531250686135081,57.5215558896316352,56.4125166695819615]},"#9977dd":{"lch":[57.256707620000924,79.2159287347205,276.425234899334782],"luv":[57.256707620000924,8.86478593594131858,-78.718351962006011],"rgb":[0.6,0.466666666666666674,0.866666666666666696],"xyz":[0.327828689201707,0.251865232196990585,0.71543337425682052],"hpluv":[276.425234899334782,175.559960004438778,57.256707620000924],"hsluv":[276.425234899334782,71.3413917340773764,57.256707620000924]},"#9977ee":{"lch":[58.1687631275758434,92.5981917117116211,274.294200356840065],"luv":[58.1687631275758434,6.93354781471817905,-92.3382424728774822],"rgb":[0.6,0.466666666666666674,0.933333333333333348],"xyz":[0.351640869467881756,0.261390104303460602,0.840844190325343743],"hpluv":[274.294200356840065,202.000294664132923,58.1687631275758434],"hsluv":[274.294200356840065,85.4864748016987903,58.1687631275758434]},"#9977ff":{"lch":[59.1459606243173,105.700835267318482,272.760722153075335],"luv":[59.1459606243173,5.0910859147335179,-105.578157875659116],"rgb":[0.6,0.466666666666666674,1],"xyz":[0.377811917877713122,0.271858523667393326,0.978678378617125588],"hpluv":[272.760722153075335,226.773684284234889,59.1459606243173],"hsluv":[272.760722153075335,99.9999999999988,59.1459606243173]},"#bb7700":{"lch":[55.8465021194210323,78.9426527823167703,44.2288975260652037],"luv":[55.8465021194210323,56.5670601566064,55.0645996403160751],"rgb":[0.733333333333333282,0.466666666666666674,0],"xyz":[0.270895964056058,0.237598076137063796,0.0315945779884111572],"hpluv":[44.2288975260652037,179.372171604304526,55.8465021194210323],"hsluv":[44.2288975260652037,100.000000000002402,55.8465021194210323]},"#bb7711":{"lch":[55.8872675460691113,77.5581898683241775,43.5811171927028127],"luv":[55.8872675460691113,56.1830827877517081,53.4671303149482782],"rgb":[0.733333333333333282,0.466666666666666674,0.0666666666666666657],"xyz":[0.271907629555695085,0.238002742336918649,0.0369226829531667869],"hpluv":[43.5811171927028127,176.097874689063588,55.8872675460691113],"hsluv":[43.5811171927028127,97.2747266570755613,55.8872675460691113]},"#bb7722":{"lch":[55.9627137258116534,75.0570685818031365,42.3362918908129799],"luv":[55.9627137258116534,55.4825342436315907,50.549499878809371],"rgb":[0.733333333333333282,0.466666666666666674,0.133333333333333331],"xyz":[0.273782987694172142,0.238752885592309477,0.0467995691491459864],"hpluv":[42.3362918908129799,170.189263625481374,55.9627137258116534],"hsluv":[42.3362918908129799,92.3060252972229875,55.9627137258116534]},"#bb7733":{"lch":[56.086591241629975,71.12386069085467,40.1553843778465094],"luv":[56.086591241629975,54.3598535070873652,45.8651271257379562],"rgb":[0.733333333333333282,0.466666666666666674,0.2],"xyz":[0.276870738426629848,0.239987985885292576,0.0630617230067571366],"hpluv":[40.1553843778465094,160.914656808849855,56.086591241629975],"hsluv":[40.1553843778465094,84.3528141134219425,56.086591241629975]},"#bb7744":{"lch":[56.2646940492590346,65.8532423012147632,36.6949041745596887],"luv":[56.2646940492590346,52.8030258036740747,39.3508575199960617],"rgb":[0.733333333333333282,0.466666666666666674,0.266666666666666663],"xyz":[0.281328733670848763,0.24177118398298017,0.0865404979596437751],"hpluv":[36.6949041745596887,148.518490760970963,56.2646940492590346],"hsluv":[36.6949041745596887,73.3442464951488517,56.2646940492590346]},"#bb7755":{"lch":[56.5015366957073866,59.5720019456390375,31.4313823601585],"luv":[56.5015366957073866,50.8307220514796256,31.0654327434279267],"rgb":[0.733333333333333282,0.466666666666666674,0.333333333333333315],"xyz":[0.287291147710210748,0.244156149598725,0.117942545233617677],"hpluv":[31.4313823601585,133.789263155984059,56.5015366957073866],"hsluv":[31.4313823601585,59.433527841274838,56.5015366957073866]},"#bb7766":{"lch":[56.8006139195957758,52.9060784141758376,23.584548946691168],"luv":[56.8006139195957758,48.4868685528452588,21.1678225404983067],"rgb":[0.733333333333333282,0.466666666666666674,0.4],"xyz":[0.294876143483718933,0.247190147908128294,0.157890189640761625],"hpluv":[23.584548946691168,118.193030459121616,56.8006139195957758],"hsluv":[23.584548946691168,42.9582981176577476,56.8006139195957758]},"#bb7777":{"lch":[57.1645375630264851,46.8887603377642677,12.1770506300621175],"luv":[57.1645375630264851,45.8337848153679062,9.89040016939892652],"rgb":[0.733333333333333282,0.466666666666666674,0.466666666666666674],"xyz":[0.304190156503920839,0.250915753116209117,0.206943991547159534],"hpluv":[12.1770506300621175,104.083378979503351,57.1645375630264851],"hsluv":[12.1770506300621175,30.9338815185941769,57.1645375630264851]},"#bb7788":{"lch":[57.5951231639082408,43.0166042307866761,356.679907444569722],"luv":[57.5951231639082408,42.9444038116514264,-2.49126891562360298],"rgb":[0.733333333333333282,0.466666666666666674,0.533333333333333326],"xyz":[0.315330573605864639,0.255371919956986715,0.265616854950731729],"hpluv":[356.679907444569722,94.7741152880685149,57.5951231639082408],"hsluv":[356.679907444569722,32.9204937798227419,57.5951231639082408]},"#bb7799":{"lch":[58.0934559183715322,42.8683503206465062,338.533521874652],"luv":[58.0934559183715322,39.8946515879682408,-15.6879646190414519],"rgb":[0.733333333333333282,0.466666666666666674,0.6],"xyz":[0.328387537714937339,0.260594705600615872,0.334383532591849608],"hpluv":[338.533521874652,93.6373004736019823,58.0934559183715322],"hsluv":[338.533521874652,34.9811369830312131,58.0934559183715322]},"#bb77aa":{"lch":[58.6599497668646706,47.0820583870944276,321.324781752589786],"luv":[58.6599497668646706,36.7569990603765,-29.4218157502430451],"rgb":[0.733333333333333282,0.466666666666666674,0.66666666666666663],"xyz":[0.343445230680189895,0.266617782786717,0.413687382208848209],"hpluv":[321.324781752589786,101.848135129910219,58.6599497668646706],"hsluv":[321.324781752589786,37.0556810629478051,58.6599497668646706]},"#bb77bb":{"lch":[59.2944060970233693,54.9189596898792303,307.71501294924542],"luv":[59.2944060970233693,33.5958135510894706,-43.4443718479046765],"rgb":[0.733333333333333282,0.466666666666666674,0.733333333333333282],"xyz":[0.360582822787526569,0.273472819629651753,0.50394536730749],"hpluv":[307.71501294924542,117.529775077760561,59.2944060970233693],"hsluv":[307.71501294924542,40.6617226560308467,59.2944060970233693]},"#bb77cc":{"lch":[59.9960747587738155,65.1135012197087519,297.896140559284788],"luv":[59.9960747587738155,30.4646722292654815,-57.5471266620014177],"rgb":[0.733333333333333282,0.466666666666666674,0.8],"xyz":[0.379875198231248268,0.281189769807140555,0.605551877977760111],"hpluv":[297.896140559284788,137.716994859863917,59.9960747587738155],"hsluv":[297.896140559284788,53.5682479917909,59.9960747587738155]},"#bb77dd":{"lch":[60.7637179337253599,76.6332290650186394,290.953982706702106],"luv":[60.7637179337253599,27.4054240934965065,-71.5653165100750357],"rgb":[0.733333333333333282,0.466666666666666674,0.866666666666666696],"xyz":[0.401393523781881867,0.289797100027394061,0.718881725877766109],"hpluv":[290.953982706702106,160.033945707839,60.7637179337253599],"hsluv":[290.953982706702106,68.5485010485900119,60.7637179337253599]},"#bb77ee":{"lch":[61.5956761624293563,88.8082274030350902,285.979672103614405],"luv":[61.5956761624293563,24.4485758512518743,-85.3766267389077456],"rgb":[0.733333333333333282,0.466666666666666674,0.933333333333333348],"xyz":[0.425205704048056576,0.299321972133864078,0.844292541946289332],"hpluv":[285.979672103614405,182.954165183101395,61.5956761624293563],"hsluv":[285.979672103614405,84.0163684558434909,61.5956761624293563]},"#bb77ff":{"lch":[62.4899351736807773,101.23109143545085,282.328516880108566],"luv":[62.4899351736807773,21.6145233767131266,-98.8966442929694693],"rgb":[0.733333333333333282,0.466666666666666674,1],"xyz":[0.451376752457888,0.309790391497796802,0.982126730238071177],"hpluv":[282.328516880108566,205.562159598045383,62.4899351736807773],"hsluv":[282.328516880108566,99.9999999999986784,62.4899351736807773]},"#998800":{"lch":[56.4673516485332527,62.834492950420568,74.7562721675545561],"luv":[56.4673516485332527,16.5207966112614884,60.6237311922136897],"rgb":[0.6,0.533333333333333326,0],"xyz":[0.219403499200853586,0.243810947756601892,0.0355036829424554834],"hpluv":[74.7562721675545561,141.201731332299261,56.4673516485332527],"hsluv":[74.7562721675545561,100.000000000002331,56.4673516485332527]},"#998811":{"lch":[56.5074221469723881,61.2259080808398366,74.51872844438833],"luv":[56.5074221469723881,16.3426261455871646,59.0044946676862878],"rgb":[0.6,0.533333333333333326,0.0666666666666666657],"xyz":[0.220415164700490718,0.244215613956456745,0.0408317879072111131],"hpluv":[74.51872844438833,137.489352382480689,56.5074221469723881],"hsluv":[74.51872844438833,97.3110722480099781,56.5074221469723881]},"#998822":{"lch":[56.5815852437789744,58.2905156727598666,74.0508275651119],"luv":[56.5815852437789744,16.0173304476746452,56.0466711119068961],"rgb":[0.6,0.533333333333333326,0.133333333333333331],"xyz":[0.222290522838967719,0.244965757211847573,0.0507086741031903127],"hpluv":[74.0508275651119,130.726042229432494,56.5815852437789744],"hsluv":[74.0508275651119,92.4075523300517574,56.5815852437789744]},"#998833":{"lch":[56.7033645714083,53.5858970619529273,73.1917859227149],"luv":[56.7033645714083,15.4953822971072128,51.2966031175623911],"rgb":[0.6,0.533333333333333326,0.2],"xyz":[0.22537827357142548,0.246200857504830672,0.066970827960801449],"hpluv":[73.1917859227149,119.917068416956084,56.7033645714083],"hsluv":[73.1917859227149,84.5557602276611533,56.7033645714083]},"#998844":{"lch":[56.8784692361674189,47.0662938677721456,71.7105236832421156],"luv":[56.8784692361674189,14.7702533586865563,44.6886521856241927],"rgb":[0.6,0.533333333333333326,0.266666666666666663],"xyz":[0.22983626881564434,0.247984055602518266,0.0904496029136880875],"hpluv":[71.7105236832421156,105.00293267331034,56.8784692361674189],"hsluv":[71.7105236832421156,73.6816499137771075,56.8784692361674189]},"#998855":{"lch":[57.1113583918905761,38.8337969655052433,69.1066660847648393],"luv":[57.1113583918905761,13.8492700909341142,36.2803184206870242],"rgb":[0.6,0.533333333333333326,0.333333333333333315],"xyz":[0.235798682855006325,0.250369021218263099,0.121851650187662],"hpluv":[69.1066660847648393,86.2832891510872599,57.1113583918905761],"hsluv":[69.1066660847648393,59.9309888570698774,57.1113583918905761]},"#998866":{"lch":[57.4054971647218224,29.1657433305745144,64.0747883902216],"luv":[57.4054971647218224,12.7511922431808031,26.2306629806110223],"rgb":[0.6,0.533333333333333326,0.4],"xyz":[0.24338367862851451,0.253403019527666418,0.161799294594805965],"hpluv":[64.0747883902216,64.4701815948561574,57.4054971647218224],"hsluv":[64.0747883902216,43.6310875702010321,57.4054971647218224]},"#998877":{"lch":[57.7634914296009612,18.7238256654584347,52.0945218145914097],"luv":[57.7634914296009612,11.5031815844705712,14.773573060880608],"rgb":[0.6,0.533333333333333326,0.466666666666666674],"xyz":[0.252697691648716416,0.257128624735747213,0.210853096501203874],"hpluv":[52.0945218145914097,41.1320618043462858,57.7634914296009612],"hsluv":[52.0945218145914097,25.2418236256697028,57.7634914296009612]},"#998888":{"lch":[58.1871725604667489,10.3706980586515272,12.1770506300640946],"luv":[58.1871725604667489,10.1373621264743505,2.18752539195365081],"rgb":[0.6,0.533333333333333326,0.533333333333333326],"xyz":[0.263838108750660272,0.261584791576524811,0.269525959904776],"hpluv":[12.1770506300640946,22.6162221883482317,58.1871725604667489],"hsluv":[12.1770506300640946,7.14421708061451799,58.1871725604667489]},"#998899":{"lch":[58.6776613659523605,14.2013195506443459,307.715012949254117],"luv":[58.6776613659523605,8.6874348403017283,-11.2341422847952668],"rgb":[0.6,0.533333333333333326,0.6],"xyz":[0.276895072859732971,0.266807577220153969,0.338292637545893948],"hpluv":[307.715012949254117,30.7110899398720818,58.6776613659523605],"hsluv":[307.715012949254117,10.6251017733449729,58.6776613659523605]},"#9988aa":{"lch":[59.2354248002074399,26.2127450059066938,285.910383521223935],"luv":[59.2354248002074399,7.18579172527609789,-25.2085778659891844],"rgb":[0.6,0.533333333333333326,0.66666666666666663],"xyz":[0.291952765824985527,0.272830654406255091,0.417596487162892549],"hpluv":[285.910383521223935,56.1526584479988173,59.2354248002074399],"hsluv":[285.910383521223935,23.5088603674401817,59.2354248002074399]},"#9988bb":{"lch":[59.8603319378123189,39.8857557696632696,278.160160819701673],"luv":[59.8603319378123189,5.66141142610705117,-39.4819190767314581],"rgb":[0.6,0.533333333333333326,0.733333333333333282],"xyz":[0.309090357932322146,0.279685691249189849,0.507854472261534351],"hpluv":[278.160160819701673,84.5508603994872,59.8603319378123189],"hsluv":[278.160160819701673,37.7262541103550291,59.8603319378123189]},"#9988cc":{"lch":[60.55171199345871,53.9990869041691823,274.395593429514747],"luv":[60.55171199345871,4.13861667015410095,-53.8402566723222264],"rgb":[0.6,0.533333333333333326,0.8],"xyz":[0.3283827333760439,0.287402641426678651,0.609460982931804507],"hpluv":[274.395593429514747,113.161661700826286,60.55171199345871],"hsluv":[274.395593429514747,52.5240219153236723,60.55171199345871]},"#9988dd":{"lch":[61.3084150605589855,68.1648195931338563,272.216747448240312],"luv":[61.3084150605589855,2.63660773112319324,-68.1138086575451],"rgb":[0.6,0.533333333333333326,0.866666666666666696],"xyz":[0.349901058926677444,0.296009971646932157,0.722790830831810505],"hpluv":[272.216747448240312,141.084572716849891,61.3084150605589855],"hsluv":[272.216747448240312,67.8395486149695,61.3084150605589855]},"#9988ee":{"lch":[62.128875020953032,82.18421866163294,270.815422264053723],"luv":[62.128875020953032,1.1695901512833331,-82.1758958326656597],"rgb":[0.6,0.533333333333333326,0.933333333333333348],"xyz":[0.373713239192852154,0.305534843753402174,0.848201646900333728],"hpluv":[270.815422264053723,167.854994169255662,62.128875020953032],"hsluv":[270.815422264053723,83.6558877567472905,62.128875020953032]},"#9988ff":{"lch":[63.0111734122257303,95.9388777898474387,269.8490772999765],"luv":[63.0111734122257303,-0.252712116882344406,-95.9385449554102],"rgb":[0.6,0.533333333333333326,1],"xyz":[0.399884287602683575,0.316003263117334898,0.986035835192115462],"hpluv":[269.8490772999765,193.204124490752207,63.0111734122257303],"hsluv":[269.8490772999765,99.9999999999985363,63.0111734122257303]},"#bb8800":{"lch":[60.0458653136574,74.8864062555341832,55.056379834278971],"luv":[60.0458653136574,42.8926945435799,61.3855894869476728],"rgb":[0.733333333333333282,0.533333333333333326,0],"xyz":[0.292968333781028434,0.281742815587005313,0.038952034563401107],"hpluv":[55.056379834278971,158.255644288368103,60.0458653136574],"hsluv":[55.056379834278971,100.000000000002288,60.0458653136574]},"#bb8811":{"lch":[60.0822560315187957,73.5298298886522161,54.5759299869630823],"luv":[60.0822560315187957,42.619621560372849,59.9183089005750773],"rgb":[0.733333333333333282,0.533333333333333326,0.0666666666666666657],"xyz":[0.293979999280665538,0.282147481786860166,0.0442801395281567367],"hpluv":[54.5759299869630823,155.294707870281485,60.0822560315187957],"hsluv":[54.5759299869630823,97.6878818876268866,60.0822560315187957]},"#bb8822":{"lch":[60.1496227929862499,71.0610449842002367,53.6488709316330343],"luv":[60.1496227929862499,42.1201645307819774,57.2325419158225586],"rgb":[0.733333333333333282,0.533333333333333326,0.133333333333333331],"xyz":[0.295855357419142595,0.282897625042250966,0.0541570257241359362],"hpluv":[53.6488709316330343,149.912555699661567,60.1496227929862499],"hsluv":[53.6488709316330343,93.46183514856709,60.1496227929862499]},"#bb8833":{"lch":[60.2602822329103844,67.1261991777524,52.0115270519145412],"luv":[60.2602822329103844,41.3163720666953154,52.9044801061090197],"rgb":[0.733333333333333282,0.533333333333333326,0.2],"xyz":[0.298943108151600301,0.284132725335234093,0.0704191795817470795],"hpluv":[52.0115270519145412,141.351435183858257,60.2602822329103844],"hsluv":[52.0115270519145412,86.668700859176,60.2602822329103844]},"#bb8844":{"lch":[60.4194844691316746,61.7320119628667285,49.374045706205429],"luv":[60.4194844691316746,40.1948297943626258,46.8531424643613406],"rgb":[0.733333333333333282,0.533333333333333326,0.266666666666666663],"xyz":[0.303401103395819216,0.285915923432921659,0.093897954534633718],"hpluv":[49.374045706205429,129.650066203053939,60.4194844691316746],"hsluv":[49.374045706205429,77.207197386412,60.4194844691316746]},"#bb8855":{"lch":[60.6313805732006585,55.0590005000961682,45.2500033552910708],"luv":[60.6313805732006585,38.7623447760430935,39.1020992215604082],"rgb":[0.733333333333333282,0.533333333333333326,0.333333333333333315],"xyz":[0.309363517435181201,0.28830088904866652,0.125300001808607619],"hpluv":[45.2500033552910708,115.231228654446355,60.6313805732006585],"hsluv":[45.2500033552910708,65.1528926573884775,60.6313805732006585]},"#bb8866":{"lch":[60.8992588402534949,47.519038379270981,38.7816256818529581],"luv":[60.8992588402534949,37.0429375720225096,29.7637327048519147],"rgb":[0.733333333333333282,0.533333333333333326,0.4],"xyz":[0.316948513208689386,0.291334887358069838,0.165247646215751581],"hpluv":[38.7816256818529581,99.0136254476035305,60.8992588402534949],"hsluv":[38.7816256818529581,50.7321114426118,60.8992588402534949]},"#bb8877":{"lch":[61.2256685857267087,39.8992767652027354,28.4701407483744688],"luv":[61.2256685857267087,35.0740840991728362,19.0200134329710231],"rgb":[0.733333333333333282,0.533333333333333326,0.466666666666666674],"xyz":[0.326262526228891292,0.295060492566150634,0.21430144812214949],"hpluv":[28.4701407483744688,82.6933933486175761,61.2256685857267087],"hsluv":[28.4701407483744688,34.2887258466009897,61.2256685857267087]},"#bb8888":{"lch":[61.6124959728340684,33.6595928281588499,12.1770506300623627],"luv":[61.6124959728340684,32.9022674846918903,7.09992843085263114],"rgb":[0.733333333333333282,0.533333333333333326,0.533333333333333326],"xyz":[0.337402943330835092,0.299516659406928232,0.272974311525721658],"hpluv":[12.1770506300623627,69.3233245158679,61.6124959728340684],"hsluv":[12.1770506300623627,26.8235367690150284,61.6124959728340684]},"#bb8899":{"lch":[62.0610184830546388,31.1131530731089718,349.361203223606594],"luv":[62.0610184830546388,30.5783355372127765,-5.74401339869088723],"rgb":[0.733333333333333282,0.533333333333333326,0.6],"xyz":[0.350459907439907847,0.304739445050557389,0.341740989166839593],"hpluv":[349.361203223606594,63.6157209963685091,62.0610184830546388],"hsluv":[349.361203223606594,28.7433747177793393,62.0610184830546388]},"#bb88aa":{"lch":[62.5719506337331097,34.1093853871598185,325.627133749050586],"luv":[62.5719506337331097,28.1532372220531357,-19.2573467904743723],"rgb":[0.733333333333333282,0.533333333333333326,0.66666666666666663],"xyz":[0.365517600405160348,0.310762522236658512,0.421044838783838193],"hpluv":[325.627133749050586,69.1725086761469328,62.5719506337331097],"hsluv":[325.627133749050586,30.7007491098828176,62.5719506337331097]},"#bb88bb":{"lch":[63.1454872588298,41.9701566603395477,307.715012949246614],"luv":[63.1454872588298,25.674586077978244,-33.2010493782640808],"rgb":[0.733333333333333282,0.533333333333333326,0.733333333333333282],"xyz":[0.382655192512497,0.31761755907959327,0.51130282388247994],"hpluv":[307.715012949246614,84.3407770596407,63.1454872588298],"hsluv":[307.715012949246614,32.6446535119142354,63.1454872588298]},"#bb88cc":{"lch":[63.7813474201422,52.7335158558763055,296.081540752202443],"luv":[63.7813474201422,23.1842810338905281,-47.3636232510092228],"rgb":[0.733333333333333282,0.533333333333333326,0.8],"xyz":[0.401947567956218776,0.325334509257082072,0.612909334552750096],"hpluv":[296.081540752202443,104.913738848088499,63.7813474201422],"hsluv":[296.081540752202443,48.441096457031712,63.7813474201422]},"#bb88dd":{"lch":[64.4788201663492089,64.9599578897110916,288.597779393076337],"luv":[64.4788201663492089,20.7171971389296665,-61.56779898404492],"rgb":[0.733333333333333282,0.533333333333333326,0.866666666666666696],"xyz":[0.423465893506852264,0.333941839477335578,0.726239182452756094],"hpluv":[288.597779393076337,127.840358269428478,64.4788201663492089],"hsluv":[288.597779393076337,64.9415793589177,64.4788201663492089]},"#bb88ee":{"lch":[65.2368122498474463,77.8541115668441392,283.595470556329246],"luv":[65.2368122498474463,18.300798164755431,-75.6726071600252084],"rgb":[0.733333333333333282,0.533333333333333326,0.933333333333333348],"xyz":[0.44727807377302703,0.343466711583805595,0.851649998521279317],"hpluv":[283.595470556329246,151.435657753316406,65.2368122498474463],"hsluv":[283.595470556329246,82.1213401763518789,65.2368122498474463]},"#bb88ff":{"lch":[66.0538972531437452,90.9819525935223652,280.100148709787334],"luv":[66.0538972531437452,15.9554396417090967,-89.5719802369565201],"rgb":[0.733333333333333282,0.533333333333333326,1],"xyz":[0.473449122182858395,0.353935130947738319,0.989484186813061162],"hpluv":[280.100148709787334,174.781769995450787,66.0538972531437452],"hsluv":[280.100148709787334,99.99999999999838,66.0538972531437452]},"#999900":{"lch":[61.2683639221826866,67.5422828804358772,85.8743202181747449],"luv":[61.2683639221826866,4.85929488236129092,67.3672563635114869],"rgb":[0.6,0.6,0],"xyz":[0.245273099653321058,0.295550148661537559,0.0441268830932777384],"hpluv":[85.8743202181747449,139.887458074797593,61.2683639221826866],"hsluv":[85.8743202181747449,100.000000000002359,61.2683639221826866]},"#999911":{"lch":[61.3036130280217861,66.0751339072958785,85.8743202181746881],"luv":[61.3036130280217861,4.75374160235953358,65.9039093047224185],"rgb":[0.6,0.6,0.0666666666666666657],"xyz":[0.24628476515295819,0.295954814861392412,0.0494549880580333681],"hpluv":[85.8743202181746881,136.770144995815713,61.3036130280217861],"hsluv":[85.8743202181746881,97.7715564197957718,61.3036130280217861]},"#999922":{"lch":[61.3688705786650104,63.38848415762304,85.8743202181745744],"luv":[61.3688705786650104,4.56045196477970372,63.2242216375825663],"rgb":[0.6,0.6,0.133333333333333331],"xyz":[0.248160123291435192,0.296704958116783213,0.0593318742540125676],"hpluv":[85.8743202181745744,131.069475710796667,61.3688705786650104],"hsluv":[85.8743202181745744,93.6963738669960691,61.3688705786650104]},"#999933":{"lch":[61.4760769955270945,59.0559618954583243,85.8743202181743754],"luv":[61.4760769955270945,4.24875087387181871,58.9029265097210484],"rgb":[0.6,0.6,0.2],"xyz":[0.251247874023892925,0.29794005840976634,0.0755940281116237178],"hpluv":[85.8743202181743754,121.898097720990123,61.4760769955270945],"hsluv":[85.8743202181743754,87.1401192062652683,61.4760769955270945]},"#999944":{"lch":[61.6303367515695,52.9921690524208,85.8743202181739775],"luv":[61.6303367515695,3.81249440942850049,52.8548471500809569],"rgb":[0.6,0.6,0.266666666666666663],"xyz":[0.255705869268111841,0.299723256507453906,0.0990728030645103563],"hpluv":[85.8743202181739775,109.10797160418339,61.6303367515695],"hsluv":[85.8743202181739775,77.9969649215058,61.6303367515695]},"#999955":{"lch":[61.8357003743425935,45.2147461889200173,85.8743202181734517],"luv":[61.8357003743425935,3.25295171251598125,45.0975784059909],"rgb":[0.6,0.6,0.333333333333333315],"xyz":[0.261668283307473826,0.302108222123198766,0.130474850338484272],"hpluv":[85.8743202181734517,92.7855058259100218,61.8357003743425935],"hsluv":[85.8743202181734517,66.3286810003367577,61.8357003743425935]},"#999966":{"lch":[62.0953945325949377,35.8293841981041083,85.874320218172457],"luv":[62.0953945325949377,2.57772666020637553,35.7365372872164784],"rgb":[0.6,0.6,0.4],"xyz":[0.269253279080982,0.305142220432602085,0.170422494745628206],"hpluv":[85.874320218172457,73.2182390722606,62.0953945325949377],"hsluv":[85.874320218172457,52.3408174542086542,62.0953945325949377]},"#999977":{"lch":[62.4119425079225749,25.0116267171883422,85.8743202181703],"luv":[62.4119425079225749,1.79944864939855109,24.9468125338318],"rgb":[0.6,0.6,0.466666666666666674],"xyz":[0.278567292101183916,0.30886782564068288,0.219476296652026115],"hpluv":[85.8743202181703,50.8526471570801775,62.4119425079225749],"hsluv":[85.8743202181703,36.3525421484824918,62.4119425079225749]},"#999988":{"lch":[62.7872374999600567,12.9853368609797517,85.8743202181639589],"luv":[62.7872374999600567,0.934223397011331502,12.9516871502363],"rgb":[0.6,0.6,0.533333333333333326],"xyz":[0.289707709203127717,0.313323992481460478,0.27814916005559831],"hpluv":[85.8743202181639589,26.2434647477884546,62.7872374999600567],"hsluv":[85.8743202181639589,18.7604129126121961,62.7872374999600567]},"#999999":{"lch":[63.2225945523589843,3.33307052034688283e-12,0],"luv":[63.2225945523589843,3.14807442966336163e-12,1.09498241031769098e-12],"rgb":[0.6,0.6,0.6],"xyz":[0.302764673312200472,0.318546778125089636,0.346915837696716189],"hpluv":[0,6.68977504875838914e-12,63.2225945523589843],"hsluv":[0,3.10313074237261963e-12,63.2225945523589843]},"#9999aa":{"lch":[63.7187933641432238,13.6904464527836414,265.874320218190064],"luv":[63.7187933641432238,-0.984952144759020598,-13.6549695477167123],"rgb":[0.6,0.6,0.66666666666666663],"xyz":[0.317822366277453,0.324569855311190758,0.42621968731371479],"hpluv":[265.874320218190064,27.2639887848552753,63.7187933641432238],"hsluv":[265.874320218190064,14.5770868731616492,63.7187933641432238]},"#9999bb":{"lch":[64.276118203606174,27.8450519356751158,265.874320218183641],"luv":[64.276118203606174,-2.00329797275791854,-27.7728953213882335],"rgb":[0.6,0.6,0.733333333333333282],"xyz":[0.334959958384789647,0.331424892154125517,0.516477672412356537],"hpluv":[265.874320218183641,54.9715165011475904,64.276118203606174],"hsluv":[265.874320218183641,30.0955931685464577,64.276118203606174]},"#9999cc":{"lch":[64.8943980299807635,42.2483295275786332,265.874320218181538],"luv":[64.8943980299807635,-3.03953438803302189,-42.138848804575062],"rgb":[0.6,0.6,0.8],"xyz":[0.354252333828511401,0.339141842331614318,0.618084183082626692],"hpluv":[265.874320218181538,82.6117192029769,64.8943980299807635],"hsluv":[265.874320218181538,46.4456834766813316,64.8943980299807635]},"#9999dd":{"lch":[65.5730481583578353,56.7175687031348,265.874320218180458],"luv":[65.5730481583578353,-4.08051637559571567,-56.570592941061804],"rgb":[0.6,0.6,0.866666666666666696],"xyz":[0.375770659379144889,0.347749172551867824,0.73141403098263269],"hpluv":[265.874320218180458,109.756831209262941,65.5730481583578353],"hsluv":[265.874320218180458,63.5568222493012627,65.5730481583578353]},"#9999ee":{"lch":[66.311113738117,71.1055788100052695,265.874320218179832],"luv":[66.311113738117,-5.11565437949467672,-70.9213185027987691],"rgb":[0.6,0.6,0.933333333333333348],"xyz":[0.399582839645319654,0.357274044658337842,0.856824847051155913],"hpluv":[265.874320218179832,136.068212717368169,66.311113738117],"hsluv":[265.874320218179832,81.4020980414818922,66.311113738117]},"#9999ff":{"lch":[67.1073146704137145,85.2999068143523829,265.874320218179378],"luv":[67.1073146704137145,-6.13685802391602486,-85.0788638624864149],"rgb":[0.6,0.6,1],"xyz":[0.425753888055151,0.367742464022270565,0.994659035342937758],"hpluv":[265.874320218179378,161.293929533565688,67.1073146704137145],"hsluv":[265.874320218179378,99.9999999999983,67.1073146704137145]},"#bb9900":{"lch":[64.4418646198176219,74.1135014806344117,66.2793330800256228],"luv":[64.4418646198176219,29.8142337654579457,67.8522112145111],"rgb":[0.733333333333333282,0.6,0],"xyz":[0.318837934233495934,0.333482016491941036,0.047575234714223362],"hpluv":[66.2793330800256228,145.938057142603384,64.4418646198176219],"hsluv":[66.2793330800256228,100.000000000002416,64.4418646198176219]},"#bb9911":{"lch":[64.4743890579801331,72.806990252212529,65.9899074816349],"luv":[64.4743890579801331,29.6249863695688624,66.5072778888794147],"rgb":[0.733333333333333282,0.6,0.0666666666666666657],"xyz":[0.319849599733133039,0.333886682691795889,0.0529033396789789917],"hpluv":[65.9899074816349,143.29306400111571,64.4743890579801331],"hsluv":[65.9899074816349,98.0367215419372542,64.4743890579801331]},"#bb9922":{"lch":[64.5346112536789,70.4161712525116599,65.4311312102869636],"luv":[64.5346112536789,29.2781077929992222,64.0408430450799671],"rgb":[0.733333333333333282,0.6,0.133333333333333331],"xyz":[0.321724957871610096,0.334636825947186689,0.0627802258749581843],"hpluv":[65.4311312102869636,138.458312961065701,64.5346112536789],"hsluv":[65.4311312102869636,94.4406497380354892,64.5346112536789]},"#bb9933":{"lch":[64.6335704733000398,66.566957174521292,64.4427367566729146],"luv":[64.6335704733000398,28.7178476591491503,60.0536844273559396],"rgb":[0.733333333333333282,0.6,0.2],"xyz":[0.324812708604067801,0.335871926240169816,0.0790423797325693345],"hpluv":[64.4427367566729146,130.689255588928205,64.6335704733000398],"hsluv":[64.4427367566729146,88.6394107340449153,64.6335704733000398]},"#bb9944":{"lch":[64.7760175449466828,61.1991201001527685,62.8442649593615386],"luv":[64.7760175449466828,27.9319304868930693,54.4530950480162872],"rgb":[0.733333333333333282,0.6,0.266666666666666663],"xyz":[0.329270703848286717,0.337655124337857382,0.102521154685455973],"hpluv":[62.8442649593615386,119.886494259466,64.7760175449466828],"hsluv":[62.8442649593615386,80.5164965868838607,64.7760175449466828]},"#bb9955":{"lch":[64.965753761967747,54.3684881208399204,60.3198292286154],"luv":[64.965753761967747,26.9209928274273445,47.235501963369849],"rgb":[0.733333333333333282,0.6,0.333333333333333315],"xyz":[0.335233117887648702,0.340040089953602243,0.133923201959429888],"hpluv":[60.3198292286154,106.194518749025775,64.965753761967747],"hsluv":[60.3198292286154,70.0945405394646883,64.965753761967747]},"#bb9966":{"lch":[65.2058459998609,46.2670609228556557,56.2614414361724258],"luv":[65.2058459998609,25.6969192719684436,38.4747874116176689],"rgb":[0.733333333333333282,0.6,0.4],"xyz":[0.342818113661156887,0.343074088263005561,0.17387084636657385],"hpluv":[56.2614414361724258,90.0377647384168,65.2058459998609],"hsluv":[56.2614414361724258,57.5177389460533064,65.2058459998609]},"#bb9977":{"lch":[65.4987393303808147,37.2952826673053153,49.3796729345645886],"luv":[65.4987393303808147,24.280853083902965,28.3086255892461871],"rgb":[0.733333333333333282,0.6,0.466666666666666674],"xyz":[0.352132126681358792,0.346799693471086357,0.222924648272971759],"hpluv":[49.3796729345645886,72.2537327682772172,65.4987393303808147],"hsluv":[49.3796729345645886,43.0302399575574199,65.4987393303808147]},"#bb9988":{"lch":[65.8463246780106601,28.3139420599436384,36.7022131699001193],"luv":[65.8463246780106601,22.7007755052872291,16.9220006628175241],"rgb":[0.733333333333333282,0.6,0.533333333333333326],"xyz":[0.363272543783302593,0.351255860311863954,0.281597511676543899],"hpluv":[36.7022131699001193,54.564242001153282,65.8463246780106601],"hsluv":[36.7022131699001193,26.9495650592517677,65.8463246780106601]},"#bb9999":{"lch":[66.2499853133799377,21.4719543680734333,12.1770506300627517],"luv":[66.2499853133799377,20.9888452793887552,4.52914983440691099],"rgb":[0.733333333333333282,0.6,0.6],"xyz":[0.376329507892375292,0.356478645955493112,0.350364189317661834],"hpluv":[12.1770506300627517,41.1268186121042731,66.2499853133799377],"hsluv":[12.1770506300627517,20.948078856310218,66.2499853133799377]},"#bb99aa":{"lch":[66.7106335886793715,21.0368039825091344,335.738246937474969],"luv":[66.7106335886793715,19.1787866223333445,-8.64414631375011489],"rgb":[0.733333333333333282,0.6,0.66666666666666663],"xyz":[0.391387200857627848,0.362501723141594234,0.429668038934660435],"hpluv":[335.738246937474969,40.0151105801343192,66.7106335886793715],"hsluv":[335.738246937474969,22.766845509204984,66.7106335886793715]},"#bb99bb":{"lch":[67.2287438260669887,28.2861274819753,307.715012949249171],"luv":[67.2287438260669887,17.3035955220760833,-22.3761165070024362],"rgb":[0.733333333333333282,0.6,0.733333333333333282],"xyz":[0.408524792964964523,0.369356759984529,0.519926024033302125],"hpluv":[307.715012949249171,53.3897422679679323,67.2287438260669887],"hsluv":[307.715012949249171,24.5905380245485432,67.2287438260669887]},"#bb99cc":{"lch":[67.8043844715017343,39.5775547497090656,292.889275489017223],"luv":[67.8043844715017343,15.393749985076461,-36.4611478338680044],"rgb":[0.733333333333333282,0.6,0.8],"xyz":[0.427817168408686221,0.377073710162017794,0.621532534703572281],"hpluv":[292.889275489017223,74.0679810995506642,67.8043844715017343],"hsluv":[292.889275489017223,42.0187450252511,67.8043844715017343]},"#bb99dd":{"lch":[68.4372510447458353,52.4777928084534082,284.879936967142157],"luv":[68.4372510447458353,13.4760025497769718,-50.718005612655638],"rgb":[0.733333333333333282,0.6,0.866666666666666696],"xyz":[0.449335493959319821,0.385681040382271301,0.734862382603578279],"hpluv":[284.879936967142157,97.3021261982971737,68.4372510447458353],"hsluv":[284.879936967142157,60.4059975969609724,68.4372510447458353]},"#bb99ee":{"lch":[69.1267004581107898,66.0165196934359244,280.096152477623832],"luv":[69.1267004581107898,11.5727364631099334,-64.9942508472035456],"rgb":[0.733333333333333282,0.6,0.933333333333333348],"xyz":[0.47314767422549453,0.395205912488741318,0.860273198672101502],"hpluv":[280.096152477623832,121.184234531677617,69.1267004581107898],"hsluv":[280.096152477623832,79.7264365589122548,69.1267004581107898]},"#bb99ff":{"lch":[69.8717866786541,79.7596884688517207,276.986638727898821],"luv":[69.8717866786541,9.70179942494587877,-79.1674364405365765],"rgb":[0.733333333333333282,0.6,1],"xyz":[0.499318722635325951,0.405674331852674042,0.998107386963883347],"hpluv":[276.986638727898821,144.850809586534439,69.8717866786541],"hsluv":[276.986638727898821,99.9999999999980247,69.8717866786541]},"#880000":{"lch":[27.3946073685119416,92.1289276169810876,12.1770506300617765],"luv":[27.3946073685119416,90.0560691570773,19.4330571920800175],"rgb":[0.533333333333333326,0,0],"xyz":[0.101531161901381561,0.0523520053554009795,0.00475927321412716],"hpluv":[12.1770506300617765,426.746789183125316,27.3946073685119416],"hsluv":[12.1770506300617765,100.000000000002245,27.3946073685119416]},"#880011":{"lch":[27.5061298630582485,89.4551794237446529,10.4692299831444977],"luv":[27.5061298630582485,87.9659862388495242,16.254672889999533],"rgb":[0.533333333333333326,0,0.0666666666666666657],"xyz":[0.10254282740101868,0.0527566715552558324,0.0100873781788827915],"hpluv":[10.4692299831444977,412.68181181873,27.5061298630582485],"hsluv":[10.4692299831444977,99.9999999999965,27.5061298630582485]},"#880022":{"lch":[27.711363673312789,85.0234292319238421,7.23413932290422057],"luv":[27.711363673312789,84.3466296586470463,10.7065206104973338],"rgb":[0.533333333333333326,0,0.133333333333333331],"xyz":[0.104418185539495709,0.0535068148106466537,0.0199642643748619876],"hpluv":[7.23413932290422057,389.331950846774873,27.711363673312789],"hsluv":[7.23413932290422057,99.9999999999967,27.711363673312789]},"#880033":{"lch":[28.0451389930846,79.0521177396887396,1.75350406004841131],"luv":[28.0451389930846,79.0150993176991392,2.41896650323101259],"rgb":[0.533333333333333326,0,0.2],"xyz":[0.107505936271953442,0.0547419151036297666,0.0362264182324731343],"hpluv":[1.75350406004841131,357.680479105960103,28.0451389930846],"hsluv":[1.75350406004841131,99.9999999999969589,28.0451389930846]},"#880044":{"lch":[28.5182895144164306,72.8806899851902585,353.674121255230034],"luv":[28.5182895144164306,72.4369406321056459,-8.0302306678086488],"rgb":[0.533333333333333326,0,0.266666666666666663],"xyz":[0.111963931516172316,0.0565251132013173396,0.0597051931853597728],"hpluv":[353.674121255230034,324.286096087098713,28.5182895144164306],"hsluv":[353.674121255230034,99.9999999999972857,28.5182895144164306]},"#880055":{"lch":[29.1358047874334787,68.1690091719341922,343.056201782139055],"luv":[29.1358047874334787,65.2098664506571453,-19.866734230132252],"rgb":[0.533333333333333326,0,0.333333333333333315],"xyz":[0.117926345555534315,0.0589100788170621725,0.0911072404593336743],"hpluv":[343.056201782139055,296.892542908362316,29.1358047874334787],"hsluv":[343.056201782139055,99.9999999999977405,29.1358047874334787]},"#880066":{"lch":[29.8977347275108087,66.3157421691867768,330.790160549998632],"luv":[29.8977347275108087,57.8829185884671915,-32.3627161272186115],"rgb":[0.533333333333333326,0,0.4],"xyz":[0.125511341329042486,0.0619440771264654841,0.13105488486647765],"hpluv":[330.790160549998632,281.460643767249167,29.8977347275108087],"hsluv":[330.790160549998632,99.9999999999981384,29.8977347275108087]},"#880077":{"lch":[30.8000475559674527,67.8890879971799,318.512376228514142],"luv":[30.8000475559674527,50.8556366042998462,-44.9736866918894549],"rgb":[0.533333333333333326,0,0.466666666666666674],"xyz":[0.13482535434924442,0.0656696823345463,0.180108686772875559],"hpluv":[318.512376228514142,279.697068124812404,30.8000475559674527],"hsluv":[318.512376228514142,99.9999999999984652,30.8000475559674527]},"#880088":{"lch":[31.8355421357531156,72.5162027692933862,307.715012949243601],"luv":[31.8355421357531156,44.3606514294377803,-57.3649045046986288],"rgb":[0.533333333333333326,0,0.533333333333333326],"xyz":[0.14596577145118822,0.0701258491753239,0.238781550176447727],"hpluv":[307.715012949243601,289.042783730483279,31.8355421357531156],"hsluv":[307.715012949243601,99.9999999999987921,31.8355421357531156]},"#880099":{"lch":[32.9947769935272675,79.3376809512942,299.026215263792551],"luv":[32.9947769935272675,38.4954159686478121,-69.3726932454703444],"rgb":[0.533333333333333326,0,0.6],"xyz":[0.159022735560260947,0.0753486348189530558,0.307548227817565634],"hpluv":[299.026215263792551,305.122076286487129,32.9947769935272675],"hsluv":[299.026215263792551,99.9999999999991189,32.9947769935272675]},"#8800aa":{"lch":[34.2669429307518527,87.5167556566874651,292.341813883439613],"luv":[34.2669429307518527,33.2678552259606306,-80.9470958672197298],"rgb":[0.533333333333333326,0,0.66666666666666663],"xyz":[0.174080428525513475,0.0813717120050541642,0.386852077434564234],"hpluv":[292.341813883439613,324.082197305514,34.2669429307518527],"hsluv":[292.341813883439613,99.9999999999993605,34.2669429307518527]},"#8800bb":{"lch":[35.6406160405817047,96.4510237672048589,287.271351738157534],"luv":[35.6406160405817047,28.6360630376966157,-92.1019862947753296],"rgb":[0.533333333333333326,0,0.733333333333333282],"xyz":[0.19121802063285015,0.0882267488479889228,0.477110062533206],"hpluv":[287.271351738157534,343.400533998367337,35.6406160405817047],"hsluv":[287.271351738157534,99.999999999999531,35.6406160405817047]},"#8800cc":{"lch":[37.1043554501127346,105.765919518381835,283.413875530142832],"luv":[37.1043554501127346,24.5359458020369345,-102.880596300606314],"rgb":[0.533333333333333326,0,0.8],"xyz":[0.210510396076571876,0.0959436990254777244,0.578716573203476137],"hpluv":[283.413875530142832,361.709723992276565,37.1043554501127346],"hsluv":[283.413875530142832,99.9999999999998,37.1043554501127346]},"#8800dd":{"lch":[38.6471386159700145,115.245648848701009,280.44740978906907],"luv":[38.6471386159700145,20.8978330626497737,-113.335079087825761],"rgb":[0.533333333333333326,0,0.866666666666666696],"xyz":[0.23202872162720542,0.104551029245731258,0.692046421103482134],"hpluv":[280.44740978906907,378.39598449622531,38.6471386159700145],"hsluv":[280.44740978906907,99.9999999999998863,38.6471386159700145]},"#8800ee":{"lch":[40.258648150966188,124.7713904223,278.13468614008417],"luv":[40.258648150966188,17.6552208530237813,-123.515962711485074],"rgb":[0.533333333333333326,0,0.933333333333333348],"xyz":[0.255840901893380157,0.114075901352201275,0.817457237172005358],"hpluv":[278.13468614008417,393.273926011730225,40.258648150966188],"hsluv":[278.13468614008417,99.9999999999999858,40.258648150966188]},"#8800ff":{"lch":[41.9294357887748674,134.280036872974534,276.305800055850909],"luv":[41.9294357887748674,14.7486383519278057,-133.467621426964229],"rgb":[0.533333333333333326,0,1],"xyz":[0.282011950303211578,0.124544320716133985,0.955291425463787203],"hpluv":[276.305800055850909,406.37947026199555,41.9294357887748674],"hsluv":[276.305800055850909,100.000000000000171,41.9294357887748674]},"#aa0000":{"lch":[35.0982840320529732,118.036634932245676,12.1770506300617765],"luv":[35.0982840320529732,115.380864984340803,24.8978549596859438],"rgb":[0.66666666666666663,0,0],"xyz":[0.165771937912151307,0.08547615548595483,0.00777055958963192815],"hpluv":[12.1770506300617765,426.746789183125145,35.0982840320529732],"hsluv":[12.1770506300617765,100.000000000002217,35.0982840320529732]},"#aa0011":{"lch":[35.178794604810534,115.883637018633408,11.1343823918443601],"luv":[35.178794604810534,113.702354404428164,22.3783808966644813],"rgb":[0.66666666666666663,0,0.0666666666666666657],"xyz":[0.166783603411788439,0.0858808216858096829,0.0130986645543875596],"hpluv":[11.1343823918443601,418.004049663923468,35.178794604810534],"hsluv":[11.1343823918443601,99.9999999999964473,35.178794604810534]},"#aa0022":{"lch":[35.327373324777,112.154849255399441,9.17432067350408431],"luv":[35.327373324777,110.720144559212301,17.8818287736043224],"rgb":[0.66666666666666663,0,0.133333333333333331],"xyz":[0.16865896155026544,0.0866309649412005,0.0229755507503667557],"hpluv":[9.17432067350408431,402.852473647417696,35.327373324777],"hsluv":[9.17432067350408431,99.9999999999965752,35.327373324777]},"#aa0033":{"lch":[35.5701485089931921,106.706281850707128,5.8788523359554592],"luv":[35.5701485089931921,106.14508040487398,10.9294323844098908],"rgb":[0.66666666666666663,0,0.2],"xyz":[0.171746712282723202,0.0878660652341836101,0.0392377046079779],"hpluv":[5.8788523359554592,380.665602767339294,35.5701485089931921],"hsluv":[5.8788523359554592,99.9999999999967741,35.5701485089931921]},"#aa0044":{"lch":[35.9166782648329104,100.198740700315142,1.0062433800652546],"luv":[35.9166782648329104,100.183288799466339,1.75962588401964615],"rgb":[0.66666666666666663,0,0.266666666666666663],"xyz":[0.176204707526942062,0.0896492633318711901,0.0627164795608645409],"hpluv":[1.0062433800652546,354.001763490246503,35.9166782648329104],"hsluv":[1.0062433800652546,99.999999999997,35.9166782648329104]},"#aa0055":{"lch":[36.3730398367095,93.6502679946689369,354.384147096436777],"luv":[36.3730398367095,93.2007806216229113,-9.16445235643848832],"rgb":[0.66666666666666663,0,0.333333333333333315],"xyz":[0.182167121566304047,0.092034228947616023,0.0941185268348384424],"hpluv":[354.384147096436777,326.714758289773386,36.3730398367095],"hsluv":[354.384147096436777,99.9999999999973,36.3730398367095]},"#aa0066":{"lch":[36.9423385777606228,88.2319659172366926,346.039412913085584],"luv":[36.9423385777606228,85.6257622699194,-21.2863488018886251],"rgb":[0.66666666666666663,0,0.4],"xyz":[0.189752117339812232,0.0950682272570193415,0.134066171241982418],"hpluv":[346.039412913085584,303.068568849792825,36.9423385777606228],"hsluv":[346.039412913085584,99.9999999999976126,36.9423385777606228]},"#aa0077":{"lch":[37.6250775946346891,84.9907340508927689,336.365700313169],"luv":[37.6250775946346891,77.8619577045834319,-34.0725757306260348],"rgb":[0.66666666666666663,0,0.466666666666666674],"xyz":[0.199066130360014137,0.0987938324651001509,0.183119973148380327],"hpluv":[336.365700313169,286.637826777930513,37.6250775946346891],"hsluv":[336.365700313169,99.9999999999979536,37.6250775946346891]},"#aa0088":{"lch":[38.4195160158879432,84.5572797483387717,326.161033183527252],"luv":[38.4195160158879432,70.2337789048813761,-47.0866208086656215],"rgb":[0.66666666666666663,0,0.533333333333333326],"xyz":[0.210206547461958,0.103249999305877749,0.241792836551952495],"hpluv":[326.161033183527252,279.279102381419364,38.4195160158879432],"hsluv":[326.161033183527252,99.9999999999982379,38.4195160158879432]},"#aa0099":{"lch":[39.3220484546604681,86.9871636461465272,316.374304421046759],"luv":[39.3220484546604681,62.9667468975572859,-60.0162929906574334],"rgb":[0.66666666666666663,0,0.6],"xyz":[0.223263511571030693,0.108472784949506906,0.310559514193070374],"hpluv":[316.374304421046759,280.710309296009257,39.3220484546604681],"hsluv":[316.374304421046759,99.9999999999986,39.3220484546604681]},"#aa00aa":{"lch":[40.3276007574525863,91.8597353001339627,307.715012949243601],"luv":[40.3276007574525863,56.1937545325413,-72.6668626056414411],"rgb":[0.66666666666666663,0,0.66666666666666663],"xyz":[0.238321204536283249,0.114495862135608,0.389863363810069],"hpluv":[307.715012949243601,289.042783730483393,40.3276007574525863],"hsluv":[307.715012949243601,99.9999999999988205,40.3276007574525863]},"#aa00bb":{"lch":[41.4300227805658849,98.5480850422065089,300.471226581677797],"luv":[41.4300227805658849,49.974285465742625,-84.9370111180893304],"rgb":[0.66666666666666663,0,0.733333333333333282],"xyz":[0.255458796643619868,0.121350898978542759,0.480121348908710721],"hpluv":[300.471226581677797,301.836908489583834,41.4300227805658849],"hsluv":[300.471226581677797,99.9999999999990621,41.4300227805658849]},"#aa00cc":{"lch":[42.6224565622471445,106.453892931925211,294.601049164416338],"luv":[42.6224565622471445,44.3164832708711813,-96.7909119228886681],"rgb":[0.66666666666666663,0,0.8],"xyz":[0.274751172087341622,0.129067849156031561,0.581727859578980877],"hpluv":[294.601049164416338,316.929304470761622,42.6224565622471445],"hsluv":[294.601049164416338,99.9999999999992895,42.6224565622471445]},"#aa00dd":{"lch":[43.8976622887243266,115.112632227118652,289.907671140995035],"luv":[43.8976622887243266,39.1964773946494063,-108.233794436426436],"rgb":[0.66666666666666663,0,0.866666666666666696],"xyz":[0.296269497637975165,0.137675179376285095,0.695057707478986875],"hpluv":[289.907671140995035,332.752186796280228,43.8976622887243266],"hsluv":[289.907671140995035,99.9999999999994174,43.8976622887243266]},"#aa00ee":{"lch":[45.2482911917969233,124.202454763835647,286.162342623679535],"luv":[45.2482911917969233,34.5729825657367655,-119.293581746345012],"rgb":[0.66666666666666663,0,0.933333333333333348],"xyz":[0.320081677904149875,0.14720005148275514,0.820468523547510098],"hpluv":[286.162342623679535,348.311106794177135,45.2482911917969233],"hsluv":[286.162342623679535,99.9999999999996589,45.2482911917969233]},"#aa00ff":{"lch":[46.667101462293175,133.514790614533382,283.159905061129905],"luv":[46.667101462293175,30.397247590160724,-130.008486845225434],"rgb":[0.66666666666666663,0,1],"xyz":[0.346252726313981296,0.157668470846687836,0.958302711839291943],"hpluv":[283.159905061129905,363.042841924949244,46.667101462293175],"hsluv":[283.159905061129905,99.9999999999998153,46.667101462293175]},"#881100":{"lch":[28.4751123640698864,88.1761994811112,13.8943544232398857],"luv":[28.4751123640698864,85.5961768878489124,21.1739617718743069],"rgb":[0.533333333333333326,0.0666666666666666657,0],"xyz":[0.103535562162309969,0.0563608058772578496,0.00542740663443661096],"hpluv":[13.8943544232398857,392.939109149716501,28.4751123640698864],"hsluv":[13.8943544232398857,100.000000000002331,28.4751123640698864]},"#881111":{"lch":[28.5813012406410962,85.6429421929893522,12.1770506300617782],"luv":[28.5813012406410962,83.7160154193071548,18.0649469909557752],"rgb":[0.533333333333333326,0.0666666666666666657,0.0666666666666666657],"xyz":[0.104547227661947087,0.0567654720771127,0.0107555115991922433],"hpluv":[12.1770506300617782,380.232213605760478,28.5813012406410962],"hsluv":[12.1770506300617782,89.1001931926906536,28.5813012406410962]},"#881122":{"lch":[28.776819878520115,81.4294437186752589,8.91447414891876377],"luv":[28.776819878520115,80.445837197505071,12.6183034487767767],"rgb":[0.533333333333333326,0.0666666666666666657,0.133333333333333331],"xyz":[0.106422585800424116,0.0575156153325035238,0.0206323977951714393],"hpluv":[8.91447414891876377,359.069069298387092,28.776819878520115],"hsluv":[8.91447414891876377,89.5522119422979,28.776819878520115]},"#881133":{"lch":[29.0950676619922959,75.7256767264573227,3.35964558590209394],"luv":[29.0950676619922959,75.5955308554484162,4.43777313107212557],"rgb":[0.533333333333333326,0.0666666666666666657,0.2],"xyz":[0.10951033653288185,0.0587507156254866367,0.0368945516527825826],"hpluv":[3.35964558590209394,330.265430862114329,29.0950676619922959],"hsluv":[3.35964558590209394,90.2199940579986475,29.0950676619922959]},"#881144":{"lch":[29.5467689283324617,69.8105982852884779,355.112641815866198],"luv":[29.5467689283324617,69.5567752183087435,-5.94765955478224484],"rgb":[0.533333333333333326,0.0666666666666666657,0.266666666666666663],"xyz":[0.113968331777100723,0.0605339137231742097,0.0603733266056692211],"hpluv":[355.112641815866198,299.81315922456514,29.5467689283324617],"hsluv":[355.112641815866198,91.0462468049379083,29.5467689283324617]},"#881155":{"lch":[30.1372440361953267,65.3247498846549,344.189828060851937],"luv":[30.1372440361953267,62.8534910411243928,-17.7977979378353552],"rgb":[0.533333333333333326,0.0666666666666666657,0.333333333333333315],"xyz":[0.119930745816462722,0.0629188793389190426,0.0917753738796431295],"hpluv":[344.189828060851937,275.05120204756264,30.1372440361953267],"hsluv":[344.189828060851937,91.9552565263170294,30.1372440361953267]},"#881166":{"lch":[30.8672249177773494,63.7021552959616173,331.50461515751158],"luv":[30.8672249177773494,55.9849923977636479,-30.3915319714745138],"rgb":[0.533333333333333326,0.0666666666666666657,0.4],"xyz":[0.127515741589970893,0.0659528776483223611,0.131723018286787091],"hpluv":[331.50461515751158,261.876101180723595,30.8672249177773494],"hsluv":[331.50461515751158,92.8754029221989299,30.8672249177773494]},"#881177":{"lch":[31.7336031237729514,65.5512880923603376,318.81152503011009],"luv":[31.7336031237729514,49.3304506912780525,-43.1680206305895737],"rgb":[0.533333333333333326,0.0666666666666666657,0.466666666666666674],"xyz":[0.136829754610172827,0.0696784828564031705,0.180776820193185],"hpluv":[318.81152503011009,262.120610410187965,31.7336031237729514],"hsluv":[318.81152503011009,93.7528273751248094,31.7336031237729514]},"#881188":{"lch":[32.7302234117729114,70.4946015177073377,307.715012949243658],"luv":[32.7302234117729114,43.1239685223607268,-55.7656900075914663],"rgb":[0.533333333333333326,0.0666666666666666657,0.533333333333333326],"xyz":[0.147970171712116627,0.0741346496971807684,0.239449683596757168],"hpluv":[307.715012949243658,273.304143969878908,32.7302234117729114],"hsluv":[307.715012949243658,94.5549099834012736,32.7302234117729114]},"#881199":{"lch":[33.8487030992268245,77.6382380820710836,298.861624073140206],"luv":[33.8487030992268245,37.4756592651389795,-67.9946393117248249],"rgb":[0.533333333333333326,0.0666666666666666657,0.6],"xyz":[0.161027135821189354,0.0793574353408099259,0.308216361237875103],"hpluv":[298.861624073140206,291.053592363859707,33.8487030992268245],"hsluv":[298.861624073140206,95.267111116431,33.8487030992268245]},"#8811aa":{"lch":[35.0792182273937954,86.1162494337963551,292.107316515455238],"luv":[35.0792182273937954,32.4092110837954692,-79.7850327659882623],"rgb":[0.533333333333333326,0.0666666666666666657,0.66666666666666663],"xyz":[0.176084828786441883,0.0853805125269110343,0.387520210854873703],"hpluv":[292.107316515455238,311.511817997128389,35.0792182273937954],"hsluv":[292.107316515455238,95.8874450484264571,35.0792182273937954]},"#8811bb":{"lch":[36.4111998559147381,95.3124415598142,287.019214731984619],"luv":[36.4111998559147381,27.8972267898096504,-91.1383906678789515],"rgb":[0.533333333333333326,0.0666666666666666657,0.733333333333333282],"xyz":[0.193222420893778557,0.0922355493698457929,0.47777819595351545],"hpluv":[287.019214731984619,332.16504711372977,36.4111998559147381],"hsluv":[287.019214731984619,96.4212920970111753,36.4111998559147381]},"#8811cc":{"lch":[37.8339039869932847,104.849214202707898,283.169050576302368],"luv":[37.8339039869932847,23.8872658659353974,-102.091900993053514],"rgb":[0.533333333333333326,0.0666666666666666657,0.8],"xyz":[0.212514796337500284,0.0999524995473346,0.579384706623785606],"hpluv":[283.169050576302368,351.660305548048939,37.8339039869932847],"hsluv":[283.169050576302368,96.8775739500717776,37.8339039869932847]},"#8811dd":{"lch":[39.3368423655390274,114.513051177954694,280.22024610097435],"luv":[39.3368423655390274,20.3183376083265372,-112.696069349906494],"rgb":[0.533333333333333326,0.0666666666666666657,0.866666666666666696],"xyz":[0.234033121888133827,0.108559829767588129,0.692714554523791604],"hpluv":[280.22024610097435,369.398236331583689,39.3368423655390274],"hsluv":[280.22024610097435,97.2663289333616348,39.3368423655390274]},"#8811ee":{"lch":[40.9100807353410261,124.189527798253138,277.928390028110698],"luv":[40.9100807353410261,17.130123009315259,-123.002429652583771],"rgb":[0.533333333333333326,0.0666666666666666657,0.933333333333333348],"xyz":[0.257845302154308564,0.118084701874058146,0.818125370592314827],"hpluv":[277.928390028110698,385.206818333834917,40.9100807353410261],"hsluv":[277.928390028110698,97.5973562787359867,40.9100807353410261]},"#8811ff":{"lch":[42.5444231432324926,133.820472646418182,276.120297984259253],"luv":[42.5444231432324926,14.2674470621751119,-133.057727523202459],"rgb":[0.533333333333333326,0.0666666666666666657,1],"xyz":[0.28401635056414,0.128553121237990842,0.955959558884096672],"hpluv":[276.120297984259253,399.134479754608662,42.5444231432324926],"hsluv":[276.120297984259253,99.9999999999993605,42.5444231432324926]},"#aa1100":{"lch":[35.8849415951509485,114.659477700983,13.2232466646238507],"luv":[35.8849415951509485,111.619416231509064,26.2278810962561089],"rgb":[0.66666666666666663,0.0666666666666666657,0],"xyz":[0.167776338173079714,0.0894849560078117,0.00843869300994137816],"hpluv":[13.2232466646238507,405.449754626827882,35.8849415951509485],"hsluv":[13.2232466646238507,100.000000000002245,35.8849415951509485]},"#aa1111":{"lch":[35.9630348414680086,112.584844162769954,12.1770506300617871],"luv":[35.9630348414680086,110.051736997450746,23.747890832642895],"rgb":[0.66666666666666663,0.0666666666666666657,0.0666666666666666657],"xyz":[0.168788003672716846,0.089889622207666553,0.0137667979746970096],"hpluv":[12.1770506300617871,397.249101663635656,35.9630348414680086],"hsluv":[12.1770506300617871,93.0877775141683514,35.9630348414680086]},"#aa1122":{"lch":[36.1071812157442409,108.986817867719594,10.2082214608018411],"luv":[36.1071812157442409,107.261576994584843,19.3152936702042],"rgb":[0.66666666666666663,0.0666666666666666657,0.133333333333333331],"xyz":[0.170663361811193848,0.0906397654630573674,0.0236436841706762074],"hpluv":[10.2082214608018411,383.018466712830786,36.1071812157442409],"hsluv":[10.2082214608018411,93.272361347425246,36.1071812157442409]},"#aa1133":{"lch":[36.3427932754706546,103.718469067724868,6.89182233030552727],"luv":[36.3427932754706546,102.969049051934846,12.4457126390109512],"rgb":[0.66666666666666663,0.0666666666666666657,0.2],"xyz":[0.173751112543651609,0.0918748657560404802,0.0399058380282873507],"hpluv":[6.89182233030552727,362.140519718911037,36.3427932754706546],"hsluv":[6.89182233030552727,93.5557024333493388,36.3427932754706546]},"#aa1144":{"lch":[36.6792659124992824,97.4113439982971698,1.97455903872184],"luv":[36.6792659124992824,97.3535035649005778,3.35637947697775552],"rgb":[0.66666666666666663,0.0666666666666666657,0.266666666666666663],"xyz":[0.178209107787870469,0.0936580638537280602,0.0633846129811739822],"hpluv":[1.97455903872184,336.99870087691761,36.6792659124992824],"hsluv":[1.97455903872184,93.9250914747756696,36.6792659124992824]},"#aa1155":{"lch":[37.1226754299384396,91.055498296574811,355.267689161716703],"luv":[37.1226754299384396,90.7450919896636634,-7.51212685096688926],"rgb":[0.66666666666666663,0.0666666666666666657,0.333333333333333315],"xyz":[0.184171521827232454,0.0960430294694729,0.0947866602551479],"hpluv":[355.267689161716703,311.247759321881176,37.1226754299384396],"hsluv":[355.267689161716703,94.3576556410013154,37.1226754299384396]},"#aa1166":{"lch":[37.6762679798416,85.8108023849569577,346.783206271719791],"luv":[37.6762679798416,83.5378398512485205,-19.6194576616503156],"rgb":[0.66666666666666663,0.0666666666666666657,0.4],"xyz":[0.191756517600740639,0.0990770277788762116,0.134734304662291859],"hpluv":[346.783206271719791,289.010360822200312,37.6762679798416],"hsluv":[346.783206271719791,94.8263018378468558,37.6762679798416]},"#aa1177":{"lch":[38.3408051028578285,82.7345113545946163,336.916515476294876],"luv":[38.3408051028578285,76.110335477500783,-32.4378822148708],"rgb":[0.66666666666666663,0.0666666666666666657,0.466666666666666674],"xyz":[0.201070530620942545,0.102802632986957021,0.183788106568689769],"hpluv":[336.916515476294876,273.819772016881302,38.3408051028578285],"hsluv":[336.916515476294876,95.3051408978498387,38.3408051028578285]},"#aa1188":{"lch":[39.1148927869010379,82.477083595297529,326.495944929629673],"luv":[39.1148927869010379,68.7732486834780445,-45.5270203714912753],"rgb":[0.66666666666666663,0.0666666666666666657,0.533333333333333326],"xyz":[0.212210947722886401,0.107258799827734619,0.242460969972261936],"hpluv":[326.495944929629673,267.565723971153261,39.1148927869010379],"hsluv":[326.495944929629673,95.7730681487448,39.1148927869010379]},"#aa1199":{"lch":[39.9953287808464424,85.1038505069809617,316.515705271857257],"luv":[39.9953287808464424,61.7482074461545665,-58.5647013848890552],"rgb":[0.66666666666666663,0.0666666666666666657,0.6],"xyz":[0.2252679118319591,0.112481585471363776,0.311227647613379843],"hpluv":[316.515705271857257,270.00963724100518,39.9953287808464424],"hsluv":[316.515705271857257,96.2151887572794,39.9953287808464424]},"#aa11aa":{"lch":[40.9774666162921406,90.1875437006381588,307.715012949243601],"luv":[40.9774666162921406,55.1708175083225498,-71.3440532505540261],"rgb":[0.66666666666666663,0.0666666666666666657,0.66666666666666663],"xyz":[0.240325604797211656,0.118504662657464871,0.390531497230378444],"hpluv":[307.715012949243601,279.28060733669264,40.9774666162921406],"hsluv":[307.715012949243601,96.6225842874192864,40.9774666162921406]},"#aa11bb":{"lch":[42.0555802442747719,97.087212137786878,300.384453602166161],"luv":[42.0555802442747719,49.106684193967304,-83.7523750598249705],"rgb":[0.66666666666666663,0.0666666666666666657,0.733333333333333282],"xyz":[0.257463196904548275,0.12535969950039963,0.48078948232902019],"hpluv":[300.384453602166161,292.939359498794147,42.0555802442747719],"hsluv":[300.384453602166161,96.9911870522472697,42.0555802442747719]},"#aa11cc":{"lch":[43.2232098485165395,105.192683835863036,294.469145625450437],"luv":[43.2232098485165395,43.5711419401365,-95.7447456658814247],"rgb":[0.66666666666666663,0.0666666666666666657,0.8],"xyz":[0.276755572348270029,0.133076649677888431,0.582395992999290346],"hpluv":[294.469145625450437,308.821726609797679,43.2232098485165395],"hsluv":[294.469145625450437,97.3204020480748255,43.2232098485165395]},"#aa11dd":{"lch":[44.4734721926781518,114.032755796715193,289.757274940509092],"luv":[44.4734721926781518,38.5472014936014489,-107.320001172218454],"rgb":[0.66666666666666663,0.0666666666666666657,0.866666666666666696],"xyz":[0.298273897898903573,0.141683979898141965,0.695725840899296344],"hpluv":[289.757274940509092,325.362808980276498,44.4734721926781518],"hsluv":[289.757274940509092,97.611854654502622,44.4734721926781518]},"#aa11ee":{"lch":[45.7993244881172,123.283094749558884,286.008743686799619],"luv":[45.7993244881172,33.9995108001485136,-118.502129585840351],"rgb":[0.66666666666666663,0.0666666666666666657,0.933333333333333348],"xyz":[0.322086078165078282,0.151208852004612,0.821136656967819567],"hpluv":[286.008743686799619,341.573194884792258,45.7993244881172],"hsluv":[286.008743686799619,97.8684161167955153,45.7993244881172]},"#aa11ff":{"lch":[47.1937769411101868,132.735165800167636,283.011169167098501],"luv":[47.1937769411101868,29.8841269734434611,-129.327348983241365],"rgb":[0.66666666666666663,0.0666666666666666657,1],"xyz":[0.348257126574909703,0.161677271368544706,0.958970845259601412],"hpluv":[283.011169167098501,356.89510187446183,47.1937769411101868],"hsluv":[283.011169167098501,99.9999999999993321,47.1937769411101868]},"#882200":{"lch":[30.3496916993887922,81.7292062801124786,17.2000641303745212],"luv":[30.3496916993887922,78.0741152618852254,24.1680716080335465],"rgb":[0.533333333333333326,0.133333333333333331,0],"xyz":[0.107251185897077911,0.0637920533467938311,0.00666594787935922105],"hpluv":[17.2000641303745212,341.713647377264522,30.3496916993887922],"hsluv":[17.2000641303745212,100.000000000002359,30.3496916993887922]},"#882211":{"lch":[30.4474919309639347,79.3871193031655338,15.4743840495427136],"luv":[30.4474919309639347,76.5093230935452908,21.181080969170015],"rgb":[0.533333333333333326,0.133333333333333331,0.0666666666666666657],"xyz":[0.108262851396715029,0.064196719546648684,0.0119940528441148525],"hpluv":[15.4743840495427136,330.855109199112462,30.4474919309639347],"hsluv":[15.4743840495427136,90.2707057474005,30.4474919309639347]},"#882222":{"lch":[30.6277058928754826,75.4670009360781648,12.1770506300618102],"luv":[30.6277058928754826,73.7690281561900321,15.9185022906448506],"rgb":[0.533333333333333326,0.133333333333333331,0.133333333333333331],"xyz":[0.110138209535192058,0.0649468628020395,0.0218709390400940486],"hpluv":[12.1770506300618102,312.666930334371557,30.6277058928754826],"hsluv":[12.1770506300618102,73.2675530922876277,30.6277058928754826]},"#882233":{"lch":[30.9214262019897674,70.1124269978110135,6.50693872003014],"luv":[30.9214262019897674,69.6607724946186266,7.94538828354938],"rgb":[0.533333333333333326,0.133333333333333331,0.2],"xyz":[0.113225960267649792,0.0661819630950226112,0.0381330928977051953],"hpluv":[6.50693872003014,287.723152758323693,30.9214262019897674],"hsluv":[6.50693872003014,74.8097141082451458,30.9214262019897674]},"#882244":{"lch":[31.3391119188553589,64.5127804411509,357.965654494967],"luv":[31.3391119188553589,64.472119792654567,-2.29011128326569047],"rgb":[0.533333333333333326,0.133333333333333331,0.266666666666666663],"xyz":[0.117683955511868665,0.0679651611927101912,0.0616118678505918338],"hpluv":[357.965654494967,261.215173773686786,31.3391119188553589],"hsluv":[357.965654494967,76.7464797952550839,31.3391119188553589]},"#882255":{"lch":[31.8864840032734449,60.2907989794282599,346.464164292394514],"luv":[31.8864840032734449,58.6161449596217778,-14.1112717942230379],"rgb":[0.533333333333333326,0.133333333333333331,0.333333333333333315],"xyz":[0.123646369551230664,0.0703501268084550241,0.0930139151245657353],"hpluv":[346.464164292394514,239.929545755427228,31.8864840032734449],"hsluv":[346.464164292394514,78.9147131880069566,31.8864840032734449]},"#882266":{"lch":[32.565220274416383,58.9629659850378189,332.945096803324191],"luv":[32.565220274416383,52.5107124518348698,-26.8189566455043362],"rgb":[0.533333333333333326,0.133333333333333331,0.4],"xyz":[0.131231365324738836,0.0733841251178583426,0.132961559531709711],"hpluv":[332.945096803324191,229.754818264706444,32.565220274416383],"hsluv":[332.945096803324191,81.1505919454384923,32.565220274416383]},"#882277":{"lch":[33.3735533542235316,61.2256527964903086,319.411642653163199],"luv":[33.3735533542235316,46.4949769025583564,-39.8346291960518499],"rgb":[0.533333333333333326,0.133333333333333331,0.466666666666666674],"xyz":[0.140545378344940741,0.077109730325939152,0.18201536143810762],"hpluv":[319.411642653163199,232.79320602780777,33.3735533542235316],"hsluv":[319.411642653163199,83.3222334130424116,33.3735533542235316]},"#882288":{"lch":[34.3068967831130962,66.691064714973308,307.715012949243771],"luv":[34.3068967831130962,40.7972144472485709,-52.7568517461189046],"rgb":[0.533333333333333326,0.133333333333333331,0.533333333333333326],"xyz":[0.151685795446884597,0.0815658971667167498,0.240688224841679788],"hpluv":[307.715012949243771,246.675229855048,34.3068967831130962],"hsluv":[307.715012949243771,85.3421167175917,34.3068967831130962]},"#882299":{"lch":[35.3585028262625087,74.3915148492043699,298.539568373309862],"luv":[35.3585028262625087,35.5417034620318262,-65.3520068289902554],"rgb":[0.533333333333333326,0.133333333333333331,0.6],"xyz":[0.164742759555957297,0.0867886828103459074,0.309454902482797667],"hpluv":[298.539568373309862,266.973934190138948,35.3585028262625087],"hsluv":[298.539568373309862,87.1641407220543556,35.3585028262625087]},"#8822aa":{"lch":[36.5201138266519365,83.3993900511107142,291.653660077047903],"luv":[36.5201138266519365,30.7739719973965897,-77.5140045953036463],"rgb":[0.533333333333333326,0.133333333333333331,0.66666666666666663],"xyz":[0.179800452521209853,0.092811759996447,0.388758752099796268],"hpluv":[291.653660077047903,289.781114528802732,36.5201138266519365],"hsluv":[291.653660077047903,88.7734689989794532,36.5201138266519365]},"#8822bb":{"lch":[37.7825623664262196,93.0686060696910857,286.53575696187113],"luv":[37.7825623664262196,26.4885972028076893,-89.2195026548722],"rgb":[0.533333333333333326,0.133333333333333331,0.733333333333333282],"xyz":[0.196938044628546471,0.0996667968393817605,0.479016737198438],"hpluv":[286.53575696187113,312.57276028475934,37.7825623664262196],"hsluv":[286.53575696187113,90.1753980157506874,37.7825623664262196]},"#8822cc":{"lch":[39.1362858369643476,103.012880313051866,282.702767559286599],"luv":[39.1362858369643476,22.6518448072254479,-100.491529181421669],"rgb":[0.533333333333333326,0.133333333333333331,0.8],"xyz":[0.216230420072268226,0.107383747016870562,0.580623247868708225],"hpluv":[282.702767559286599,334.003678399645651,39.1362858369643476],"hsluv":[282.702767559286599,91.3862929083300628,39.1362858369643476]},"#8822dd":{"lch":[40.5717373677475379,113.020349666590874,279.789793007972776],"luv":[40.5717373677475379,19.2172965257181652,-111.374570495248548],"rgb":[0.533333333333333326,0.133333333333333331,0.866666666666666696],"xyz":[0.237748745622901769,0.115991077237124096,0.693953095768714223],"hpluv":[279.789793007972776,353.486121759760863,40.5717373677475379],"hsluv":[279.789793007972776,92.4273238443811209,40.5717373677475379]},"#8822ee":{"lch":[42.0796906219744145,122.982600065668066,277.538986095624125],"luv":[42.0796906219744145,16.1354126197819454,-121.919515986988074],"rgb":[0.533333333333333326,0.133333333333333331,0.933333333333333348],"xyz":[0.261560925889076534,0.125515949343594141,0.819363911837237446],"hpluv":[277.538986095624125,370.860397035002336,42.0796906219744145],"hsluv":[277.538986095624125,93.320628909539181,42.0796906219744145]},"#8822ff":{"lch":[43.6514473624058752,132.848943476626658,275.771185477405766],"luv":[43.6514473624058752,13.3587518063908028,-132.175585994657865],"rgb":[0.533333333333333326,0.133333333333333331,1],"xyz":[0.2877319742989079,0.135984368707526837,0.957198100129019291],"hpluv":[275.771185477405766,386.188007357759091,43.6514473624058752],"hsluv":[275.771185477405766,99.9999999999994,43.6514473624058752]},"#ffaa00":{"lch":[76.0766826449234799,103.646966048157225,46.9849230608437125],"luv":[76.0766826449234799,70.7070052858721,75.7839889059127785],"rgb":[1,0.66666666666666663,0],"xyz":[0.556131758114240538,0.500120923568095,0.0672444716650198171],"hpluv":[46.9849230608437125,173.218766512771339,76.0766826449234799],"hsluv":[46.9849230608437125,100.0000000000028,76.0766826449234799]},"#ffaa11":{"lch":[76.1015101579349533,102.726050652762069,46.6846637022245687],"luv":[76.1015101579349533,70.4714195905473275,74.7423608377930719],"rgb":[1,0.66666666666666663,0.0666666666666666657],"xyz":[0.557143423613877697,0.500525589767949919,0.0725725766297754538],"hpluv":[46.6846637022245687,171.896872437304751,76.1015101579349533],"hsluv":[46.6846637022245687,100.000000000002771,76.1015101579349533]},"#ffaa22":{"lch":[76.1474983763177,101.038792737361192,46.1176753587789605],"luv":[76.1474983763177,70.0380208569547591,72.8252241483965719],"rgb":[1,0.66666666666666663,0.133333333333333331],"xyz":[0.559018781752354643,0.501275733023340719,0.0824494628257546464],"hpluv":[46.1176753587789605,169.470349592440897,76.1474983763177],"hsluv":[46.1176753587789605,100.0000000000028,76.1474983763177]},"#ffaa33":{"lch":[76.2231174741888395,98.3169656691378577,45.1538509265191337],"luv":[76.2231174741888395,69.3336656617894533,69.7070193329597885],"rgb":[1,0.66666666666666663,0.2],"xyz":[0.56210653248481246,0.502510833316323846,0.0987116166833657827],"hpluv":[45.1538509265191337,165.543337136749699,76.2231174741888395],"hsluv":[45.1538509265191337,100.000000000002927,76.2231174741888395]},"#ffaa44":{"lch":[76.3320756204529118,94.5107446089494516,43.6926927141772694],"luv":[76.3320756204529118,68.3364903114306514,65.2870962629968119],"rgb":[1,0.66666666666666663,0.266666666666666663],"xyz":[0.56656452772903132,0.504294031414011412,0.122190391636252421],"hpluv":[43.6926927141772694,160.025535099593441,76.3320756204529118],"hsluv":[43.6926927141772694,100.000000000003,76.3320756204529118]},"#ffaa55":{"lch":[76.4774026026215,89.6489515946998807,41.6012791226812411],"luv":[76.4774026026215,67.0379860163697288,59.5217855318358247],"rgb":[1,0.66666666666666663,0.333333333333333315],"xyz":[0.572526941768393249,0.506678997029756162,0.153592438910226337],"hpluv":[41.6012791226812411,152.933128718005122,76.4774026026215],"hsluv":[41.6012791226812411,100.000000000003,76.4774026026215]},"#ffaa66":{"lch":[76.6616205587261,83.8466863985853905,38.6944265301345354],"luv":[76.6616205587261,65.4416029270402788,52.418159318716242],"rgb":[1,0.66666666666666663,0.4],"xyz":[0.58011193754190149,0.50971299533915948,0.193540083317370298],"hpluv":[38.6944265301345354,144.405277715469396,76.6616205587261],"hsluv":[38.6944265301345354,100.000000000003197,76.6616205587261]},"#ffaa77":{"lch":[76.8868341725165,77.3210793721064533,34.7099370327462324],"luv":[76.8868341725165,63.5614296008349058,44.0283315873505927],"rgb":[1,0.66666666666666663,0.466666666666666674],"xyz":[0.58942595056210334,0.513438600547240331,0.242593885223768208],"hpluv":[34.7099370327462324,134.738986801151128,76.8868341725165],"hsluv":[34.7099370327462324,100.000000000003354,76.8868341725165]},"#ffaa88":{"lch":[77.1547840912050873,70.4186738688562741,29.282319230158226],"luv":[77.1547840912050873,61.4205932059712723,34.4427112706728948],"rgb":[1,0.66666666666666663,0.533333333333333326],"xyz":[0.600566367664047251,0.517894767388017874,0.301266748627340375],"hpluv":[29.282319230158226,124.451835787871019,77.1547840912050873],"hsluv":[29.282319230158226,100.000000000003638,77.1547840912050873]},"#ffaa99":{"lch":[77.466881654564645,63.658531214354845,21.9370110659791244],"luv":[77.466881654564645,59.0493431107362383,23.7820031654092716],"rgb":[1,0.66666666666666663,0.6],"xyz":[0.613623331773119896,0.523117553031647087,0.370033426268458254],"hpluv":[21.9370110659791244,114.385173247539697,77.466881654564645],"hsluv":[21.9370110659791244,100.000000000003624,77.466881654564645]},"#ffaaaa":{"lch":[77.8242336850598,57.783013099698,12.1770506300621957],"luv":[77.8242336850598,56.482921905318662,12.1883606739193855],"rgb":[1,0.66666666666666663,0.66666666666666663],"xyz":[0.628681024738372507,0.529140630217748154,0.44933727588545691],"hpluv":[12.1770506300621957,105.841692205508735,77.8242336850598],"hsluv":[12.1770506300621957,100.000000000003837,77.8242336850598]},"#ffaabb":{"lch":[78.227662021793833,53.7597014753195,359.804273109779956],"luv":[78.227662021793833,53.7593877986938224,-0.183647012281759531],"rgb":[1,0.66666666666666663,0.733333333333333282],"xyz":[0.64581861684570907,0.535995667060682912,0.539595260984098601],"hpluv":[359.804273109779956,100.661858044669231,78.227662021793833],"hsluv":[359.804273109779956,100.000000000004135,78.227662021793833]},"#ffaacc":{"lch":[78.6777204654413254,52.5946111834740293,345.492217824016791],"luv":[78.6777204654413254,50.9175596191628586,-13.1755549397286202],"rgb":[1,0.66666666666666663,0.8],"xyz":[0.665110992289430825,0.543712617238171769,0.641201771654368757],"hpluv":[345.492217824016791,100.966318741741958,78.6777204654413254],"hsluv":[345.492217824016791,100.000000000004306,78.6777204654413254]},"#ffaadd":{"lch":[79.1747106956411244,54.8892328831665353,330.97422205899818],"luv":[79.1747106956411244,47.9952274547753177,-26.6324243745640352],"rgb":[1,0.66666666666666663,0.866666666666666696],"xyz":[0.686629317840064424,0.552319947458425275,0.754531619554374755],"hpluv":[330.97422205899818,108.36723319715793,79.1747106956411244],"hsluv":[330.97422205899818,100.000000000004704,79.1747106956411244]},"#ffaaee":{"lch":[79.718698064048283,60.5009523664383337,318.094564198374599],"luv":[79.718698064048283,45.0277239197174595,-40.4087777080146822],"rgb":[1,0.66666666666666663,0.933333333333333348],"xyz":[0.710441498106239133,0.561844819564895293,0.879942435622898],"hpluv":[318.094564198374599,123.247069988098687,79.718698064048283],"hsluv":[318.094564198374599,100.000000000004945,79.718698064048283]},"#ffaaff":{"lch":[80.3095277487323074,68.733917080261989,307.715012949245647],"luv":[80.3095277487323074,42.0468973903394,-54.3728772187255203],"rgb":[1,0.66666666666666663,1],"xyz":[0.736612546516070554,0.572313238928828,1.01777662391468],"hpluv":[307.715012949245647,144.979279509576116,80.3095277487323074],"hsluv":[307.715012949245647,100.000000000005301,80.3095277487323074]},"#aa2200":{"lch":[37.2831780533064929,108.910935722579069,15.2092016225530191],"luv":[37.2831780533064929,105.096262108869439,28.5721474641225],"rgb":[0.66666666666666663,0.133333333333333331,0],"xyz":[0.171491961907847656,0.0969162034773476816,0.00967723425486398912],"hpluv":[15.2092016225530191,370.67892165569458,37.2831780533064929],"hsluv":[15.2092016225530191,100.000000000002217,37.2831780533064929]},"#aa2211":{"lch":[37.3572350214345619,106.95640568906397,14.158492547926917],"luv":[37.3572350214345619,103.707370245599336,26.1620732103901794],"rgb":[0.66666666666666663,0.133333333333333331,0.0666666666666666657],"xyz":[0.172503627407484789,0.0973208696772025345,0.0150053392196196206],"hpluv":[14.158492547926917,363.305022455593,37.3572350214345619],"hsluv":[14.158492547926917,93.5777596020973732,37.3572350214345619]},"#aa2222":{"lch":[37.4939757158163331,103.55828406892158,12.1770506300617907],"luv":[37.4939757158163331,101.228270350344232,21.8438888748564],"rgb":[0.66666666666666663,0.133333333333333331,0.133333333333333331],"xyz":[0.17437898554596179,0.0980710129325933488,0.0248822254155988166],"hpluv":[12.1770506300617907,350.479546677114797,37.4939757158163331],"hsluv":[12.1770506300617907,82.128221128038831,37.4939757158163331]},"#aa2233":{"lch":[37.7176061419824791,98.5638584928897359,8.82735266140639],"luv":[37.7176061419824791,97.3963926843060506,15.125372494284127],"rgb":[0.66666666666666663,0.133333333333333331,0.2],"xyz":[0.177466736278419523,0.0993061132255764617,0.0411443792732099634],"hpluv":[8.82735266140639,331.598763076121088,37.7176061419824791],"hsluv":[8.82735266140639,82.8309253801110401,37.7176061419824791]},"#aa2244":{"lch":[38.0372287502177358,92.5577577991589209,3.83362915136278648],"luv":[38.0372287502177358,92.350650343690134,6.18836892123021798],"rgb":[0.66666666666666663,0.133333333333333331,0.266666666666666663],"xyz":[0.181924731522638411,0.101089311323264042,0.0646231542260966],"hpluv":[3.83362915136278648,308.775819843535,38.0372287502177358],"hsluv":[3.83362915136278648,83.7532195801290698,38.0372287502177358]},"#aa2255":{"lch":[38.4588905236098242,86.4856662057644172,356.973865768881865],"luv":[38.4588905236098242,86.3650670431288603,-4.56570407393633459],"rgb":[0.66666666666666663,0.133333333333333331,0.333333333333333315],"xyz":[0.187887145562000424,0.103474276939008875,0.0960252015000705],"hpluv":[356.973865768881865,285.355803984318584,38.4588905236098242],"hsluv":[356.973865768881865,84.8422496447961,38.4588905236098242]},"#aa2266":{"lch":[38.9860395203518237,81.4924101374980268,348.227712846231327],"luv":[38.9860395203518237,79.7783138580272464,-16.6262908668256522],"rgb":[0.66666666666666663,0.133333333333333331,0.4],"xyz":[0.195472141335508581,0.106508275248412193,0.135972845907214479],"hpluv":[348.227712846231327,265.245100213362434,38.9860395203518237],"hsluv":[348.227712846231327,86.0332228090823747,38.9860395203518237]},"#aa2277":{"lch":[39.619833929041036,78.6591168776988354,337.990195281021442],"luv":[39.619833929041036,72.9264197190586572,-29.4787037526953952],"rgb":[0.66666666666666663,0.133333333333333331,0.466666666666666674],"xyz":[0.204786154355710515,0.110233880456493,0.185026647813612388],"hpluv":[337.990195281021442,251.92759566726761,39.619833929041036],"hsluv":[337.990195281021442,87.2621982611374278,39.619833929041036]},"#aa2288":{"lch":[40.3594266716885386,78.6767938432408,327.148786779116733],"luv":[40.3594266716885386,66.0949636498191637,-42.6789605025813046],"rgb":[0.66666666666666663,0.133333333333333331,0.533333333333333326],"xyz":[0.215926571457654315,0.1146900472972706,0.243699511217184556],"hpluv":[327.148786779116733,247.366561360315984,40.3594266716885386],"hsluv":[327.148786779116733,88.4751585260979283,40.3594266716885386]},"#aa2299":{"lch":[41.2022629883412748,81.6302410017403162,316.790315261789033],"luv":[41.2022629883412748,59.4964385039503,-55.8898027492302489],"rgb":[0.66666666666666663,0.133333333333333331,0.6],"xyz":[0.228983535566727042,0.119912832940899758,0.312466188858302463],"hpluv":[316.790315261789033,251.402351399829286,41.2022629883412748],"hsluv":[316.790315261789033,89.6322731802278554,41.2022629883412748]},"#aa22aa":{"lch":[42.1443943233873242,87.0780915666379229,307.715012949243715],"luv":[42.1443943233873242,53.2686588598376076,-68.8842798769212834],"rgb":[0.66666666666666663,0.133333333333333331,0.66666666666666663],"xyz":[0.24404122853197957,0.125935910127000866,0.391770038475301063],"hpluv":[307.715012949243715,262.185344504614818,42.1443943233873242],"hsluv":[307.715012949243715,90.7081440057972515,42.1443943233873242]},"#aa22bb":{"lch":[43.1807973125030387,94.3504956605328573,300.218008125398399],"luv":[43.1807973125030387,47.4858085519839577,-81.5298351375283801],"rgb":[0.66666666666666663,0.133333333333333331,0.733333333333333282],"xyz":[0.261178820639316245,0.132790946969935625,0.48202802357394281],"hpluv":[300.218008125398399,277.263598469343151,43.1807973125030387],"hsluv":[300.218008125398399,91.6896384965505291,43.1807973125030387]},"#aa22cc":{"lch":[44.3056820912093627,102.813108633557576,294.217612554784239],"luv":[44.3056820912093627,42.1742864712375294,-93.764944769021767],"rgb":[0.66666666666666663,0.133333333333333331,0.8],"xyz":[0.280471196083037944,0.140507897147424426,0.583634534244213],"hpluv":[294.217612554784239,294.461411899371626,44.3056820912093627],"hsluv":[294.217612554784239,92.5728114271618097,44.3056820912093627]},"#aa22dd":{"lch":[45.5127751844210451,111.980933923074502,289.471886144522102],"luv":[45.5127751844210451,37.3282042805071441,-105.576203414769125],"rgb":[0.66666666666666663,0.133333333333333331,0.866666666666666696],"xyz":[0.301989521633671543,0.14911522736767796,0.696964382144219],"hpluv":[289.471886144522102,312.212361278410071,45.5127751844210451],"hsluv":[289.471886144522102,93.3598993754704622,45.5127751844210451]},"#aa22ee":{"lch":[46.7955661660676938,121.524022862348417,285.718434714393425],"luv":[46.7955661660676938,32.9220942551774698,-116.979587289842115],"rgb":[0.66666666666666663,0.133333333333333331,0.933333333333333348],"xyz":[0.325801701899846252,0.158640099474147978,0.822375198212742187],"hpluv":[285.718434714393425,329.531365671141714,46.7955661660676938],"hsluv":[285.718434714393425,94.0568560040361348,46.7955661660676938]},"#aa22ff":{"lch":[48.1475121680676921,131.233078667623346,282.730941389390409],"luv":[48.1475121680676921,28.9202258451599548,-128.006802450680539],"rgb":[0.66666666666666663,0.133333333333333331,1],"xyz":[0.351972750309677673,0.169108518838080701,0.960209386504524],"hpluv":[282.730941389390409,345.866733454918517,48.1475121680676921],"hsluv":[282.730941389390409,99.9999999999992,48.1475121680676921]},"#883300":{"lch":[33.1414787667816597,73.2165592554870841,22.9600016117944072],"luv":[33.1414787667816597,67.4161530625393084,28.5609323282788417],"rgb":[0.533333333333333326,0.2,0],"xyz":[0.113368907986088716,0.076027497524815621,0.00870518857569610102],"hpluv":[22.9600016117944072,280.334636286210525,33.1414787667816597],"hsluv":[22.9600016117944072,100.000000000002245,33.1414787667816597]},"#883311":{"lch":[33.2285118286029402,71.0572306739368287,21.2511434941679589],"luv":[33.2285118286029402,66.2253841559006844,25.7551650053430592],"rgb":[0.533333333333333326,0.2,0.0666666666666666657],"xyz":[0.114380573485725834,0.0764321637246704738,0.0140332935404517325],"hpluv":[21.2511434941679589,271.354302974885854,33.2285118286029402],"hsluv":[21.2511434941679589,91.7325092821930355,33.2285118286029402]},"#883322":{"lch":[33.389038834633638,67.403958774683133,17.9527330699243208],"luv":[33.389038834633638,64.1221355411587126,20.7760774002325519],"rgb":[0.533333333333333326,0.2,0.133333333333333331],"xyz":[0.116255931624202863,0.0771823069800612882,0.0239101797364309268],"hpluv":[17.9527330699243208,256.165602847605,33.389038834633638],"hsluv":[17.9527330699243208,77.1564226992543354,33.389038834633638]},"#883333":{"lch":[33.6510932573449324,62.3280121609532785,12.1770506300618564],"luv":[33.6510932573449324,60.9256605799824484,13.1470522486492083],"rgb":[0.533333333333333326,0.2,0.2],"xyz":[0.119343682356660596,0.0784174072730444,0.04017233359404207],"hpluv":[12.1770506300618564,235.030067027939708,33.6510932573449324],"hsluv":[12.1770506300618564,55.0748296144977,33.6510932573449324]},"#883344":{"lch":[34.0246284162643136,56.9037682047597428,3.23132728809417369],"luv":[34.0246284162643136,56.8132965471078748,3.20751794249172528],"rgb":[0.533333333333333326,0.2,0.266666666666666663],"xyz":[0.12380167760087947,0.080200605370731981,0.0636511085469287086],"hpluv":[3.23132728809417369,212.220318588139889,34.0246284162643136],"hsluv":[3.23132728809417369,58.083398150148156,34.0246284162643136]},"#883355":{"lch":[34.5156618951709859,52.7529688087382524,350.767304332875],"luv":[34.5156618951709859,52.0695471674777721,-8.46392201697997137],"rgb":[0.533333333333333326,0.2,0.333333333333333315],"xyz":[0.129764091640241469,0.0825855709864768139,0.0950531558209026239],"hpluv":[350.767304332875,193.941176615342812,34.5156618951709859],"hsluv":[350.767304332875,61.5291535706030714,34.5156618951709859]},"#883366":{"lch":[35.1268460128593318,51.5738240122621576,335.705329263136434],"luv":[35.1268460128593318,47.0065260432940519,-21.2189969741481157],"rgb":[0.533333333333333326,0.2,0.4],"xyz":[0.137349087413749654,0.0856195692958801324,0.135000800228046586],"hpluv":[335.705329263136434,186.307141954737205,35.1268460128593318],"hsluv":[335.705329263136434,65.1713869724459869,35.1268460128593318]},"#883377":{"lch":[35.8579115963162849,54.2604071268956929,320.552373035814298],"luv":[35.8579115963162849,41.9001950458929713,-34.4755773946224],"rgb":[0.533333333333333326,0.2,0.466666666666666674],"xyz":[0.14666310043395156,0.0893451745039609418,0.184054602134444495],"hpluv":[320.552373035814298,192.015984070736607,35.8579115963162849],"hsluv":[320.552373035814298,68.798738775930957,35.8579115963162849]},"#883388":{"lch":[36.7061150242973682,60.4128011412536097,307.715012949244056],"luv":[36.7061150242973682,36.9565850245806402,-47.7903480323547711],"rgb":[0.533333333333333326,0.2,0.533333333333333326],"xyz":[0.157803517535895388,0.0938013413447385397,0.242727465538016662],"hpluv":[307.715012949244056,208.847787272345244,36.7061150242973682],"hsluv":[307.715012949244056,72.2549736675254479,36.7061150242973682]},"#883399":{"lch":[37.6667130487112445,68.9141309342046213,297.955533412138379],"luv":[37.6667130487112445,32.3059919210196611,-60.8726566564636684],"rgb":[0.533333333333333326,0.2,0.6],"xyz":[0.170860481644968087,0.0990241269883677,0.311494143179134542],"hpluv":[297.955533412138379,232.161331922109071,37.6667130487112445],"hsluv":[297.955533412138379,75.4431641885032604,37.6667130487112445]},"#8833aa":{"lch":[38.7334497692602824,78.7159372772915162,290.848124870138179],"luv":[38.7334497692602824,28.0143748789862741,-73.5621749378178436],"rgb":[0.533333333333333326,0.2,0.66666666666666663],"xyz":[0.185918174610220643,0.105047204174468806,0.390797992796133142],"hpluv":[290.848124870138179,257.878905714084965,38.7334497692602824],"hsluv":[290.848124870138179,78.3166072053086282,38.7334497692602824]},"#8833bb":{"lch":[39.8990272727434743,89.1142300257769193,285.691107407551272],"luv":[39.8990272727434743,24.1010351313191435,-85.7932753698447073],"rgb":[0.533333333333333326,0.2,0.733333333333333282],"xyz":[0.20305576671755729,0.111902241017403564,0.481055977894774889],"hpluv":[285.691107407551272,283.415812953045702,39.8990272727434743],"hsluv":[285.691107407551272,80.8649153118493444,39.8990272727434743]},"#8833cc":{"lch":[41.1555326498064318,99.7027359993818578,281.897918690971494],"luv":[41.1555326498064318,20.5555775093346966,-97.560769774639283],"rgb":[0.533333333333333326,0.2,0.8],"xyz":[0.222348142161279017,0.119619191194892366,0.5826624885650451],"hpluv":[281.897918690971494,307.410130900702256,41.1555326498064318],"hsluv":[281.897918690971494,83.1006969987668356,41.1555326498064318]},"#8833dd":{"lch":[42.4948021164729042,110.266949448261684,279.053462184119098],"luv":[42.4948021164729042,17.3511661022166734,-108.893237510502843],"rgb":[0.533333333333333326,0.2,0.866666666666666696],"xyz":[0.24386646771191256,0.1282265214151459,0.695992336465051098],"hpluv":[279.053462184119098,329.267506795456711,42.4948021164729042],"hsluv":[279.053462184119098,85.0491409670088103,42.4948021164729042]},"#8833ee":{"lch":[43.9087129541284185,120.703343561802441,276.877390721452173],"luv":[43.9087129541284185,14.4536316684396038,-119.834843341123431],"rgb":[0.533333333333333326,0.2,0.933333333333333348],"xyz":[0.267678647978087325,0.137751393521615917,0.821403152533574321],"hpluv":[276.877390721452173,348.825254458779511,43.9087129541284185],"hsluv":[276.877390721452173,90.7214777394212177,43.9087129541284185]},"#8833ff":{"lch":[45.3894029264418037,130.969293653816607,275.181129330284705],"luv":[45.3894029264418037,11.8271264623124566,-130.43417864894198],"rgb":[0.533333333333333326,0.2,1],"xyz":[0.293849696387918691,0.148219812885548641,0.959237340825356166],"hpluv":[275.181129330284705,366.146040402293636,45.3894029264418037],"hsluv":[275.181129330284705,99.9999999999993179,45.3894029264418037]},"#ffbb00":{"lch":[80.0686585320779614,99.7432534700870832,55.1804439586775146],"luv":[80.0686585320779614,56.9527800089419642,81.8846595037867928],"rgb":[1,0.733333333333333282,0],"xyz":[0.590086256022839262,0.568029919385293569,0.0785626376345524291],"hpluv":[55.1804439586775146,207.400278899961506,80.0686585320779614],"hsluv":[55.1804439586775146,100.000000000004661,80.0686585320779614]},"#ffbb11":{"lch":[80.0914663159454,98.8408701901197304,54.9443852376931758],"luv":[80.0914663159454,56.7713575947746136,80.9106332739172558],"rgb":[1,0.733333333333333282,0.0666666666666666657],"xyz":[0.591097921522476422,0.568434585585148477,0.0838907425993080658],"hpluv":[54.9443852376931758,205.801067903733326,80.0914663159454],"hsluv":[54.9443852376931758,100.000000000004746,80.0914663159454]},"#ffbb22":{"lch":[80.1337172522408849,97.1832370837577173,54.4980435584705063],"luv":[80.1337172522408849,56.4372945908461148,79.11645435270664],"rgb":[1,0.733333333333333282,0.133333333333333331],"xyz":[0.592973279660953367,0.569184728840539278,0.0937676287952872584],"hpluv":[54.4980435584705063,202.856099527528187,80.1337172522408849],"hsluv":[54.4980435584705063,100.00000000000469,80.1337172522408849]},"#ffbb33":{"lch":[80.2032020182086569,94.4967793168558643,53.7374633716008248],"luv":[80.2032020182086569,55.8935303906135772,76.1941898161015558],"rgb":[1,0.733333333333333282,0.2],"xyz":[0.596061030393411184,0.570419829133522405,0.110029782652898395],"hpluv":[53.7374633716008248,198.062979410590685,80.2032020182086569],"hsluv":[53.7374633716008248,100.000000000004576,80.2032020182086569]},"#ffbb44":{"lch":[80.3033451682561,90.7120739700224874,52.5796541788809932],"luv":[80.3033451682561,55.1219083097901148,72.0434284874749835],"rgb":[1,0.733333333333333282,0.266666666666666663],"xyz":[0.60051902563763,0.57220302723121,0.133508557605785033],"hpluv":[52.5796541788809932,191.266883403483888,80.3033451682561],"hsluv":[52.5796541788809932,100.000000000004732,80.3033451682561]},"#ffbb55":{"lch":[80.4369584648287343,85.824023801574981,50.9113466162360169],"luv":[80.4369584648287343,54.1139445833304435,66.614143116349922],"rgb":[1,0.733333333333333282,0.333333333333333315],"xyz":[0.606481439676992,0.57458799284695472,0.164910604879758949],"hpluv":[50.9113466162360169,182.412290123698938,80.4369584648287343],"hsluv":[50.9113466162360169,100.000000000004846,80.4369584648287343]},"#ffbb66":{"lch":[80.6063993458739532,79.8959983704508545,48.5678239065140147],"luv":[80.6063993458739532,52.8698192869345931,59.9011916757752374],"rgb":[1,0.733333333333333282,0.4],"xyz":[0.614066435450500214,0.577621991156358,0.20485824928690291],"hpluv":[48.5678239065140147,171.553596694327723,80.6063993458739532],"hsluv":[48.5678239065140147,100.000000000004945,80.6063993458739532]},"#ffbb77":{"lch":[80.8136549908608828,73.0715029906331353,45.3006510664637219],"luv":[80.8136549908608828,51.397517928562209,51.9397699272266067],"rgb":[1,0.733333333333333282,0.466666666666666674],"xyz":[0.623380448470702064,0.58134759636443889,0.253912051193300847],"hpluv":[45.3006510664637219,158.885762577352,80.8136549908608828],"hsluv":[45.3006510664637219,100.000000000005144,80.8136549908608828]},"#ffbb88":{"lch":[81.0603921498240823,65.5982066090816,40.7273497798256443],"luv":[81.0603921498240823,49.7118280718431649,42.8002203275083914],"rgb":[1,0.733333333333333282,0.533333333333333326],"xyz":[0.634520865572646,0.585803763205216432,0.312584914596873],"hpluv":[40.7273497798256443,144.809180382553194,81.0603921498240823],"hsluv":[40.7273497798256443,100.0000000000054,81.0603921498240823]},"#ffbb99":{"lch":[81.347989327564818,57.8755898316684423,34.2609783084776538],"luv":[81.347989327564818,47.8331272298795724,32.5818329406692087],"rgb":[1,0.733333333333333282,0.6],"xyz":[0.64757782968171862,0.591026548848845645,0.381351592237990866],"hpluv":[34.2609783084776538,130.060421106466862,81.347989327564818],"hsluv":[34.2609783084776538,100.000000000005514,81.347989327564818]},"#ffbbaa":{"lch":[81.6775593509345725,50.5427251754064883,25.056975338279841],"luv":[81.6775593509345725,45.7860019440054415,21.405819165362459],"rgb":[1,0.733333333333333282,0.66666666666666663],"xyz":[0.662635522646971231,0.597049626034946712,0.460655441854989522],"hpluv":[25.056975338279841,115.96007016550756,81.6775593509345725],"hsluv":[25.056975338279841,100.000000000005954,81.6775593509345725]},"#ffbbbb":{"lch":[82.0499666293022,44.6012959670408264,12.1770506300623094],"luv":[82.0499666293022,43.5977873399533138,9.40789779917804125],"rgb":[1,0.733333333333333282,0.733333333333333282],"xyz":[0.679773114754307795,0.603904662877881471,0.550913426953631213],"hpluv":[12.1770506300623094,104.793068167285782,82.0499666293022],"hsluv":[12.1770506300623094,100.000000000006168,82.0499666293022]},"#ffbbcc":{"lch":[82.4658415859876,41.4263127316455169,355.474040938847054],"luv":[82.4658415859876,41.2971323922898534,-3.26898190783910625],"rgb":[1,0.733333333333333282,0.8],"xyz":[0.699065490198029549,0.611621613055370328,0.652519937623901369],"hpluv":[355.474040938847054,100.004408983591958,82.4658415859876],"hsluv":[355.474040938847054,100.000000000006509,82.4658415859876]},"#ffbbdd":{"lch":[82.9255937413379,42.2590852539423381,337.045135839305544],"luv":[82.9255937413379,38.9126886018087319,-16.4812909773061058],"rgb":[1,0.733333333333333282,0.866666666666666696],"xyz":[0.720583815748663148,0.620228943275623834,0.765849785523907367],"hpluv":[337.045135839305544,105.181583048825317,82.9255937413379],"hsluv":[337.045135839305544,100.000000000006992,82.9255937413379]},"#ffbbee":{"lch":[83.4294243398036315,47.2826492521794748,320.476273654572083],"luv":[83.4294243398036315,36.4719970678196077,-30.0905691237235686],"rgb":[1,0.733333333333333282,0.933333333333333348],"xyz":[0.744395996014837857,0.629753815382093851,0.89126060159243059],"hpluv":[320.476273654572083,121.793886282549721,83.4294243398036315],"hsluv":[320.476273654572083,100.000000000007375,83.4294243398036315]},"#ffbbff":{"lch":[83.9773390427358493,55.5806936350452148,307.715012949246614],"luv":[83.9773390427358493,34.0006189291922496,-43.9678452665650781],"rgb":[1,0.733333333333333282,1],"xyz":[0.770567044424669279,0.640222234746026575,1.02909478988421244],"hpluv":[307.715012949246614,148.765749509941259,83.9773390427358493],"hsluv":[307.715012949246614,100.00000000000793,83.9773390427358493]},"#aa3300":{"lch":[39.4372171279304595,100.717281062042773,18.6056676884160446],"luv":[39.4372171279304595,95.4534790945485838,32.1341568004684959],"rgb":[0.66666666666666663,0.2,0],"xyz":[0.177609683996858475,0.109151647655369471,0.0117164749512008691],"hpluv":[18.6056676884160446,324.068678498457416,39.4372171279304595],"hsluv":[18.6056676884160446,100.00000000000226,39.4372171279304595]},"#aa3311":{"lch":[39.5056415087576553,98.9056898290362199,17.5539290045831464],"luv":[39.5056415087576553,94.2999972712563,29.8302865423477179],"rgb":[0.66666666666666663,0.2,0.0666666666666666657],"xyz":[0.178621349496495607,0.109556313855224324,0.0170445799159565023],"hpluv":[17.5539290045831464,317.688492914835,39.5056415087576553],"hsluv":[17.5539290045831464,94.2489803369173558,39.5056415087576553]},"#aa3322":{"lch":[39.6320377265530155,95.7434230458582789,15.5633947922033684],"luv":[39.6320377265530155,92.2329117474569102,25.688383505468213],"rgb":[0.66666666666666663,0.2,0.133333333333333331],"xyz":[0.180496707634972609,0.110306457110615139,0.0269214661119356949],"hpluv":[15.5633947922033684,306.55039093266322,39.6320377265530155],"hsluv":[15.5633947922033684,83.9544037116345123,39.6320377265530155]},"#aa3333":{"lch":[39.8389046640011415,91.0660982539230162,12.1770506300618351],"luv":[39.8389046640011415,89.0171529654153488,19.2088711049089049],"rgb":[0.66666666666666663,0.2,0.2],"xyz":[0.18358445836743037,0.111541557403598252,0.0431836199695468381],"hpluv":[12.1770506300618351,290.060550373943784,39.8389046640011415],"hsluv":[12.1770506300618351,67.9701775681036366,39.8389046640011415]},"#aa3344":{"lch":[40.1348956250933142,85.3951569144799691,7.07959423789482756],"luv":[40.1348956250933142,84.7440953003879116,10.5247867516366789],"rgb":[0.66666666666666663,0.2,0.266666666666666663],"xyz":[0.18804245361164923,0.113324755501285832,0.0666623949224334766],"hpluv":[7.07959423789482756,269.991710008472637,40.1348956250933142],"hsluv":[7.07959423789482756,69.5294395234689659,40.1348956250933142]},"#aa3355":{"lch":[40.5259588707466,79.61783322386637,359.98582832830067],"luv":[40.5259588707466,79.6178307884273693,-0.0196928603108827253],"rgb":[0.66666666666666663,0.2,0.333333333333333315],"xyz":[0.194004867651011215,0.115709721117030664,0.098064442196407392],"hpluv":[359.98582832830067,249.296614878837403,40.5259588707466],"hsluv":[359.98582832830067,71.3920974276079079,40.5259588707466]},"#aa3366":{"lch":[41.0157539995587683,74.8661602955128558,350.806369630673316],"luv":[41.0157539995587683,73.9044320805857,-11.9614746682639641],"rgb":[0.66666666666666663,0.2,0.4],"xyz":[0.2015898634245194,0.118743719426433983,0.138012086603551354],"hpluv":[350.806369630673316,231.619002340768361,41.0157539995587683],"hsluv":[350.806369630673316,73.4562780141226597,41.0157539995587683]},"#aa3377":{"lch":[41.6059173351841167,72.2728884464882668,339.921631600955322],"luv":[41.6059173351841167,67.8804264173117531,-24.8116527825629412],"rgb":[0.66666666666666663,0.2,0.466666666666666674],"xyz":[0.210903876444721305,0.122469324634514792,0.187065888509949263],"hpluv":[339.921631600955322,220.424384448141751,41.6059173351841167],"hsluv":[339.921631600955322,75.6166865764569138,41.6059173351841167]},"#aa3388":{"lch":[42.296293156356171,72.6091331125239918,328.324027314743319],"luv":[42.296293156356171,61.7926517819245191,-38.1281313089174],"rgb":[0.66666666666666663,0.2,0.533333333333333326],"xyz":[0.222044293546665161,0.12692549147529239,0.24573875191352143],"hpluv":[328.324027314743319,217.83530631356345,42.296293156356171],"hsluv":[328.324027314743319,77.7798333688196237,42.296293156356171]},"#aa3399":{"lch":[43.0851702185186838,75.9982874692542794,317.281450106519685],"luv":[43.0851702185186838,55.835561651799118,-51.5570533805758799],"rgb":[0.66666666666666663,0.2,0.6],"xyz":[0.235101257655737861,0.132148277118921548,0.314505429554639337],"hpluv":[317.281450106519685,223.828466633931441,43.0851702185186838],"hsluv":[317.281450106519685,79.8726039522015441,43.0851702185186838]},"#aa33aa":{"lch":[43.9695321467927229,81.9717995507402861,307.715012949243828],"luv":[43.9695321467927229,50.1449646844158607,-64.8448798162617521],"rgb":[0.66666666666666663,0.2,0.66666666666666663],"xyz":[0.250158950620990417,0.138171354305022642,0.393809279171637938],"hpluv":[307.715012949243828,236.565795567314069,43.9695321467927229],"hsluv":[307.715012949243828,81.8445603498948628,43.9695321467927229]},"#aa33bb":{"lch":[44.9453163823579231,89.8045713491188593,299.92695612823394],"luv":[44.9453163823579231,44.8030997809084,-77.8302208992172],"rgb":[0.66666666666666663,0.2,0.733333333333333282],"xyz":[0.267296542728327036,0.145026391147957401,0.484067264270279685],"hpluv":[299.92695612823394,253.543994890590483,44.9453163823579231],"hsluv":[299.92695612823394,83.6659201788580305,44.9453163823579231]},"#aa33cc":{"lch":[46.0076707905516145,98.8168321279874249,293.782406660809556],"luv":[46.0076707905516145,39.8493034294229815,-90.425656359246986],"rgb":[0.66666666666666663,0.2,0.8],"xyz":[0.28658891817204879,0.152743341325446202,0.585673774940549841],"hpluv":[293.782406660809556,272.546121846523647,46.0076707905516145],"hsluv":[293.782406660809556,85.323407183561244,46.0076707905516145]},"#aa33dd":{"lch":[47.1511962508372804,108.497592079042477,288.982430572084695],"luv":[47.1511962508372804,35.2919015872993782,-102.597315604759743],"rgb":[0.66666666666666663,0.2,0.866666666666666696],"xyz":[0.308107243722682334,0.161350671545699736,0.699003622840555838],"hpluv":[288.982430572084695,291.989148013150611,47.1511962508372804],"hsluv":[288.982430572084695,86.8156421407842771,47.1511962508372804]},"#aa33ee":{"lch":[48.3701654903461247,118.505438755587946,285.224041333998457],"luv":[48.3701654903461247,31.1188262963008349,-114.346655677352729],"rgb":[0.66666666666666663,0.2,0.933333333333333348],"xyz":[0.331919423988857099,0.170875543652169781,0.824414438909079061],"hpluv":[285.224041333998457,310.885191630161273,48.3701654903461247],"hsluv":[285.224041333998457,89.3017266962351215,48.3701654903461247]},"#aa33ff":{"lch":[49.6587116356326135,128.627945638670809,282.256374557143658],"luv":[49.6587116356326135,27.305962831451918,-125.696192436653462],"rgb":[0.66666666666666663,0.2,1],"xyz":[0.358090472398688464,0.181343963016102477,0.962248627200860907],"hpluv":[282.256374557143658,328.684490794403757,49.6587116356326135],"hsluv":[282.256374557143658,99.9999999999991616,49.6587116356326135]},"#884400":{"lch":[36.685747441671559,64.5393704655657814,31.8123524502136021],"luv":[36.685747441671559,54.844205976921188,34.0212200082916922],"rgb":[0.533333333333333326,0.266666666666666663,0],"xyz":[0.122201478469054756,0.093692638490747937,0.0116493787366846978],"hpluv":[31.8123524502136021,223.237258003095718,36.685747441671559],"hsluv":[31.8123524502136021,100.000000000002245,36.685747441671559]},"#884411":{"lch":[36.7614898568215622,62.4864851085245405,30.2058215583615599],"luv":[36.7614898568215622,54.0023006087270119,31.4374354899146],"rgb":[0.533333333333333326,0.266666666666666663,0.0666666666666666657],"xyz":[0.123213143968691874,0.0940973046906027899,0.016977483701440331],"hpluv":[30.2058215583615599,215.691146343233044,36.7614898568215622],"hsluv":[30.2058215583615599,93.206231917801162,36.7614898568215622]},"#884422":{"lch":[36.9013237077522405,58.9550348899468375,27.0578850153250627],"luv":[36.9013237077522405,52.5022536375556825,26.8180816214102],"rgb":[0.533333333333333326,0.266666666666666663,0.133333333333333331],"xyz":[0.125088502107168903,0.0948474479459936,0.0268543698974195236],"hpluv":[27.0578850153250627,202.730122118290922,36.9013237077522405],"hsluv":[27.0578850153250627,81.1214838671569822,36.9013237077522405]},"#884433":{"lch":[37.1299605496210461,53.9021323280231357,21.3870333458705382],"luv":[37.1299605496210461,50.1903435049312,19.6562785990819577],"rgb":[0.533333333333333326,0.266666666666666663,0.2],"xyz":[0.128176252839626637,0.0960825482389767171,0.0431165237550306668],"hpluv":[21.3870333458705382,184.213216030002656,37.1299605496210461],"hsluv":[21.3870333458705382,62.5495295304316272,37.1299605496210461]},"#884444":{"lch":[37.4566279620983806,48.2433933618324389,12.1770506300619505],"luv":[37.4566279620983806,47.157939219998795,10.1761373608750691],"rgb":[0.533333333333333326,0.266666666666666663,0.266666666666666663],"xyz":[0.132634248083845524,0.0978657463366643,0.0665952987079173],"hpluv":[12.1770506300619505,163.436290620587812,37.4566279620983806],"hsluv":[12.1770506300619505,38.2981887065726,37.4566279620983806]},"#884455":{"lch":[37.8873893879065804,43.5926938841600631,358.470393497241901],"luv":[37.8873893879065804,43.5771602849424937,-1.16364151632571566],"rgb":[0.533333333333333326,0.266666666666666663,0.333333333333333315],"xyz":[0.138596662123207509,0.10025071195240913,0.0979973459818912207],"hpluv":[358.470393497241901,146.001848007416612,37.8873893879065804],"hsluv":[358.470393497241901,42.6300163695831245,37.8873893879065804]},"#884466":{"lch":[38.425613648805637,41.9872152878557756,340.815857604715632],"luv":[38.425613648805637,39.6555541095459816,-13.7972198610307206],"rgb":[0.533333333333333326,0.266666666666666663,0.4],"xyz":[0.146181657896715694,0.103284710261812449,0.137944990389035183],"hpluv":[340.815857604715632,138.655016432961,38.425613648805637],"hsluv":[340.815857604715632,47.3337116796912767,38.425613648805637]},"#884477":{"lch":[39.0722986805963117,44.7783217464764363,322.645837420375756],"luv":[39.0722986805963117,35.5943002873345478,-27.1688035343115608],"rgb":[0.533333333333333326,0.266666666666666663,0.466666666666666674],"xyz":[0.1554956709169176,0.107010315469893258,0.186998792295433092],"hpluv":[322.645837420375756,145.424700121889231,39.0722986805963117],"hsluv":[322.645837420375756,52.1510622716411,39.0722986805963117]},"#884488":{"lch":[39.8263740522966856,51.5911203050634839,307.71501294924451],"luv":[39.8263740522966856,31.5600599218946343,-40.8118403414738609],"rgb":[0.533333333333333326,0.266666666666666663,0.533333333333333326],"xyz":[0.166636088018861428,0.111466482310670856,0.245671655699005259],"hpluv":[307.71501294924451,164.377933698467302,39.8263740522966856],"hsluv":[307.71501294924451,56.8697587177058,39.8263740522966856]},"#884499":{"lch":[40.6850187117946192,61.0189075542410393,296.969581150574243],"luv":[40.6850187117946192,27.6731358367265301,-54.3829443123034295],"rgb":[0.533333333333333326,0.266666666666666663,0.6],"xyz":[0.179693052127934128,0.116689267954300013,0.314438333340123166],"hpluv":[296.969581150574243,190.313341437332326,40.6850187117946192],"hsluv":[296.969581150574243,61.3383523001243134,40.6850187117946192]},"#8844aa":{"lch":[41.643995358805,71.7935926347933417,289.536616505740085],"luv":[41.643995358805,24.0084388126510113,-67.6602897510042141],"rgb":[0.533333333333333326,0.266666666666666663,0.66666666666666663],"xyz":[0.194750745093186683,0.122712345140401108,0.393742182957121767],"hpluv":[289.536616505740085,218.762371943685849,41.643995358805],"hsluv":[289.536616505740085,65.4647221474276506,41.643995358805]},"#8844bb":{"lch":[42.6979882651059626,83.1164887776927515,284.352541737053286],"luv":[42.6979882651059626,20.6035404121657031,-80.5223250360828757],"rgb":[0.533333333333333326,0.266666666666666663,0.733333333333333282],"xyz":[0.21188833720052333,0.129567381983335866,0.484000168055763513],"hpluv":[284.352541737053286,247.012596783276,42.6979882651059626],"hsluv":[284.352541737053286,69.2054262339616741,42.6979882651059626]},"#8844cc":{"lch":[43.840927241858644,94.5481620176080924,280.647262826657595],"luv":[43.840927241858644,17.4689172853010533,-92.9203522904814463],"rgb":[0.533333333333333326,0.266666666666666663,0.8],"xyz":[0.231180712644245057,0.137284332160824668,0.585606678726033669],"hpluv":[280.647262826657595,273.660859280114778,43.840927241858644],"hsluv":[280.647262826657595,72.5522514276637764,43.840927241858644]},"#8844dd":{"lch":[45.0662821798681108,105.864396975636453,277.925647559652191],"luv":[45.0662821798681108,14.5974213234566292,-104.853163222292139],"rgb":[0.533333333333333326,0.266666666666666663,0.866666666666666696],"xyz":[0.2526990381948786,0.145891662381078202,0.698936526626039667],"hpluv":[277.925647559652191,298.083215805211921,45.0662821798681108],"hsluv":[277.925647559652191,79.9664783418063649,45.0662821798681108]},"#8844ee":{"lch":[46.3673172023828,116.961454232737537,275.874868362231723],"luv":[46.3673172023828,11.97173240994087,-116.347150370524886],"rgb":[0.533333333333333326,0.266666666666666663,0.933333333333333348],"xyz":[0.276511218461053365,0.155416534487548247,0.82434734269456289],"hpluv":[275.874868362231723,320.088534026972411,46.3673172023828],"hsluv":[275.874868362231723,89.9071832422553,46.3673172023828]},"#8844ff":{"lch":[47.7372988913525091,127.801124524511906,274.29427304351259],"luv":[47.7372988913525091,9.5696272486796623,-127.442338585146516],"rgb":[0.533333333333333326,0.266666666666666663,1],"xyz":[0.302682266870884731,0.165884953851480943,0.962181530986344735],"hpluv":[274.29427304351259,339.716123682654541,47.7372988913525091],"hsluv":[274.29427304351259,99.9999999999992468,47.7372988913525091]},"#ffcc00":{"lch":[84.1983464973243,98.3335943421723613,63.5926937648685069],"luv":[84.1983464973243,43.7338065737115329,88.0729807536005751],"rgb":[1,0.8,0],"xyz":[0.628309999332456237,0.644477406004528408,0.0913038854044243842],"hpluv":[63.5926937648685069,267.385577483165775,84.1983464973243],"hsluv":[63.5926937648685069,100.000000000007688,84.1983464973243]},"#ffcc11":{"lch":[84.2193135631731877,97.4576917861448777,63.4272907637844199],"luv":[84.2193135631731877,43.5960552023901897,87.1629833075564164],"rgb":[1,0.8,0.0666666666666666657],"xyz":[0.629321664832093397,0.644882072204383316,0.0966319903691800208],"hpluv":[63.4272907637844199,265.403720884510847,84.2193135631731877],"hsluv":[63.4272907637844199,100.000000000007645,84.2193135631731877]},"#ffcc22":{"lch":[84.2581577251319516,95.845309095571892,63.1144413478925301],"luv":[84.2581577251319516,43.342199386504106,85.4855369519677168],"rgb":[1,0.8,0.133333333333333331],"xyz":[0.631197022970570343,0.645632215459774117,0.106508876565159213],"hpluv":[63.1144413478925301,261.744085553517664,84.2581577251319516],"hsluv":[63.1144413478925301,100.00000000000766,84.2581577251319516]},"#ffcc33":{"lch":[84.3220485899852719,93.2224175872051148,62.5809741236821822],"luv":[84.3220485899852719,42.9284172035605494,82.7500461462124832],"rgb":[1,0.8,0.2],"xyz":[0.63428477370302816,0.646867315752757244,0.12277103042277035],"hpluv":[62.5809741236821822,255.758846695652977,84.3220485899852719],"hsluv":[62.5809741236821822,100.000000000007859,84.3220485899852719]},"#ffcc44":{"lch":[84.41414885501203,89.5051620308737,61.7678249437873745],"luv":[84.41414885501203,42.3400226901080785,78.8574442191356439],"rgb":[1,0.8,0.266666666666666663],"xyz":[0.638742768947247,0.64865051385044481,0.146249805375657],"hpluv":[61.7678249437873745,247.206609954939694,84.41414885501203],"hsluv":[61.7678249437873745,100.000000000007887,84.41414885501203]},"#ffcc55":{"lch":[84.5370662928161,84.6613331238571476,60.5932597011580469],"luv":[84.5370662928161,41.569242864558305,73.7532329730438221],"rgb":[1,0.8,0.333333333333333315],"xyz":[0.644705182986609,0.651035479466189559,0.177651852649630904],"hpluv":[60.5932597011580469,235.935294148211483,84.5370662928161],"hsluv":[60.5932597011580469,100.000000000008015,84.5370662928161]},"#ffcc66":{"lch":[84.6930007913096,78.7104448491835456,58.9357730127494222],"luv":[84.6930007913096,40.6144802919859131,67.4225342075500151],"rgb":[1,0.8,0.4],"xyz":[0.65229017876011719,0.654069477775592878,0.217599497056774865],"hpluv":[58.9357730127494222,221.881579382217893,84.6930007913096],"hsluv":[58.9357730127494222,100.000000000008285,84.6930007913096]},"#ffcc77":{"lch":[84.8838226897762809,71.7288671198513441,56.6053668146737863],"luv":[84.8838226897762809,39.4797505573258718,59.8863897244492378],"rgb":[1,0.8,0.466666666666666674],"xyz":[0.661604191780319,0.657795082983673729,0.266653298963172802],"hpluv":[56.6053668146737863,205.087229042099608,84.8838226897762809],"hsluv":[56.6053668146737863,100.000000000008399,84.8838226897762809]},"#ffcc88":{"lch":[85.1111193079521371,63.8628893840605159,53.2910582019814285],"luv":[85.1111193079521371,38.1740592359010691,51.1977523133063457],"rgb":[1,0.8,0.533333333333333326],"xyz":[0.672744608882263,0.662251249824451271,0.325326162366744942],"hpluv":[53.2910582019814285,185.743844227516831,85.1111193079521371],"hsluv":[53.2910582019814285,100.000000000008683,85.1111193079521371]},"#ffcc99":{"lch":[85.3762249003348899,55.3594884395636555,48.4608196634464292],"luv":[85.3762249003348899,36.710650975629143,41.436711563970924],"rgb":[1,0.8,0.6],"xyz":[0.685801572991335595,0.667474035468080484,0.394092840007862821],"hpluv":[48.4608196634464292,164.300705026796521,85.3762249003348899],"hsluv":[48.4608196634464292,100.000000000008811,85.3762249003348899]},"#ffccaa":{"lch":[85.6802414041430467,46.6394331206389836,41.1740083194267896],"luv":[85.6802414041430467,35.1061374539925311,30.7049806200222122],"rgb":[1,0.8,0.66666666666666663],"xyz":[0.700859265956588207,0.673497112654181551,0.473396689624861478],"hpluv":[41.1740083194267896,141.724192848301414,85.6802414041430467],"hsluv":[41.1740083194267896,100.000000000009393,85.6802414041430467]},"#ffccbb":{"lch":[86.0240539433014106,38.4677176438646384,29.8042196075727404],"luv":[86.0240539433014106,33.3795484258888635,19.1199123327444944],"rgb":[1,0.8,0.733333333333333282],"xyz":[0.71799685806392477,0.68035214949711631,0.563654674723503168],"hpluv":[29.8042196075727404,120.116808153279436,86.0240539433014106],"hsluv":[29.8042196075727404,100.000000000009621,86.0240539433014106]},"#ffcccc":{"lch":[86.4083433793485,32.2775975377643,12.1770506300627517],"luv":[86.4083433793485,31.5513664521307504,6.80841962670093892],"rgb":[1,0.8,0.8],"xyz":[0.737289233507646524,0.688069099674605167,0.665261185393773324],"hpluv":[12.1770506300627517,103.973607583717524,86.4083433793485],"hsluv":[12.1770506300627517,100.000000000010388,86.4083433793485]},"#ffccdd":{"lch":[86.8335972965778637,30.2635044437543748,348.373924949033096],"luv":[86.8335972965778637,29.6426074465171432,-6.09881340826452867],"rgb":[1,0.8,0.866666666666666696],"xyz":[0.758807559058280123,0.696676429894858673,0.778591033293779322],"hpluv":[348.373924949033096,100.994037434302086,86.8335972965778637],"hsluv":[348.373924949033096,100.000000000011042,86.8335972965778637]},"#ffccee":{"lch":[87.3001202800073344,33.8382691858854301,324.868297683069],"luv":[87.3001202800073344,27.6740002852911822,-19.4724977777928352],"rgb":[1,0.8,0.933333333333333348],"xyz":[0.782619739324454833,0.70620130200132869,0.904001849362302545],"hpluv":[324.868297683069,117.528800717138253,87.3001202800073344],"hsluv":[324.868297683069,100.000000000011482,87.3001202800073344]},"#ffccff":{"lch":[87.8080440143565255,41.9549825399590404,307.715012949248376],"luv":[87.8080440143565255,25.6653035474654807,-33.1890456889728],"rgb":[1,0.8,1],"xyz":[0.808790787734286254,0.716669721365261414,1.0418360376540845],"hpluv":[307.715012949248376,152.433043069806,87.8080440143565255],"hsluv":[307.715012949248376,100.000000000012506,87.8080440143565255]},"#aa4400":{"lch":[42.2796461632011074,91.196234940608619,23.7609213617016479],"luv":[42.2796461632011074,83.4659581293579578,36.7448921741641357],"rgb":[0.66666666666666663,0.266666666666666663,0],"xyz":[0.186442254479824487,0.126816788621301801,0.0146606651121894659],"hpluv":[23.7609213617016479,273.706361359402308,42.2796461632011074],"hsluv":[23.7609213617016479,100.000000000002331,42.2796461632011074]},"#aa4411":{"lch":[42.3415695164373815,89.5099073241138399,22.7237862619920179],"luv":[42.3415695164373815,82.5619515402106572,34.5766925405446202],"rgb":[0.66666666666666663,0.266666666666666663,0.0666666666666666657],"xyz":[0.18745391997946162,0.127221454821156654,0.0199887700769451],"hpluv":[22.7237862619920179,268.252316854423896,42.3415695164373815],"hsluv":[22.7237862619920179,95.0030043013494634,42.3415695164373815]},"#aa4422":{"lch":[42.4560124733741162,86.5487219398638,20.7501492775311753],"luv":[42.4560124733741162,80.9346773489764075,30.663647399501361],"rgb":[0.66666666666666663,0.266666666666666663,0.133333333333333331],"xyz":[0.189329278117938621,0.127971598076547483,0.0298656562729242916],"hpluv":[20.7501492775311753,258.678767688655569,42.4560124733741162],"hsluv":[20.7501492775311753,86.0172479577967692,42.4560124733741162]},"#aa4433":{"lch":[42.643470741830761,82.1252826930209494,17.3597256589108966],"luv":[42.643470741830761,78.3845002494828691,24.5037176372775498],"rgb":[0.66666666666666663,0.266666666666666663,0.2],"xyz":[0.192417028850396354,0.129206698369530582,0.0461278101305354349],"hpluv":[17.3597256589108966,244.378874013338617,42.643470741830761],"hsluv":[17.3597256589108966,71.9602068881057733,42.643470741830761]},"#aa4444":{"lch":[42.9120210749329871,76.685866981555165,12.1770506300619239],"luv":[42.9120210749329871,74.9604702767477704,16.1756017075590073],"rgb":[0.66666666666666663,0.266666666666666663,0.266666666666666663],"xyz":[0.196875024094615242,0.130989896467218175,0.0696065850834220734],"hpluv":[12.1770506300619239,226.764824908056937,42.9120210749329871],"hsluv":[12.1770506300619239,53.1380271992519795,42.9120210749329871]},"#aa4455":{"lch":[43.2674147484635299,71.0489272172787594,4.80785478807657096],"luv":[43.2674147484635299,70.7989329223205,5.9549270177674023],"rgb":[0.66666666666666663,0.266666666666666663,0.333333333333333315],"xyz":[0.202837438133977255,0.133374862082963,0.101008632357395989],"hpluv":[4.80785478807657096,208.370342069187018,43.2674147484635299],"hsluv":[4.80785478807657096,55.6796565441877931,43.2674147484635299]},"#aa4466":{"lch":[43.7134526285125489,66.3411716499448261,355.020980864279068],"luv":[43.7134526285125489,66.0908363196155477,-5.75781299290188],"rgb":[0.66666666666666663,0.266666666666666663,0.4],"xyz":[0.210422433907485412,0.136408860392366299,0.140956276764539951],"hpluv":[355.020980864279068,192.578302395247789,43.7134526285125489],"hsluv":[355.020980864279068,58.5402216503940949,43.7134526285125489]},"#aa4477":{"lch":[44.252209356870793,63.7921835342278598,343.127789968560137],"luv":[44.252209356870793,61.046215168807521,-18.5149208377531842],"rgb":[0.66666666666666663,0.266666666666666663,0.466666666666666674],"xyz":[0.219736446927687346,0.140134465600447122,0.19001007867093786],"hpluv":[343.127789968560137,182.924482874911519,44.252209356870793],"hsluv":[343.127789968560137,61.5848400189491372,44.252209356870793]},"#aa4488":{"lch":[44.8842146397509367,64.3242328637060865,330.281311898752961],"luv":[44.8842146397509367,55.8636578331810938,-31.8882214461946916],"rgb":[0.66666666666666663,0.266666666666666663,0.533333333333333326],"xyz":[0.230876864029631146,0.14459063244122472,0.248682942074510027],"hpluv":[330.281311898752961,181.852933643495049,44.8842146397509367],"hsluv":[330.281311898752961,64.6866121014520274,44.8842146397509367]},"#aa4499":{"lch":[45.6086312393750077,68.1395242873703779,318.091147538790551],"luv":[45.6086312393750077,50.7100032224043318,-45.5136281051387854],"rgb":[0.66666666666666663,0.266666666666666663,0.6],"xyz":[0.243933828138703873,0.149813418084853878,0.317449619715627906],"hpluv":[318.091147538790551,189.579504981677246,45.6086312393750077],"hsluv":[318.091147538790551,67.7395528675925,45.6086312393750077]},"#aa44aa":{"lch":[46.4234422285949293,74.7240378323112822,307.715012949244056],"luv":[46.4234422285949293,45.7112599542092468,-59.1114417296972476],"rgb":[0.66666666666666663,0.266666666666666663,0.66666666666666663],"xyz":[0.258991521103956401,0.155836495270954972,0.396753469332626507],"hpluv":[307.715012949244056,204.25011915803762,46.4234422285949293],"hsluv":[307.715012949244056,70.6643205278868862,46.4234422285949293]},"#aa44bb":{"lch":[47.3256474704596144,83.2556513741305224,299.464802712285689],"luv":[47.3256474704596144,40.9525224701243289,-72.4872015535482177],"rgb":[0.66666666666666663,0.266666666666666663,0.733333333333333282],"xyz":[0.276129113211293076,0.162691532113889731,0.487011454431268254],"hpluv":[299.464802712285689,223.2320179514779,47.3256474704596144],"hsluv":[299.464802712285689,73.4081717041738244,47.3256474704596144]},"#aa44cc":{"lch":[48.311463406953564,92.9774863668884564,293.103270963637385],"luv":[48.311463406953564,36.4834012629607827,-85.5206080625642073],"rgb":[0.66666666666666663,0.266666666666666663,0.8],"xyz":[0.29542148865501483,0.170408482291378532,0.58861796510153841],"hpluv":[293.103270963637385,244.211962975346665,48.311463406953564],"hsluv":[293.103270963637385,75.9413806031634806,48.311463406953564]},"#aa44dd":{"lch":[49.376518181476186,103.335675962773564,288.229438001673088],"luv":[49.376518181476186,32.3257723855767125,-98.1494083851717676],"rgb":[0.66666666666666663,0.266666666666666663,0.866666666666666696],"xyz":[0.316939814205648318,0.179015812511632066,0.701947813001544407],"hpluv":[288.229438001673088,265.563967984367252,49.376518181476186],"hsluv":[288.229438001673088,78.2521754793284572,49.376518181476186]},"#aa44ee":{"lch":[50.5160343838387149,113.969241853628489,284.471970959088878],"luv":[50.5160343838387149,28.4816380653286,-110.35299897060564],"rgb":[0.66666666666666663,0.266666666666666663,0.933333333333333348],"xyz":[0.340751994471823083,0.188540684618102111,0.82735862907006763],"hpluv":[284.471970959088878,286.284434407824506,50.5160343838387149],"hsluv":[284.471970959088878,88.5420288112715355,50.5160343838387149]},"#aa44ff":{"lch":[51.7249932896939271,124.658572052901789,281.540806859048416],"luv":[51.7249932896939271,24.9399169363974949,-122.138282816953421],"rgb":[0.66666666666666663,0.266666666666666663,1],"xyz":[0.366923042881654449,0.199009103982034807,0.965192817361849476],"hpluv":[281.540806859048416,305.816582895375404,51.7249932896939271],"hsluv":[281.540806859048416,99.9999999999991189,51.7249932896939271]},"#885500":{"lch":[40.7868302215615941,57.8204075903908716,44.0255445375638317],"luv":[40.7868302215615941,41.5746091122878738,40.1839695784202107],"rgb":[0.533333333333333326,0.333333333333333315,0],"xyz":[0.134014735183400707,0.117319151919440201,0.0155871309747999068],"hpluv":[44.0255445375638317,179.887306981779091,40.7868302215615941],"hsluv":[44.0255445375638317,100.000000000002402,40.7868302215615941]},"#885511":{"lch":[40.8520464566488215,55.8013246771799061,42.6953812551229817],"luv":[40.8520464566488215,41.012258348334349,37.838901951530346],"rgb":[0.533333333333333326,0.333333333333333315,0.0666666666666666657],"xyz":[0.135026400683037839,0.117723818119295054,0.0209152359395555383],"hpluv":[42.6953812551229817,173.328515822040885,40.8520464566488215],"hsluv":[42.6953812551229817,94.5141207032234121,40.8520464566488215]},"#885522":{"lch":[40.9725457623763205,52.2529579480882163,40.0436802938645613],"luv":[40.9725457623763205,40.0024704692244413,33.6180601862079769],"rgb":[0.533333333333333326,0.333333333333333315,0.133333333333333331],"xyz":[0.136901758821514841,0.118473961374685868,0.0307921221355347344],"hpluv":[40.0436802938645613,161.829338044896133,40.9725457623763205],"hsluv":[40.0436802938645613,84.6783920295854813,40.9725457623763205]},"#885533":{"lch":[41.169842808691,46.965215190705,35.0963808532685348],"luv":[41.169842808691,38.426283274472091,27.0028182162390955],"rgb":[0.533333333333333326,0.333333333333333315,0.2],"xyz":[0.139989509553972602,0.119709061667668981,0.0470542759931458776],"hpluv":[35.0963808532685348,144.75595347357384,41.169842808691],"hsluv":[35.0963808532685348,69.3663942781120113,41.169842808691]},"#885544":{"lch":[41.4523140669009891,40.5881659839312263,26.5063976077417607],"luv":[41.4523140669009891,36.321721997537459,18.1144066718387258],"rgb":[0.533333333333333326,0.333333333333333315,0.266666666666666663],"xyz":[0.144447504798191462,0.121492259765356561,0.0705330509460325161],"hpluv":[26.5063976077417607,124.248162385526584,41.4523140669009891],"hsluv":[26.5063976077417607,49.0053368988820708,41.4523140669009891]},"#885555":{"lch":[41.8258216452066449,34.5587016635497619,12.1770506300621708],"luv":[41.8258216452066449,33.7811467851905647,7.28958040957408926],"rgb":[0.533333333333333326,0.333333333333333315,0.333333333333333315],"xyz":[0.150409918837553447,0.123877225381101394,0.101935098220006432],"hpluv":[12.1770506300621708,104.846095879990827,41.8258216452066449],"hsluv":[12.1770506300621708,24.5686900376428454,41.8258216452066449]},"#885566":{"lch":[42.2941086985740071,31.3312262907584227,350.801819307985852],"luv":[42.2941086985740071,30.9283487442626033,-5.00829160852097477],"rgb":[0.533333333333333326,0.333333333333333315,0.4],"xyz":[0.157994914611061632,0.126911223690504699,0.141882742627150393],"hpluv":[350.801819307985852,94.0019456509277092,42.2941086985740071],"hsluv":[350.801819307985852,29.8132814869556348,42.2941086985740071]},"#885577":{"lch":[42.8590433503379202,33.3514130793808121,326.760730108285],"luv":[42.8590433503379202,27.8947491372056646,-18.2811302977648822],"rgb":[0.533333333333333326,0.333333333333333315,0.466666666666666674],"xyz":[0.167308927631263538,0.130636828898585522,0.190936544533548302],"hpluv":[326.760730108285,98.7440857113442263,42.8590433503379202],"hsluv":[326.760730108285,35.3342565461126838,42.8590433503379202]},"#885588":{"lch":[43.5208237898043535,40.5407907233736822,307.71501294924542],"luv":[43.5208237898043535,24.8001938501248809,-32.0703304858651137],"rgb":[0.533333333333333326,0.333333333333333315,0.533333333333333326],"xyz":[0.178449344733207393,0.13509299573936312,0.24960940793712047],"hpluv":[307.71501294924542,118.204615389413121,43.5208237898043535],"hsluv":[307.71501294924542,40.8951968507306276,43.5208237898043535]},"#885599":{"lch":[44.278184332936334,50.8805981998246,295.296495298175159],"luv":[44.278184332936334,21.7414099229374891,-46.0015909261276477],"rgb":[0.533333333333333326,0.333333333333333315,0.6],"xyz":[0.191506308842280093,0.140315781382992277,0.318376085578238377],"hpluv":[295.296495298175159,145.814841874582299,44.278184332936334],"hsluv":[295.296495298175159,46.3068912836000735,44.278184332936334]},"#8855aa":{"lch":[45.1286132569148819,62.6826496939872868,287.441560465434577],"luv":[45.1286132569148819,18.7880516159354372,-59.8006997378464717],"rgb":[0.533333333333333326,0.333333333333333315,0.66666666666666663],"xyz":[0.206564001807532649,0.146338858569093372,0.397679935195237],"hpluv":[287.441560465434577,176.252255995348207,45.1286132569148819],"hsluv":[287.441560465434577,51.4349240401982044,45.1286132569148819]},"#8855bb":{"lch":[46.0685799041538857,75.0110486022347374,282.303621490188448],"luv":[46.0685799041538857,15.9842650126874819,-73.2882029006783284],"rgb":[0.533333333333333326,0.333333333333333315,0.733333333333333282],"xyz":[0.223701593914869268,0.15319389541202813,0.487937920293878724],"hpluv":[282.303621490188448,206.613996430434867,46.0685799041538857],"hsluv":[282.303621490188448,56.1963190544194191,46.0685799041538857]},"#8855cc":{"lch":[47.0937627302438173,87.3889723072186229,278.789341148015808],"luv":[47.0937627302438173,13.3532090014702405,-86.3627482788434406],"rgb":[0.533333333333333326,0.333333333333333315,0.8],"xyz":[0.242993969358591022,0.160910845589516932,0.58954443096414888],"hpluv":[278.789341148015808,235.468364438494291,47.0937627302438173],"hsluv":[278.789341148015808,67.0071532265272083,47.0937627302438173]},"#8855dd":{"lch":[48.1992684502362323,99.579643468316263,276.285619014825784],"luv":[48.1992684502362323,10.9024601244232162,-98.9810171523426163],"rgb":[0.533333333333333326,0.333333333333333315,0.866666666666666696],"xyz":[0.264512294909224566,0.169518175809770466,0.702874278864154878],"hpluv":[276.285619014825784,262.161822059859048,48.1992684502362323],"hsluv":[276.285619014825784,77.9008511174594673,48.1992684502362323]},"#8855ee":{"lch":[49.3798334670730128,111.473561000814087,274.439637972028379],"luv":[49.3798334670730128,8.62903279282213198,-111.139077714648238],"rgb":[0.533333333333333326,0.333333333333333315,0.933333333333333348],"xyz":[0.288324475175399275,0.179043047916240511,0.828285094932678101],"hpluv":[274.439637972028379,286.45841220928196,49.3798334670730128],"hsluv":[274.439637972028379,88.8665998649397295,49.3798334670730128]},"#8855ff":{"lch":[50.6300011250937416,123.030386306339324,273.039422554437692],"luv":[50.6300011250937416,6.52344684402536235,-122.857318039912712],"rgb":[0.533333333333333326,0.333333333333333315,1],"xyz":[0.314495523585230696,0.189511467280173207,0.96611928322446],"hpluv":[273.039422554437692,308.349875308867752,50.6300011250937416],"hsluv":[273.039422554437692,99.9999999999992,50.6300011250937416]},"#ffdd00":{"lch":[88.435570144315335,99.3071523162376195,71.7429005549186911],"luv":[88.435570144315335,31.1110916577435432,94.3080615696447211],"rgb":[1,0.866666666666666696,0],"xyz":[0.670943989879631442,0.729745387098879927,0.105515215586815703],"hpluv":[71.7429005549186911,382.363935262913174,88.435570144315335],"hsluv":[71.7429005549186911,100.000000000012946,88.435570144315335]},"#ffdd11":{"lch":[88.454870819445,98.4678340856778,71.6448189166009826],"luv":[88.454870819445,31.0081800872079896,93.4580500395971683],"rgb":[1,0.866666666666666696,0.0666666666666666657],"xyz":[0.671955655379268602,0.730150053298734836,0.110843320551571339],"hpluv":[71.6448189166009826,379.826472639876158,88.454870819445],"hsluv":[71.6448189166009826,100.00000000001296,88.454870819445]},"#ffdd22":{"lch":[88.4906302718539735,96.9204819130462,71.4594307996413],"luv":[88.4906302718539735,30.8183922605744947,91.8901872494037093],"rgb":[1,0.866666666666666696,0.133333333333333331],"xyz":[0.673831013517745547,0.730900196554125636,0.120720206747550532],"hpluv":[71.4594307996413,375.129750349680876,88.4906302718539735],"hsluv":[71.4594307996413,100.00000000001296,88.4906302718539735]},"#ffdd33":{"lch":[88.5494544369894641,94.3967280931520776,71.1436744567929793],"luv":[88.5494544369894641,30.5086598694284135,89.330643945199526],"rgb":[1,0.866666666666666696,0.2],"xyz":[0.676918764250203364,0.732135296847108763,0.136982360605161668],"hpluv":[71.1436744567929793,367.416320973762822,88.5494544369894641],"hsluv":[71.1436744567929793,100.000000000013216,88.5494544369894641]},"#ffdd44":{"lch":[88.6342662809689301,90.8049878425315455,70.6631891871382152],"luv":[88.6342662809689301,30.0674100616276441,85.6825342136204284],"rgb":[1,0.866666666666666696,0.266666666666666663],"xyz":[0.681376759494422224,0.733918494944796329,0.160461135558048307],"hpluv":[70.6631891871382152,356.322085242203968,88.6342662809689301],"hsluv":[70.6631891871382152,100.000000000013173,88.6342662809689301]},"#ffdd55":{"lch":[88.7474847112806486,86.0957791731635353,69.970644696948483],"luv":[88.7474847112806486,29.4879375414461293,80.8884709398435433],"rgb":[1,0.866666666666666696,0.333333333333333315],"xyz":[0.687339173533784153,0.736303460560541079,0.191863182832022222],"hpluv":[69.970644696948483,341.559684906391112,88.7474847112806486],"hsluv":[69.970644696948483,100.000000000013429,88.7474847112806486]},"#ffdd66":{"lch":[88.8911610589964454,80.258955992054581,68.9956984045855819],"luv":[88.8911610589964454,28.7678627944319345,74.9260307715235427],"rgb":[1,0.866666666666666696,0.4],"xyz":[0.694924169307292394,0.739337458869944397,0.231810827239166184],"hpluv":[68.9956984045855819,322.902183683526573,88.8911610589964454],"hsluv":[68.9956984045855819,100.000000000013586,88.8911610589964454]},"#ffdd77":{"lch":[89.0670520916409885,73.323747836811151,67.6276760217336346],"luv":[89.0670520916409885,27.9087592291374555,67.8046691248198812],"rgb":[1,0.866666666666666696,0.466666666666666674],"xyz":[0.704238182327494244,0.743063064078025248,0.280864629145564093],"hpluv":[67.6276760217336346,300.178104609939055,89.0670520916409885],"hsluv":[67.6276760217336346,100.000000000014367,89.0670520916409885]},"#ffdd88":{"lch":[89.2766635023192379,65.3617696880632622,65.6822421460803554],"luv":[89.2766635023192379,26.9157684368328205,59.5625918359016637],"rgb":[1,0.866666666666666696,0.533333333333333326],"xyz":[0.715378599429438156,0.747519230918802791,0.339537492549136233],"hpluv":[65.6822421460803554,273.280966903928913,89.2766635023192379],"hsluv":[65.6822421460803554,100.00000000001468,89.2766635023192379]},"#ffdd99":{"lch":[89.5212778802452362,56.4966374008110606,62.8311838382076928],"luv":[89.5212778802452362,25.7971434460875209,50.2630821540094814],"rgb":[1,0.866666666666666696,0.6],"xyz":[0.7284355635385108,0.752742016562432,0.408304170190254168],"hpluv":[62.8311838382076928,242.212083001239,89.5212778802452362],"hsluv":[62.8311838382076928,100.000000000014893,89.5212778802452362]},"#ffddaa":{"lch":[89.8019739344538408,46.9317870748453103,58.439957868293348],"luv":[89.8019739344538408,24.5637119196041205,39.9902074859498],"rgb":[1,0.866666666666666696,0.66666666666666663],"xyz":[0.743493256503763411,0.75876509374853307,0.487608019807252768],"hpluv":[58.439957868293348,207.216087370130765,89.8019739344538408],"hsluv":[58.439957868293348,100.000000000015916,89.8019739344538408]},"#ffddbb":{"lch":[90.1196406145249114,37.0342016806554142,51.1553076529108282],"luv":[90.1196406145249114,23.228278171915747,28.8440494260352231],"rgb":[1,0.866666666666666696,0.733333333333333282],"xyz":[0.7606308486111,0.765620130591467829,0.57786600490589457],"hpluv":[51.1553076529108282,169.207898233907059,90.1196406145249114],"hsluv":[51.1553076529108282,100.00000000001647,90.1196406145249114]},"#ffddcc":{"lch":[90.4749882420216665,27.6093496047032829,37.8361109659034085],"luv":[90.4749882420216665,21.8049964890922183,16.9357111957368183],"rgb":[1,0.866666666666666696,0.8],"xyz":[0.779923224054821729,0.773337080768956686,0.679472515576164726],"hpluv":[37.8361109659034085,131.228146902908946,90.4749882420216665],"hsluv":[37.8361109659034085,100.000000000017565,90.4749882420216665]},"#ffdddd":{"lch":[90.8685579434819743,20.7762078419716971,12.1770506300632935],"luv":[90.8685579434819743,20.3087527298379129,4.38239373528981613],"rgb":[1,0.866666666666666696,0.866666666666666696],"xyz":[0.801441549605455328,0.781944410989210192,0.792802363476170724],"hpluv":[12.1770506300632935,103.332662997484363,90.8685579434819743],"hsluv":[12.1770506300632935,100.000000000018645,90.8685579434819743]},"#ffddee":{"lch":[91.3007301977477255,20.6730653908416642,335.121130580225611],"luv":[91.3007301977477255,18.7545890012647547,-8.69718483462634318],"rgb":[1,0.866666666666666696,0.933333333333333348],"xyz":[0.82525372987163,0.791469283095680209,0.918213179544694],"hpluv":[335.121130580225611,108.301670079840079,91.3007301977477255],"hsluv":[335.121130580225611,100.000000000019696,91.3007301977477255]},"#ffddff":{"lch":[91.7717330140538081,28.0468143452174594,307.715012949251673],"luv":[91.7717330140538081,17.1571994583452359,-22.1868046744377736],"rgb":[1,0.866666666666666696,1],"xyz":[0.851424778281461458,0.801937702459612933,1.05604736783647568],"hpluv":[307.715012949251673,155.925616416863875,91.7717330140538081],"hsluv":[307.715012949251673,100.000000000021274,91.7717330140538081]},"#aa5500":{"lch":[45.6948541105979729,81.8101604081173406,31.0178153240564285],"luv":[45.6948541105979729,70.1118895783240674,42.1571498770823254],"rgb":[0.66666666666666663,0.333333333333333315,0],"xyz":[0.198255511194170453,0.150443302049994065,0.0185984173503046732],"hpluv":[31.0178153240564285,227.184802334875343,45.6948541105979729],"hsluv":[31.0178153240564285,100.000000000002132,45.6948541105979729]},"#aa5511":{"lch":[45.7501207141343542,80.2053049231342357,30.0334267749456458],"luv":[45.7501207141343542,69.4364235827854088,40.1431690060082786],"rgb":[0.66666666666666663,0.333333333333333315,0.0666666666666666657],"xyz":[0.199267176693807585,0.150847968249848918,0.0239265223150603029],"hpluv":[30.0334267749456458,222.459100300712947,45.7501207141343542],"hsluv":[30.0334267749456458,95.7485290168496874,45.7501207141343542]},"#aa5522":{"lch":[45.8523093955831129,77.3637164970789826,28.1463245173948593],"luv":[45.8523093955831129,68.2151287979892231,36.4943945464800308],"rgb":[0.66666666666666663,0.333333333333333315,0.133333333333333331],"xyz":[0.201142534832284586,0.151598111505239747,0.0338034085110395],"hpluv":[28.1463245173948593,214.099393521154866,45.8523093955831129],"hsluv":[28.1463245173948593,88.0687786146531835,45.8523093955831129]},"#aa5533":{"lch":[46.0198296754266707,73.057054041475979,24.8605966968797674],"luv":[46.0198296754266707,66.2871018342682845,30.7140566456547255],"rgb":[0.66666666666666663,0.333333333333333315,0.2],"xyz":[0.20423028556474232,0.152833211798222846,0.0500655623686506457],"hpluv":[24.8605966968797674,201.444992058953261,46.0198296754266707],"hsluv":[24.8605966968797674,75.9647480733224683,46.0198296754266707]},"#aa5544":{"lch":[46.260105303202792,67.6400753638857,19.7251402693972757],"luv":[46.260105303202792,63.6711277752059743,22.829088529013422],"rgb":[0.66666666666666663,0.333333333333333315,0.266666666666666663],"xyz":[0.208688280808961207,0.154616409895910439,0.0735443373215372842],"hpluv":[19.7251402693972757,185.539675327038225,46.260105303202792],"hsluv":[19.7251402693972757,59.5831884891410581,46.260105303202792]},"#aa5555":{"lch":[46.5785950143652201,61.8404850960729462,12.1770506300619488],"luv":[46.5785950143652201,60.4491026496292108,13.0442165641410206],"rgb":[0.66666666666666663,0.333333333333333315,0.333333333333333315],"xyz":[0.21465069484832322,0.157001375511655272,0.1049463845955112],"hpluv":[12.1770506300619488,168.471262237657498,46.5785950143652201],"hsluv":[12.1770506300619488,39.4780386186733381,46.5785950143652201]},"#aa5566":{"lch":[46.9791292969753727,56.7719582569154682,1.70455911852653919],"luv":[46.9791292969753727,56.7468364589401801,1.68872621441415594],"rgb":[0.66666666666666663,0.333333333333333315,0.4],"xyz":[0.222235690621831378,0.160035373821058563,0.144894029002655161],"hpluv":[1.70455911852653919,153.34451205140752,46.9791292969753727],"hsluv":[1.70455911852653919,42.9013314457092818,46.9791292969753727]},"#aa5577":{"lch":[47.4641008255870247,53.815805251865207,348.374645401059922],"luv":[47.4641008255870247,52.7118371029350072,-10.8444974129891012],"rgb":[0.66666666666666663,0.333333333333333315,0.466666666666666674],"xyz":[0.231549703642033311,0.163760979029139386,0.193947830909053071],"hpluv":[348.374645401059922,143.874527939012694,47.4641008255870247],"hsluv":[348.374645401059922,46.6096363259647291,47.4641008255870247]},"#aa5588":{"lch":[48.0346061313586716,54.1759936988691209,333.519859036575326],"luv":[48.0346061313586716,48.4923339918738,-24.1564036495598238],"rgb":[0.66666666666666663,0.333333333333333315,0.533333333333333326],"xyz":[0.242690120743977111,0.168217145869916984,0.252620694312625238],"hpluv":[333.519859036575326,143.117248614217317,48.0346061313586716],"hsluv":[333.519859036575326,50.4580944804944309,48.0346061313586716]},"#aa5599":{"lch":[48.6905763376225,58.2309730669685877,319.412334073918828],"luv":[48.6905763376225,44.2212637341432782,-37.885697275903027],"rgb":[0.66666666666666663,0.333333333333333315,0.6],"xyz":[0.255747084853049866,0.173439931513546142,0.321387371953743117],"hpluv":[319.412334073918828,151.756904292295189,48.6905763376225],"hsluv":[319.412334073918828,54.3174516364451492,48.6905763376225]},"#aa55aa":{"lch":[49.4309115490906095,65.3990862514302904,307.715012949244453],"luv":[49.4309115490906095,40.0068668547544135,-51.7348150377284242],"rgb":[0.66666666666666663,0.333333333333333315,0.66666666666666663],"xyz":[0.270804777818302367,0.179463008699647236,0.400691221570741718],"hpluv":[307.715012949244453,167.885190443837445,49.4309115490906095],"hsluv":[307.715012949244453,58.0831627335764651,49.4309115490906095]},"#aa55bb":{"lch":[50.2536225490081137,74.6889496830887651,298.754319252296796],"luv":[50.2536225490081137,35.9294822147829578,-65.4790921786531896],"rgb":[0.66666666666666663,0.333333333333333315,0.733333333333333282],"xyz":[0.287942369925639041,0.186318045542582,0.490949206669383464],"hpluv":[298.754319252296796,188.594188212432869,50.2536225490081137],"hsluv":[298.754319252296796,61.6784311565058445,50.2536225490081137]},"#aa55cc":{"lch":[51.1559779262539394,85.2173265065914194,292.086991032215337],"luv":[51.1559779262539394,32.0428980728004476,-78.9635702082114],"rgb":[0.66666666666666663,0.333333333333333315,0.8],"xyz":[0.307234745369360795,0.194034995720070796,0.59255571733965362],"hpluv":[292.086991032215337,211.383381159177,51.1559779262539394],"hsluv":[292.086991032215337,65.0527897247966536,51.1559779262539394]},"#aa55dd":{"lch":[52.1346521614624407,96.3659410029227,287.126655540846059],"luv":[52.1346521614624407,28.3783197098194826,-92.0927008824589137],"rgb":[0.66666666666666663,0.333333333333333315,0.866666666666666696],"xyz":[0.328753070919994284,0.20264232594032433,0.705885565239659618],"hpluv":[287.126655540846059,234.550526854663673,52.1346521614624407],"hsluv":[287.126655540846059,75.3446722268955256,52.1346521614624407]},"#aa55ee":{"lch":[53.1858694266106227,107.745747725204239,283.388779775386126],"luv":[53.1858694266106227,24.9493252566021582,-104.817352199450397],"rgb":[0.66666666666666663,0.333333333333333315,0.933333333333333348],"xyz":[0.352565251186169049,0.212167198046794375,0.831296381308182841],"hpluv":[283.388779775386126,257.065149407391289,53.1858694266106227],"hsluv":[283.388779775386126,87.5522298773574335,53.1858694266106227]},"#aa55ff":{"lch":[54.3055382240479361,119.125691570750178,280.523377624217346],"luv":[54.3055382240479361,21.7567225446561139,-117.12205350114192],"rgb":[0.66666666666666663,0.333333333333333315,1],"xyz":[0.378736299596000414,0.222635617410727071,0.969130569599964686],"hpluv":[280.523377624217346,278.356033354379861,54.3055382240479361],"hsluv":[280.523377624217346,99.999999999999,54.3055382240479361]},"#886600":{"lch":[45.272583339231268,54.7393681124008964,58.6614018365849361],"luv":[45.272583339231268,28.4696504737342408,46.7533680417607513],"rgb":[0.533333333333333326,0.4,0],"xyz":[0.149042792889247183,0.147375267331133541,0.020596483543415256],"hpluv":[58.6614018365849361,153.427719347991228,45.272583339231268],"hsluv":[58.6614018365849361,100.000000000002288,45.272583339231268]},"#886611":{"lch":[45.3286132830504442,52.7569286908504935,57.8019218571504112],"luv":[45.3286132830504442,28.1114182485843394,44.6434954830448234],"rgb":[0.533333333333333326,0.4,0.0666666666666666657],"xyz":[0.150054458388884315,0.147779933530988394,0.0259245885081708857],"hpluv":[57.8019218571504112,147.688404254652824,45.3286132830504442],"hsluv":[57.8019218571504112,95.5933263309827765,45.3286132830504442]},"#886622":{"lch":[45.4322079122274616,49.2027541487777427,56.0700181971155658],"luv":[45.4322079122274616,27.4639619392241023,40.8245246197174367],"rgb":[0.533333333333333326,0.4,0.133333333333333331],"xyz":[0.151929816527361317,0.148530076786379223,0.0358014747041500853],"hpluv":[56.0700181971155658,137.424731357888106,45.4322079122274616],"hsluv":[56.0700181971155658,87.640709221506242,45.4322079122274616]},"#886633":{"lch":[45.6020177209920377,43.6934420281053448,52.7580970187872822],"luv":[45.6020177209920377,26.4424624059276816,34.7838045385277539],"rgb":[0.533333333333333326,0.4,0.2],"xyz":[0.155017567259819078,0.149765177079362322,0.0520636285617612285],"hpluv":[52.7580970187872822,121.582627853675135,45.6020177209920377],"hsluv":[52.7580970187872822,75.126145239043538,45.6020177209920377]},"#886644":{"lch":[45.8455444844743383,36.5157977851307862,46.6690567683987183],"luv":[45.8455444844743383,25.057552877875338,26.56167411246971],"rgb":[0.533333333333333326,0.4,0.266666666666666663],"xyz":[0.159475562504037938,0.151548375177049915,0.0755424035146478601],"hpluv":[46.6690567683987183,101.07016738030697,45.8455444844743383],"hsluv":[46.6690567683987183,58.2269221932267413,45.8455444844743383]},"#886655":{"lch":[46.1682850891648,28.5288655346450497,35.057100942904512],"luv":[46.1682850891648,23.3531590809093643,16.3867669061227161],"rgb":[0.533333333333333326,0.4,0.333333333333333315],"xyz":[0.165437976543399923,0.153933340792794748,0.106944450788621775],"hpluv":[35.057100942904512,78.4115584201214517,46.1682850891648],"hsluv":[35.057100942904512,37.5458750067509825,46.1682850891648]},"#886666":{"lch":[46.5740725388720946,21.8884171395184417,12.1770506300623786],"luv":[46.5740725388720946,21.3959378301945833,4.61699569417310141],"rgb":[0.533333333333333326,0.4,0.4],"xyz":[0.173022972316908108,0.156967339102198039,0.146892095195765737],"hpluv":[12.1770506300623786,59.6361320849851921,46.5740725388720946],"hsluv":[12.1770506300623786,13.9745942082290213,46.5740725388720946]},"#886677":{"lch":[47.0652698878111053,20.9860757761626395,336.621799391030947],"luv":[47.0652698878111053,19.2632377900225293,-8.32724722389627559],"rgb":[0.533333333333333326,0.4,0.466666666666666674],"xyz":[0.18233698533711,0.160692944310278862,0.195945897102163646],"hpluv":[336.621799391030947,56.5809206524471051,47.0652698878111053],"hsluv":[336.621799391030947,19.7183189325496855,47.0652698878111053]},"#886688":{"lch":[47.6429159175320649,27.8420771343032278,307.715012949247239],"luv":[47.6429159175320649,17.0319546757823481,-22.0248445868429776],"rgb":[0.533333333333333326,0.4,0.533333333333333326],"xyz":[0.193477402439053869,0.16514911115105646,0.254618760505735842],"hpluv":[307.715012949247239,74.1553731862279335,47.6429159175320649],"hsluv":[307.715012949247239,25.6555006249089494,47.6429159175320649]},"#886699":{"lch":[48.306860672000596,39.0046617113806562,292.251886736336132],"luv":[48.306860672000596,14.770249996667463,-36.0999078981538304],"rgb":[0.533333333333333326,0.4,0.6],"xyz":[0.206534366548126569,0.170371896794685618,0.323385438146853721],"hpluv":[292.251886736336132,102.458272059709785,48.306860672000596],"hsluv":[292.251886736336132,31.5854767603208231,48.306860672000596]},"#8866aa":{"lch":[49.0559053000777112,51.7871044207240132,284.005102499462396],"luv":[49.0559053000777112,12.5329093477081912,-50.2476901714407305],"rgb":[0.533333333333333326,0.4,0.66666666666666663],"xyz":[0.221592059513379125,0.176394973980786712,0.402689287763852322],"hpluv":[284.005102499462396,133.958310232957899,49.0559053000777112],"hsluv":[284.005102499462396,39.6059098285329867,49.0559053000777112]},"#8866bb":{"lch":[49.8879495217490074,65.0723394771694501,279.16089377463328],"luv":[49.8879495217490074,10.3599978518109275,-64.242352148271],"rgb":[0.533333333333333326,0.4,0.733333333333333282],"xyz":[0.238729651620715744,0.183250010823721471,0.492947272862494068],"hpluv":[279.16089377463328,165.516042277675325,49.8879495217490074],"hsluv":[279.16089377463328,51.4342030459355897,49.8879495217490074]},"#8866cc":{"lch":[50.800144438276476,78.3702679805165161,276.063171305995638],"luv":[50.800144438276476,8.2778522611756955,-77.9318680982312912],"rgb":[0.533333333333333326,0.4,0.8],"xyz":[0.258022027064437498,0.190966961001210273,0.594553783532764224],"hpluv":[276.063171305995638,195.760791019658512,50.800144438276476],"hsluv":[276.063171305995638,63.370404435102877,50.800144438276476]},"#8866dd":{"lch":[51.7890458420015278,91.4433004674113903,273.951375062119212],"luv":[51.7890458420015278,6.3013441888180548,-91.225929766636682],"rgb":[0.533333333333333326,0.4,0.866666666666666696],"xyz":[0.279540352615071042,0.199574291221463807,0.707883631432770222],"hpluv":[273.951375062119212,224.054313572832513,51.7890458420015278],"hsluv":[273.951375062119212,75.4110532620532,51.7890458420015278]},"#8866ee":{"lch":[52.8507624936088831,104.176067138923727,272.440799986921],"luv":[52.8507624936088831,4.4365578942807,-104.081554170680207],"rgb":[0.533333333333333326,0.4,0.933333333333333348],"xyz":[0.303352532881245751,0.209099163327933851,0.833294447501293445],"hpluv":[272.440799986921,250.124381092910085,52.8507624936088831],"hsluv":[272.440799986921,87.5962217171162365,52.8507624936088831]},"#8866ff":{"lch":[53.9810943197935273,116.520298408763196,271.319576027424205],"luv":[53.9810943197935273,2.6833355157121912,-116.48939716462327],"rgb":[0.533333333333333326,0.4,1],"xyz":[0.329523581291077172,0.219567582691866547,0.97112863579307529],"hpluv":[271.319576027424205,273.904539658900717,53.9810943197935273],"hsluv":[271.319576027424205,99.9999999999990621,53.9810943197935273]},"#ffee00":{"lch":[92.75564548426334,102.358730475882979,79.2433869538170228],"luv":[92.75564548426334,19.1039702538988,100.560171167180329],"rgb":[1,0.933333333333333348,0],"xyz":[0.718122766220146147,0.824102939779910892,0.121241474366986887],"hpluv":[79.2433869538170228,651.393632104361359,92.75564548426334],"hsluv":[79.2433869538170228,100.000000000024428,92.75564548426334]},"#ffee11":{"lch":[92.7734436379168,101.564402459740549,79.2015044483446218],"luv":[92.7734436379168,19.0286516433192254,99.765917344759373],"rgb":[1,0.933333333333333348,0.0666666666666666657],"xyz":[0.719134431719783307,0.824507605979765801,0.12656957933174251],"hpluv":[79.2015044483446218,648.021125158270593,92.7734436379168],"hsluv":[79.2015044483446218,100.000000000024428,92.7734436379168]},"#ffee22":{"lch":[92.8064212727168183,100.098587827824673,79.1224559985664797],"luv":[92.8064212727168183,18.8896613956421291,98.3000914418838079],"rgb":[1,0.933333333333333348,0.133333333333333331],"xyz":[0.721009789858260253,0.825257749235156601,0.136446465527721716],"hpluv":[79.1224559985664797,641.762708667564539,92.8064212727168183],"hsluv":[79.1224559985664797,100.000000000024357,92.8064212727168183]},"#ffee33":{"lch":[92.8606749716073665,97.7038183815635506,78.9881622996309147],"luv":[92.8606749716073665,18.6625824309063972,95.9048702796014396],"rgb":[1,0.933333333333333348,0.2],"xyz":[0.72409754059071807,0.826492849528139728,0.152708619385332867],"hpluv":[78.9881622996309147,631.438241912838748,92.8606749716073665],"hsluv":[78.9881622996309147,100.000000000024599,92.8606749716073665]},"#ffee44":{"lch":[92.9389094487226828,94.2867391890675606,78.7846200921967181],"luv":[92.9389094487226828,18.3385503337116411,92.4861436030564192],"rgb":[1,0.933333333333333348,0.266666666666666663],"xyz":[0.728555535834936929,0.828276047625827294,0.176187394338219505],"hpluv":[78.7846200921967181,616.484076987319668,92.9389094487226828],"hsluv":[78.7846200921967181,100.000000000025381,92.9389094487226828]},"#ffee55":{"lch":[93.0433700241155179,89.7896797607108,78.4929149488566082],"luv":[93.0433700241155179,17.9120631143144244,87.984911129805738],"rgb":[1,0.933333333333333348,0.333333333333333315],"xyz":[0.734517949874298859,0.830661013241572,0.207589441612193393],"hpluv":[78.4929149488566082,596.384103057951847,93.0433700241155179],"hsluv":[78.4929149488566082,100.000000000025906,93.0433700241155179]},"#ffee66":{"lch":[93.1759694096933,84.1867368500463,78.0854442567743661],"luv":[93.1759694096933,17.3805845725397461,82.3730656305550895],"rgb":[1,0.933333333333333348,0.4],"xyz":[0.7421029456478071,0.833695011550975362,0.247537086019337382],"hpluv":[78.0854442567743661,570.62648367707834,93.1759694096933],"hsluv":[78.0854442567743661,100.000000000026517,93.1759694096933]},"#ffee77":{"lch":[93.3383558005883742,77.4816602435733586,77.5195453952684659],"luv":[93.3383558005883742,16.7442947506152713,75.6507519288807515],"rgb":[1,0.933333333333333348,0.466666666666666674],"xyz":[0.751416958668009,0.837420616759056213,0.296590887925735291],"hpluv":[77.5195453952684659,538.663675570032183,93.3383558005883742],"hsluv":[77.5195453952684659,100.00000000002693,93.3383558005883742]},"#ffee88":{"lch":[93.5319535615141433,69.7063855050026433,76.7254067288761235],"luv":[93.5319535615141433,16.0058531534094222,67.8438858336072599],"rgb":[1,0.933333333333333348,0.533333333333333326],"xyz":[0.762557375769952861,0.841876783599833756,0.355263751329307431],"hpluv":[76.7254067288761235,499.867858345774721,93.5319535615141433],"hsluv":[76.7254067288761235,100.000000000028109,93.5319535615141433]},"#ffee99":{"lch":[93.7579894103796647,60.9203426164438397,75.5807218945013517],"luv":[93.7579894103796647,15.1701259512809905,59.0013171304435744],"rgb":[1,0.933333333333333348,0.6],"xyz":[0.775614339879025505,0.847099569243463,0.424030428970425366],"hpluv":[75.5807218945013517,453.479030486808085,93.7579894103796647],"hsluv":[75.5807218945013517,100.000000000029459,93.7579894103796647]},"#ffeeaa":{"lch":[94.0175103342715204,51.2122166590618946,73.8511258956299],"luv":[94.0175103342715204,14.2438643230739057,49.191497886124175],"rgb":[1,0.933333333333333348,0.66666666666666663],"xyz":[0.790672032844278116,0.853122646429564,0.503334278587424],"hpluv":[73.8511258956299,398.552269307706354,94.0175103342715204],"hsluv":[73.8511258956299,100.00000000003169,94.0175103342715204]},"#ffeebb":{"lch":[94.3113965930375855,40.7102572776027571,71.0277189369888],"luv":[94.3113965930375855,13.2353397134719373,38.4987120599845625],"rgb":[1,0.933333333333333348,0.733333333333333282],"xyz":[0.80780962495161468,0.859977683272498794,0.593592263686065658],"hpluv":[71.0277189369888,333.94796839081863,94.3113965930375855],"hsluv":[71.0277189369888,100.000000000032855,94.3113965930375855]},"#ffeecc":{"lch":[94.6403717602024841,29.6267857036886042,65.7803861656043125],"luv":[94.6403717602024841,12.1539519061426287,27.0190281874729799],"rgb":[1,0.933333333333333348,0.8],"xyz":[0.827102000395336434,0.867694633449987651,0.695198774356335814],"hpluv":[65.7803861656043125,258.601677072085806,94.6403717602024841],"hsluv":[65.7803861656043125,100.000000000035726,94.6403717602024841]},"#ffeedd":{"lch":[95.0050109981125814,18.4911495042727,53.4580761074439366],"luv":[95.0050109981125814,11.0098304435300403,14.8561853648264481],"rgb":[1,0.933333333333333348,0.866666666666666696],"xyz":[0.84862032594597,0.876301963670241157,0.808528622256341811],"hpluv":[53.4580761074439366,173.670551799097524,95.0050109981125814],"hsluv":[53.4580761074439366,100.000000000039279,95.0050109981125814]},"#ffeeee":{"lch":[95.4057483293867,10.0393308083340358,12.1770506300655121],"luv":[95.4057483293867,9.81345048674430487,2.11762900985580904],"rgb":[1,0.933333333333333348,0.933333333333333348],"xyz":[0.872432506212144743,0.885826835776711174,0.933939438324865],"hpluv":[12.1770506300655121,102.829227108855335,95.4057483293867],"hsluv":[12.1770506300655121,100.000000000042746,95.4057483293867]},"#ffeeff":{"lch":[95.8428833991312104,14.017983351086059,307.715012949261848],"luv":[95.8428833991312104,8.57528179129596,-11.0891117512266888],"rgb":[1,0.933333333333333348,1],"xyz":[0.898603554621976164,0.896295255140643898,1.07177362661664688],"hpluv":[307.715012949261848,159.207478793902965,95.8428833991312104],"hsluv":[307.715012949261848,100.000000000047876,95.8428833991312104]},"#aa6600":{"lch":[49.5566255632669623,74.0434564420528574,40.5370999312324685],"luv":[49.5566255632669623,56.2719368465296,48.1238253407432595],"rgb":[0.66666666666666663,0.4,0],"xyz":[0.213283568900016929,0.180499417461687406,0.0236077699189200241],"hpluv":[40.5370999312324685,189.593866720893345,49.5566255632669623],"hsluv":[40.5370999312324685,100.000000000002302,49.5566255632669623]},"#aa6611":{"lch":[49.6055800152373934,72.4782904829715449,39.6736286483530876],"luv":[49.6055800152373934,55.7860674256664097,46.2711278500211662],"rgb":[0.66666666666666663,0.4,0.0666666666666666657],"xyz":[0.214295234399654061,0.180904083661542259,0.0289358748836756538],"hpluv":[39.6736286483530876,185.402990863318706,49.6055800152373934],"hsluv":[39.6736286483530876,96.4267217319678878,49.6055800152373934]},"#aa6622":{"lch":[49.6961357673044404,69.6784302133091,38.0044715349972151],"luv":[49.6961357673044404,54.9040042209680124,42.902610147809348],"rgb":[0.66666666666666663,0.4,0.133333333333333331],"xyz":[0.216170592538131062,0.181654226916933087,0.0388127610796548533],"hpluv":[38.0044715349972151,177.916023719914563,49.6961357673044404],"hsluv":[38.0044715349972151,89.9454244119252593,49.6961357673044404]},"#aa6633":{"lch":[49.8446929303716502,65.3554895773238798,35.0519229290669685],"luv":[49.8446929303716502,53.5020897896209959,37.5348692023167061],"rgb":[0.66666666666666663,0.4,0.2],"xyz":[0.219258343270588796,0.182889327209916186,0.055074914937266],"hpluv":[35.0519229290669685,166.380518722129068,49.8446929303716502],"hsluv":[35.0519229290669685,79.6601301034586,49.8446929303716502]},"#aa6644":{"lch":[50.0579996788189163,59.7471791719702878,30.3078082111971625],"luv":[50.0579996788189163,51.5813401714318687,30.1511320703974341],"rgb":[0.66666666666666663,0.4,0.266666666666666663],"xyz":[0.223716338514807683,0.18467252530760378,0.0785536898901526282],"hpluv":[30.3078082111971625,151.454869534606559,50.0579996788189163],"hsluv":[30.3078082111971625,65.6016329960131,50.0579996788189163]},"#aa6655":{"lch":[50.3411543587309183,53.4384070136854916,23.0123473649378063],"luv":[50.3411543587309183,49.1858121787411307,20.8906492114991877],"rgb":[0.66666666666666663,0.4,0.333333333333333315],"xyz":[0.229678752554169696,0.187057490923348613,0.109955737164126544],"hpluv":[23.0123473649378063,134.70064023894011,50.3411543587309183],"hsluv":[23.0123473649378063,48.1262851503794238,50.3411543587309183]},"#aa6666":{"lch":[50.6979081899742283,47.4599132867605107,12.1770506300620198],"luv":[50.6979081899742283,46.3920870859415544,10.0108753362152232],"rgb":[0.66666666666666663,0.4,0.4],"xyz":[0.237263748327677854,0.190091489232751903,0.149903381571270505],"hpluv":[12.1770506300620198,118.788999996072334,50.6979081899742283],"hsluv":[12.1770506300620198,27.8359446414257086,50.6979081899742283]},"#aa6677":{"lch":[51.1308297914663399,43.3502150416948382,357.146673366158041],"luv":[51.1308297914663399,43.29647113668576,-2.15794607701909591],"rgb":[0.66666666666666663,0.4,0.466666666666666674],"xyz":[0.246577761347879787,0.193817094440832727,0.198957183477668414],"hpluv":[357.146673366158041,107.584013476394517,51.1308297914663399],"hsluv":[357.146673366158041,31.9217683762365354,51.1308297914663399]},"#aa6688":{"lch":[51.6414184020027,42.8134625942885876,339.120025752150127],"luv":[51.6414184020027,40.0018640870324234,-15.2592086582212207],"rgb":[0.66666666666666663,0.4,0.533333333333333326],"xyz":[0.257718178449823587,0.198273261281610325,0.257630046881240582],"hpluv":[339.120025752150127,105.201399585535427,51.6414184020027],"hsluv":[339.120025752150127,36.2396804223311,51.6414184020027]},"#aa6699":{"lch":[52.2302006219705675,46.6703467022409342,321.661853982703349],"luv":[52.2302006219705675,36.6065194780657563,-28.949680361091449],"rgb":[0.66666666666666663,0.4,0.6],"xyz":[0.270775142558896342,0.203496046925239482,0.326396724522358461],"hpluv":[321.661853982703349,113.385797667979,52.2302006219705675],"hsluv":[321.661853982703349,40.6514838109423,52.2302006219705675]},"#aa66aa":{"lch":[52.8968256208086274,54.2656136904176165,307.715012949245079],"luv":[52.8968256208086274,33.1961393674155048,-42.9275338250028753],"rgb":[0.66666666666666663,0.4,0.66666666666666663],"xyz":[0.285832835524148843,0.209519124111340577,0.405700574139357117],"hpluv":[307.715012949245079,130.177052782763241,52.8968256208086274],"hsluv":[307.715012949245079,45.0372955528084091,52.8968256208086274]},"#aa66bb":{"lch":[53.6401644756464293,64.2916348467718848,297.653919381785329],"luv":[53.6401644756464293,29.8396642728746109,-56.9474209016772193],"rgb":[0.66666666666666663,0.4,0.733333333333333282],"xyz":[0.302970427631485517,0.216374160954275335,0.495958559237998808],"hpluv":[297.653919381785329,152.091062924306783,53.6401644756464293],"hsluv":[297.653919381785329,49.3013965401631964,53.6401644756464293]},"#aa66cc":{"lch":[54.4584144535918853,75.6506824974921699,290.576693925999962],"luv":[54.4584144535918853,26.5882539678026326,-70.824363839571447],"rgb":[0.66666666666666663,0.4,0.8],"xyz":[0.322262803075207271,0.224091111131764137,0.597565069908269],"hpluv":[290.576693925999962,176.273563499159138,54.4584144535918853],"hsluv":[290.576693925999962,59.8478295858589107,54.4584144535918853]},"#aa66dd":{"lch":[55.3492064676394619,87.6329338161637423,285.539109011475546],"luv":[55.3492064676394619,23.4765185392287,-84.4297587732275],"rgb":[0.66666666666666663,0.4,0.866666666666666696],"xyz":[0.343781128625840759,0.232698441352017671,0.710894917808275],"hpluv":[285.539109011475546,200.907097340780666,55.3492064676394619],"hsluv":[285.539109011475546,72.9499123576365,55.3492064676394619]},"#aa66ee":{"lch":[56.3097127205812171,99.8160041995885337,281.866291349003632],"luv":[56.3097127205812171,20.525011879724925,-97.6829492885499775],"rgb":[0.66666666666666663,0.4,0.933333333333333348],"xyz":[0.367593308892015525,0.242223313458487716,0.836305733876798185],"hpluv":[281.866291349003632,224.934563930918017,56.3097127205812171],"hsluv":[281.866291349003632,86.3166325899195215,56.3097127205812171]},"#aa66ff":{"lch":[57.3367512293125543,111.956114799504135,279.118878442970129],"luv":[57.3367512293125543,17.7431860168323468,-110.541173283857603],"rgb":[0.66666666666666663,0.4,1],"xyz":[0.39376435730184689,0.252691732822420412,0.97413992216858],"hpluv":[279.118878442970129,247.773048158040382,57.3367512293125543],"hsluv":[279.118878442970129,99.9999999999988631,57.3367512293125543]},"#887700":{"lch":[50.0114915023736586,55.8665567864094825,73.357205010908],"luv":[50.0114915023736586,16.0004093344436384,53.5262465366231766],"rgb":[0.533333333333333326,0.466666666666666674,0],"xyz":[0.167496530942664812,0.184282743437969299,0.0267477295612209565],"hpluv":[73.357205010908,141.749463920516746,50.0114915023736586],"hsluv":[73.357205010908,100.000000000002359,50.0114915023736586]},"#887711":{"lch":[50.0597743565714524,53.993823922257576,73.0031869817398302],"luv":[50.0597743565714524,15.783394234863108,51.6354286142242103],"rgb":[0.533333333333333326,0.466666666666666674,0.0666666666666666657],"xyz":[0.168508196442301944,0.184687409637824151,0.0320758345259765862],"hpluv":[73.0031869817398302,136.865669051735267,50.0597743565714524],"hsluv":[73.0031869817398302,96.4507191106164328,50.0597743565714524]},"#887722":{"lch":[50.1490916772086592,50.5946145563497751,72.2920831328592755],"luv":[50.1490916772086592,15.3890953737340599,48.1974145124374616],"rgb":[0.533333333333333326,0.466666666666666674,0.133333333333333331],"xyz":[0.170383554580778945,0.18543755289321498,0.0419527207219557857],"hpluv":[72.2920831328592755,128.020802989304741,50.1490916772086592],"hsluv":[72.2920831328592755,90.012010730737714,50.1490916772086592]},"#887733":{"lch":[50.2956280558193356,45.1970113165044083,70.9372107781068735],"luv":[50.2956280558193356,14.7615306672340392,42.718462569532349],"rgb":[0.533333333333333326,0.466666666666666674,0.2],"xyz":[0.173471305313236679,0.186672653186198079,0.058214874579566929],"hpluv":[70.9372107781068735,114.029917097227894,50.2956280558193356],"hsluv":[70.9372107781068735,79.7918184760720237,50.2956280558193356]},"#887744":{"lch":[50.5060566549544916,37.8272673959478567,68.4411772520018076],"luv":[50.5060566549544916,13.89986571870684,35.1809023711225777],"rgb":[0.533333333333333326,0.466666666666666674,0.266666666666666663],"xyz":[0.177929300557455566,0.188455851283885673,0.0816936495324535605],"hpluv":[68.4411772520018076,95.0387759917387598,50.5060566549544916],"hsluv":[68.4411772520018076,65.8173762074568316,50.5060566549544916]},"#887755":{"lch":[50.7854328179731453,28.7445471843262688,63.5083223958924279],"luv":[50.7854328179731453,12.8220173934607509,25.7263456945161408],"rgb":[0.533333333333333326,0.466666666666666674,0.333333333333333315],"xyz":[0.183891714596817579,0.190840816899630505,0.113095696806427476],"hpluv":[63.5083223958924279,71.82169329487634,50.7854328179731453],"hsluv":[63.5083223958924279,48.4385690265679756,50.7854328179731453]},"#887766":{"lch":[51.1374932189691549,18.6360854649452037,51.6613245975388082],"luv":[51.1374932189691549,11.5601245482137447,14.6173596072111405],"rgb":[0.533333333333333326,0.466666666666666674,0.4],"xyz":[0.191476710370325737,0.193874815209033796,0.153043341213571438],"hpluv":[51.6613245975388082,46.2439140208651,51.1374932189691549],"hsluv":[51.6613245975388082,28.2492665088726049,51.1374932189691549]},"#887777":{"lch":[51.5648179079599629,10.388802862097231,12.1770506300635812],"luv":[51.5648179079599629,10.1550595801770775,2.19134429758843829],"rgb":[0.533333333333333326,0.466666666666666674,0.466666666666666674],"xyz":[0.20079072339052767,0.197600420417114619,0.202097143119969347],"hpluv":[12.1770506300635812,25.5653264810281158,51.5648179079599629],"hsluv":[12.1770506300635812,5.9907484084339373,51.5648179079599629]},"#887788":{"lch":[52.0689409540354262,14.1414171783799034,307.715012949252923],"luv":[52.0689409540354262,8.65079050214889378,-11.1867557182995974],"rgb":[0.533333333333333326,0.466666666666666674,0.533333333333333326],"xyz":[0.21193114049247147,0.202056587257892217,0.260770006523541542],"hpluv":[307.715012949252923,34.4630346227371902,52.0689409540354262],"hsluv":[307.715012949252923,11.9231603633022036,52.0689409540354262]},"#887799":{"lch":[52.6504441343355154,26.1446518461971777,285.73365348909897],"luv":[52.6504441343355154,7.08953673880610147,-25.1650807467009763],"rgb":[0.533333333333333326,0.466666666666666674,0.6],"xyz":[0.224988104601544198,0.207279372901521375,0.329536684164659421],"hpluv":[285.73365348909897,63.0115482025775862,52.6504441343355154],"hsluv":[285.73365348909897,20.7849368541844512,52.6504441343355154]},"#8877aa":{"lch":[53.3090485775123142,39.8165287152511951,277.951975125090712],"luv":[53.3090485775123142,5.50833871717125412,-39.4336678931764482],"rgb":[0.533333333333333326,0.466666666666666674,0.66666666666666663],"xyz":[0.240045797566796726,0.213302450087622469,0.408840533781658],"hpluv":[277.951975125090712,94.7767450693341118,53.3090485775123142],"hsluv":[277.951975125090712,33.2193336653547036,53.3090485775123142]},"#8877bb":{"lch":[54.043710164283695,53.8841311835491,274.190220195010625],"luv":[54.043710164283695,3.93720379281895738,-53.7400969453883732],"rgb":[0.533333333333333326,0.466666666666666674,0.733333333333333282],"xyz":[0.2571833896741334,0.220157486930557228,0.499098518880299769],"hpluv":[274.190220195010625,126.518797380186697,54.043710164283695],"hsluv":[274.190220195010625,46.027457746288988,54.043710164283695]},"#8877cc":{"lch":[54.8527197178713095,67.9360625264533695,272.023364737824068],"luv":[54.8527197178713095,2.39862107173988059,-67.8937052203839215],"rgb":[0.533333333333333326,0.466666666666666674,0.8],"xyz":[0.276475765117855099,0.22787443710804603,0.600705029550569924],"hpluv":[272.023364737824068,157.159823716941304,54.8527197178713095],"hsluv":[272.023364737824068,59.1220253911564413,54.8527197178713095]},"#8877dd":{"lch":[55.7338064566187228,81.7667290312133,270.636302714775695],"luv":[55.7338064566187228,0.90804807322034331,-81.7616867803042595],"rgb":[0.533333333333333326,0.466666666666666674,0.866666666666666696],"xyz":[0.297994090668488698,0.236481767328299564,0.714034877450575922],"hpluv":[270.636302714775695,186.164661983392193,55.7338064566187228],"hsluv":[270.636302714775695,72.4679508704990809,55.7338064566187228]},"#8877ee":{"lch":[56.6842419440431939,95.2620356561917419,269.684203716511661],"luv":[56.6842419440431939,-0.525051666249150784,-95.2605886928551229],"rgb":[0.533333333333333326,0.466666666666666674,0.933333333333333348],"xyz":[0.321806270934663408,0.246006639434769608,0.839445693519099145],"hpluv":[269.684203716511661,213.253830698535069,56.6842419440431939],"hsluv":[269.684203716511661,86.076772525698,56.6842419440431939]},"#8877ff":{"lch":[57.7009414002340577,108.362660778640901,268.997474997449615],"luv":[57.7009414002340577,-1.89596396936046907,-108.346073171359961],"rgb":[0.533333333333333326,0.466666666666666674,1],"xyz":[0.347977319344494829,0.256475058798702304,0.977279881810881],"hpluv":[268.997474997449615,238.306609639193027,57.7009414002340577],"hsluv":[268.997474997449615,99.9999999999988631,57.7009414002340577]},"#ffff00":{"lch":[97.1385593417967357,107.085608846920664,85.8743202181747307],"luv":[97.1385593417967357,7.70421917727499928,106.808111250898],"rgb":[1,1,0],"xyz":[0.76997513864982,0.92780768463926,0.138525598510210984],"hpluv":[85.8743202181747307,1784.23591835690763,97.1385593417967357],"hsluv":[85.8743202181747307,100.000000000072717,97.1385593417967357]},"#ffff11":{"lch":[97.1550055288865337,106.340968495662651,85.8743202181747307],"luv":[97.1550055288865337,7.65064640931757278,106.065400532478591],"rgb":[1,1,0.0666666666666666657],"xyz":[0.770986804149457194,0.928212350839114908,0.143853703474966621],"hpluv":[85.8743202181747307,1782.29032599077573,97.1550055288865337],"hsluv":[85.8743202181747307,100.000000000072447,97.1550055288865337]},"#ffff22":{"lch":[97.1854797367251564,104.966044999604463,85.8743202181747],"luv":[97.1854797367251564,7.5517282439387623,104.694039961158666],"rgb":[1,1,0.133333333333333331],"xyz":[0.77286216228793414,0.928962494094505709,0.1537305896709458],"hpluv":[85.8743202181747,1778.69938503976459,97.1854797367251564],"hsluv":[85.8743202181747,100.00000000007401,97.1854797367251564]},"#ffff33":{"lch":[97.2356193677236291,102.717517786777336,85.8743202181746312],"luv":[97.2356193677236291,7.38995910744871409,102.451339496695468],"rgb":[1,1,0.2],"xyz":[0.775949913020392,0.930197594387488835,0.16999274352855695],"hpluv":[85.8743202181746312,1772.83090468185333,97.2356193677236291],"hsluv":[85.8743202181746312,100.000000000075445,97.2356193677236291]},"#ffff44":{"lch":[97.3079311184623776,99.5042093292491,85.874320218174546],"luv":[97.3079311184623776,7.15877927938833114,99.2463578851537704],"rgb":[1,1,0.266666666666666663],"xyz":[0.780407908264610817,0.931980792485176401,0.193471518481443588],"hpluv":[85.874320218174546,1764.45330998562531,97.3079311184623776],"hsluv":[85.874320218174546,100.000000000077918,97.3079311184623776]},"#ffff55":{"lch":[97.4045015397841212,95.2663481722239283,85.8743202181744323],"luv":[97.4045015397841212,6.8538885331141568,95.0194785612246875],"rgb":[1,1,0.333333333333333315],"xyz":[0.786370322303972746,0.934365758100921151,0.224873565755417504],"hpluv":[85.8743202181744323,1753.42077174454698,97.4045015397841212],"hsluv":[85.8743202181744323,100.000000000080163,97.4045015397841212]},"#ffff66":{"lch":[97.5271149532436539,89.9715947326486258,85.8743202181742333],"luv":[97.5271149532436539,6.47296021391862286,89.7384457454272706],"rgb":[1,1,0.4],"xyz":[0.793955318077481,0.93739975641032447,0.264821210162561438],"hpluv":[85.8743202181742333,1739.66322518688298,97.5271149532436539],"hsluv":[85.8743202181742333,100.000000000084981,97.5271149532436539]},"#ffff77":{"lch":[97.6773170086398608,83.6127156419164663,85.8743202181740202],"luv":[97.6773170086398608,6.01547392080898469,83.3960448134325389],"rgb":[1,1,0.466666666666666674],"xyz":[0.803269331097682837,0.941125361618405321,0.313875012068959403],"hpluv":[85.8743202181740202,1723.18045161093028,97.6773170086398608],"hsluv":[85.8743202181740202,100.00000000009112,97.6773170086398608]},"#ffff88":{"lch":[97.8564527859654589,76.2055692953657342,85.8743202181736791],"luv":[97.8564527859654589,5.48257057790026181,76.0080930657330214],"rgb":[1,1,0.533333333333333326],"xyz":[0.814409748199626748,0.945581528459182863,0.372547875472531542],"hpluv":[85.8743202181736791,1704.03672017478311,97.8564527859654589],"hsluv":[85.8743202181736791,100.000000000099803,97.8564527859654589]},"#ffff99":{"lch":[98.0656913545514612,67.7868897983338741,85.8743202181732102],"luv":[98.0656913545514612,4.87689300155069283,67.6112294162950889],"rgb":[1,1,0.6],"xyz":[0.827466712308699393,0.950804314102812076,0.441314553113649422],"hpluv":[85.8743202181732102,1682.35465810463256,98.0656913545514612],"hsluv":[85.8743202181732102,100.000000000112891,98.0656913545514612]},"#ffffaa":{"lch":[98.3060425431328611,58.4116937234916094,85.8743202181725707],"luv":[98.3060425431328611,4.20239933084915052,58.260327869924204],"rgb":[1,1,0.66666666666666663],"xyz":[0.842524405273952,0.956827391288913143,0.520618402730648078],"hpluv":[85.8743202181725707,1658.30791632356272,98.3060425431328611],"hsluv":[85.8743202181725707,100.000000000127613,98.3060425431328611]},"#ffffbb":{"lch":[98.5783690162300559,48.1503065934375414,85.8743202181715759],"luv":[98.5783690162300559,3.46414909943131732,48.0255317103199246],"rgb":[1,1,0.733333333333333282],"xyz":[0.859661997381288567,0.963682428131847901,0.610876387829289769],"hpluv":[85.8743202181715759,1632.1126639545671,98.5783690162300559],"hsluv":[85.8743202181715759,100.000000000152809,98.5783690162300559]},"#ffffcc":{"lch":[98.8833954570195317,37.0851031688938804,85.8743202181698706],"luv":[98.8833954570195317,2.66806871718659799,36.9890022353654899],"rgb":[1,1,0.8],"xyz":[0.878954372825010322,0.971399378309336758,0.712482898499559925],"hpluv":[85.8743202181698706,1604.018210645404,98.8833954570195317],"hsluv":[85.8743202181698706,100.00000000019709,98.8833954570195317]},"#ffffdd":{"lch":[99.2217159651800245,25.3071072074552177,85.8743202181663889],"luv":[99.2217159651800245,1.82070684164607655,25.2415273271332552],"rgb":[1,1,0.866666666666666696],"xyz":[0.900472698375643921,0.980006708529590265,0.825812746399565922],"hpluv":[85.8743202181663889,1574.29719653830034,99.2217159651800245],"hsluv":[85.8743202181663889,100.000000000286278,99.2217159651800245]},"#ffffee":{"lch":[99.5938003805277248,12.9126149352850259,85.8743202181558161],"luv":[99.5938003805277248,0.928991455386458775,12.8791536733888243],"rgb":[1,1,0.933333333333333348],"xyz":[0.92428487864181863,0.989531580636060282,0.951223562468089145],"hpluv":[85.8743202181558161,1543.23583838085528,99.5938003805277248],"hsluv":[85.8743202181558161,100.000000000556355,99.5938003805277248]},"#ffffff":{"lch":[99.99999999999973,5.29610712429325706e-12,0],"luv":[99.99999999999973,4.97935026544381416e-12,1.80411241501587473e-12],"rgb":[1,1,1],"xyz":[0.95045592705165,0.999999999999993,1.0890577507598711],"hpluv":[0,0,100],"hsluv":[0,0,100]},"#aa7700":{"lch":[53.7507838912622304,69.116848270999057,51.9676330333141223],"luv":[53.7507838912622304,42.5833417137676875,54.4407726194696622],"rgb":[0.66666666666666663,0.466666666666666674,0],"xyz":[0.231737306953434558,0.217406893568523163,0.0297590159367257245],"hpluv":[51.9676330333141223,163.169299961930307,53.7507838912622304],"hsluv":[51.9676330333141223,100.000000000002359,53.7507838912622304]},"#aa7711":{"lch":[53.7940335015026,67.5786316453491906,51.3090056740019378],"luv":[53.7940335015026,42.244752971039,52.7470596476588653],"rgb":[0.66666666666666663,0.466666666666666674,0.0666666666666666657],"xyz":[0.23274897245307169,0.217811559768378016,0.0350871209014813543],"hpluv":[51.3090056740019378,159.40965108533166,53.7940335015026],"hsluv":[51.3090056740019378,97.0120153186068,53.7940335015026]},"#aa7722":{"lch":[53.874065271669366,64.7981771198060272,50.0272013346139],"luv":[53.874065271669366,41.6278947732915157,49.6580520640260588],"rgb":[0.66666666666666663,0.466666666666666674,0.133333333333333331],"xyz":[0.234624330591548691,0.218561703023768844,0.0449640070974605538],"hpluv":[50.0272013346139,152.623836787181489,53.874065271669366],"hsluv":[50.0272013346139,91.5730337049880632,53.874065271669366]},"#aa7733":{"lch":[54.0054384284815,60.4215101577181812,47.7291529037971785],"luv":[54.0054384284815,40.6416884431496115,44.7103125713654705],"rgb":[0.66666666666666663,0.466666666666666674,0.2],"xyz":[0.237712081324006452,0.219796803316751943,0.0612261609550717],"hpluv":[47.7291529037971785,141.968961696257139,54.0054384284815],"hsluv":[47.7291529037971785,82.890357503842381,54.0054384284815]},"#aa7744":{"lch":[54.1942453736720324,54.5501661616690754,43.9413891432679051],"luv":[54.1942453736720324,39.2788485799816911,37.8535689532252277],"rgb":[0.66666666666666663,0.466666666666666674,0.266666666666666663],"xyz":[0.242170076568225312,0.221580001414439537,0.0847049359079583286],"hpluv":[43.9413891432679051,127.726858599491337,54.1942453736720324],"hsluv":[43.9413891432679051,70.9191698542686453,54.1942453736720324]},"#aa7755":{"lch":[54.4451912879813307,47.55778496198932,37.8352816528713],"luv":[54.4451912879813307,37.5600659479400178,29.1716361638701045],"rgb":[0.66666666666666663,0.466666666666666674,0.333333333333333315],"xyz":[0.248132490607587297,0.22396496703018437,0.116106983181932244],"hpluv":[37.8352816528713,110.841250641501858,54.4451912879813307],"hsluv":[37.8352816528713,55.8697139193963039,54.4451912879813307]},"#aa7766":{"lch":[54.7618668139504621,40.2221891209492881,27.9562221290694595],"luv":[54.7618668139504621,35.5285027246357359,18.8560333004309904],"rgb":[0.66666666666666663,0.466666666666666674,0.4],"xyz":[0.255717486381095482,0.226998965339587661,0.156054627589076206],"hpluv":[27.9562221290694595,93.2023334238246264,54.7618668139504621],"hsluv":[27.9562221290694595,38.157009054435612,54.7618668139504621]},"#aa7777":{"lch":[55.1468928183874851,34.0080558607991321,12.1770506300622881],"luv":[55.1468928183874851,33.2428902595124569,7.17343088244713467],"rgb":[0.66666666666666663,0.466666666666666674,0.466666666666666674],"xyz":[0.265031499401297388,0.230724570547668484,0.205108429495474115],"hpluv":[12.1770506300622881,78.2528356679829074,55.1468928183874851],"hsluv":[12.1770506300622881,20.6006796366476941,55.1468928183874851]},"#aa7788":{"lch":[55.6020140468043849,31.2700131437067519,349.739442339375785],"luv":[55.6020140468043849,30.7699397165362107,-5.56996695217490778],"rgb":[0.66666666666666663,0.466666666666666674,0.533333333333333326],"xyz":[0.276171916503241244,0.235180737388446082,0.263781292899046282],"hpluv":[349.739442339375785,71.363619208349732,55.6020140468043849],"hsluv":[349.739442339375785,23.0952607722130772,55.6020140468043849]},"#aa7799":{"lch":[56.1281730235999845,34.0192547961324365,325.92167501088062],"luv":[56.1281730235999845,28.1772086346441704,-19.0618627223027133],"rgb":[0.66666666666666663,0.466666666666666674,0.6],"xyz":[0.289228880612313943,0.240403523032075239,0.332547970540164162],"hpluv":[325.92167501088062,76.9100717288581706,56.1281730235999845],"hsluv":[325.92167501088062,27.5449434619861648,56.1281730235999845]},"#aa77aa":{"lch":[56.7255784680210127,41.7295245342496131,307.715012949246272],"luv":[56.7255784680210127,25.5273831431779215,-33.0106941416859],"rgb":[0.66666666666666663,0.466666666666666674,0.66666666666666663],"xyz":[0.304286573577566499,0.246426600218176334,0.411851820157162818],"hpluv":[307.715012949246272,93.3477446513022642,56.7255784680210127],"hsluv":[307.715012949246272,32.2954766233998285,56.7255784680210127]},"#aa77bb":{"lch":[57.3937746480490176,52.417961949749369,295.873528074876958],"luv":[57.3937746480490176,22.8744713506946127,-47.1635589771554891],"rgb":[0.66666666666666663,0.466666666666666674,0.733333333333333282],"xyz":[0.321424165684903118,0.25328163706111112,0.502109805255804509],"hpluv":[295.873528074876958,115.892323381948941,57.3937746480490176],"hsluv":[295.873528074876958,41.7229864085831679,57.3937746480490176]},"#aa77cc":{"lch":[58.1317139736185,64.5762938068646548,288.286403622885132],"luv":[58.1317139736185,20.2619194712353625,-61.3151885031081],"rgb":[0.66666666666666663,0.466666666666666674,0.8],"xyz":[0.340716541128624872,0.260998587238599922,0.603716315926074665],"hpluv":[288.286403622885132,140.961111207958226,58.1317139736185],"hsluv":[288.286403622885132,55.678510160825347,58.1317139736185]},"#aa77dd":{"lch":[58.9378328182195759,77.3666791836153,283.242275299631103],"luv":[58.9378328182195759,17.7223199365118553,-75.3095108466943088],"rgb":[0.66666666666666663,0.466666666666666674,0.866666666666666696],"xyz":[0.362234866679258416,0.269605917458853428,0.717046163826080662],"hpluv":[283.242275299631103,166.570895286205939,58.9378328182195759],"hsluv":[283.242275299631103,70.0408478070886105,58.9378328182195759]},"#aa77ee":{"lch":[59.8101292792768646,90.3373867943789151,279.736895248195651],"luv":[59.8101292792768646,15.2782276108220607,-89.0360556960445138],"rgb":[0.66666666666666663,0.466666666666666674,0.933333333333333348],"xyz":[0.386047046945433125,0.279130789565323445,0.842456979894603886],"hpluv":[279.736895248195651,191.660275847677298,59.8101292792768646],"hsluv":[279.736895248195651,84.8029379630096685,59.8101292792768646]},"#aa77ff":{"lch":[60.7462409754246551,103.238062985892157,277.202485092995744],"luv":[60.7462409754246551,12.9436026905507742,-102.423438716283115],"rgb":[0.66666666666666663,0.466666666666666674,1],"xyz":[0.412218095355264547,0.289599208929256169,0.980291168186385731],"hpluv":[277.202485092995744,215.655115976047284,60.7462409754246551],"hsluv":[277.202485092995744,99.999999999998721,60.7462409754246551]},"#888800":{"lch":[54.9099926918455452,60.532810441385358,85.8743202181747449],"luv":[54.9099926918455452,4.35500198466006783,60.375948006191166],"rgb":[0.533333333333333326,0.533333333333333326,0],"xyz":[0.189568900667635265,0.228427482887910871,0.0341051861362109063],"hpluv":[85.8743202181747449,139.887458074797593,54.9099926918455452],"hsluv":[85.8743202181747449,100.000000000002331,54.9099926918455452]},"#888811":{"lch":[54.9518410557904673,58.8347385736240369,85.8743202181746739],"luv":[54.9518410557904673,4.23283507550337568,58.6822764576347353],"rgb":[0.533333333333333326,0.533333333333333326,0.0666666666666666657],"xyz":[0.190580566167272397,0.228832149087765724,0.039433291100966536],"hpluv":[85.8743202181746739,135.85978011465275,54.9518410557904673],"hsluv":[85.8743202181746739,97.1207726442580395,54.9518410557904673]},"#888822":{"lch":[55.0292864560463215,55.7361292450240882,85.8743202181745602],"luv":[55.0292864560463215,4.00990721741558787,55.5916967480373643],"rgb":[0.533333333333333326,0.533333333333333326,0.133333333333333331],"xyz":[0.192455924305749398,0.229582292343156552,0.0493101772969457355],"hpluv":[85.8743202181745602,128.523412903997382,55.0292864560463215],"hsluv":[85.8743202181745602,91.8762944675706,55.0292864560463215]},"#888833":{"lch":[55.1564325013520573,50.7686053645684225,85.8743202181742902],"luv":[55.1564325013520573,3.65252126093227947,50.6370455210582335],"rgb":[0.533333333333333326,0.533333333333333326,0.2],"xyz":[0.195543675038207132,0.230817392636139651,0.0655723311545568788],"hpluv":[85.8743202181742902,116.798802852822334,55.1564325013520573],"hsluv":[85.8743202181742902,83.4948353914423,55.1564325013520573]},"#888844":{"lch":[55.3392041906722767,43.8756115710196184,85.8743202181737786],"luv":[55.3392041906722767,3.15660835961073616,43.7619139708837039],"rgb":[0.533333333333333326,0.533333333333333326,0.266666666666666663],"xyz":[0.20000167028242602,0.232600590733827245,0.0890511061074435173],"hpluv":[85.8743202181737786,100.607324583255647,55.3392041906722767],"hsluv":[85.8743202181737786,71.9201892491773833,55.3392041906722767]},"#888855":{"lch":[55.5822005995452173,35.1333862553221152,85.8743202181729],"luv":[55.5822005995452173,2.5276534453655044,35.0423429271758167],"rgb":[0.533333333333333326,0.533333333333333326,0.333333333333333315],"xyz":[0.205964084321788032,0.234985556349572078,0.120453153381417433],"hpluv":[85.8743202181729,80.2090919262666233,55.5822005995452173],"hsluv":[85.8743202181729,57.3383011101545321,55.5822005995452173]},"#888866":{"lch":[55.8889601924437187,24.7258905438507242,85.874320218171],"luv":[55.8889601924437187,1.778891507033598,24.6618168064052092],"rgb":[0.533333333333333326,0.533333333333333326,0.4],"xyz":[0.21354908009529619,0.238019554658975369,0.160400797788561394],"hpluv":[85.874320218171,56.1390732800859524,55.8889601924437187],"hsluv":[85.874320218171,40.1315986813270698,55.8889601924437187]},"#888877":{"lch":[56.2621011123828509,12.9137749110131566,85.8743202181651668],"luv":[56.2621011123828509,0.929074909242871283,12.8803106431998842],"rgb":[0.533333333333333326,0.533333333333333326,0.466666666666666674],"xyz":[0.222863093115498123,0.241745159867056192,0.209454599694959304],"hpluv":[85.8743202181651668,29.1257147579972724,56.2621011123828509],"hsluv":[85.8743202181651668,20.8208192205656601,56.2621011123828509]},"#888888":{"lch":[56.703410756754252,2.95076376078202623e-12,0],"luv":[56.703410756754252,2.78254170310414444e-12,9.82073542272051e-13],"rgb":[0.533333333333333326,0.533333333333333326,0.533333333333333326],"xyz":[0.234003510217441923,0.24620132670783379,0.268127463098531471],"hpluv":[0,6.60335407213460764e-12,56.703410756754252],"hsluv":[0,2.14018342731852893e-12,56.703410756754252]},"#888899":{"lch":[57.2139150634865246,13.7029898302256612,265.874320218188814],"luv":[57.2139150634865246,-0.985854571612734376,-13.6674804207248872],"rgb":[0.533333333333333326,0.533333333333333326,0.6],"xyz":[0.247060474326514651,0.251424112351462947,0.33689414073964935],"hpluv":[265.874320218188814,30.3915601408835876,57.2139150634865246],"hsluv":[265.874320218188814,12.5386286039598396,57.2139150634865246]},"#8888aa":{"lch":[57.7939415002624486,27.9001972781706051,265.874320218182902],"luv":[57.7939415002624486,-2.00726537612613365,-27.8278977623291475],"rgb":[0.533333333333333326,0.533333333333333326,0.66666666666666663],"xyz":[0.262118167291767179,0.25744718953756407,0.416197990356647951],"hpluv":[265.874320218182902,61.2582077856443377,57.7939415002624486],"hsluv":[265.874320218182902,25.8334660761224093,57.7939415002624486]},"#8888bb":{"lch":[58.4431822360017605,42.3326731508362428,265.874320218181083],"luv":[58.4431822360017605,-3.04560244672749647,-42.2229738629578222],"rgb":[0.533333333333333326,0.533333333333333326,0.733333333333333282],"xyz":[0.279255759399103853,0.264302226380498828,0.506455975455289753],"hpluv":[265.874320218181083,91.9138937804104756,58.4431822360017605],"hsluv":[265.874320218181083,39.7348050695490116,58.4431822360017605]},"#8888cc":{"lch":[59.1607600358786812,56.7874726838639603,265.874320218180117],"luv":[59.1607600358786812,-4.0855455816182138,-56.6403157752595448],"rgb":[0.533333333333333326,0.533333333333333326,0.8],"xyz":[0.298548134842825608,0.27201917655798763,0.608062486125559909],"hpluv":[265.874320218180117,121.803038601679276,59.1607600358786812],"hsluv":[265.874320218180117,54.1372084350884322,59.1607600358786812]},"#8888dd":{"lch":[59.9452971965242654,71.1002375720468649,265.874320218179605],"luv":[59.9452971965242654,-5.11527010687093497,-70.9159911059223447],"rgb":[0.533333333333333326,0.533333333333333326,0.866666666666666696],"xyz":[0.320066460393459096,0.280626506778241136,0.721392334025565907],"hpluv":[265.874320218179605,150.506501481916018,59.9452971965242654],"hsluv":[265.874320218179605,68.9826297466640881,59.9452971965242654]},"#8888ee":{"lch":[60.7949865781877747,85.1524606014505,265.874320218179207],"luv":[60.7949865781877747,-6.12625008179143,-84.9317997361231676],"rgb":[0.533333333333333326,0.533333333333333326,0.933333333333333348],"xyz":[0.343878640659633861,0.290151378884711153,0.84680315009408913],"hpluv":[265.874320218179207,177.733282428962553,60.7949865781877747],"hsluv":[265.874320218179207,84.2595641984559194,60.7949865781877747]},"#8888ff":{"lch":[61.7076631467729726,98.8655769196339,265.874320218179],"luv":[61.7076631467729726,-7.11283319838656247,-98.6093804034077408],"rgb":[0.533333333333333326,0.533333333333333326,1],"xyz":[0.370049689069465226,0.300619798248643877,0.984637338385871],"hpluv":[265.874320218179,203.303722842755434,61.7076631467729726],"hsluv":[265.874320218179,99.9999999999986073,61.7076631467729726]},"#aa8800":{"lch":[58.1840377660698493,67.6904417424552634,64.2288134226940173],"luv":[58.1840377660698493,29.4303340948507071,60.9577832467208225],"rgb":[0.66666666666666663,0.533333333333333326,0],"xyz":[0.253809676678405038,0.261551633018464735,0.0371164725117156744],"hpluv":[64.2288134226940173,147.625988392398114,58.1840377660698493],"hsluv":[64.2288134226940173,100.000000000002373,58.1840377660698493]},"#aa8811":{"lch":[58.2222766199063955,66.2027965316335809,63.8264905250604926],"luv":[58.2222766199063955,29.2014551434886229,59.4145208354969085],"rgb":[0.66666666666666663,0.533333333333333326,0.0666666666666666657],"xyz":[0.254821342178042143,0.261956299218319588,0.0424445774764713041],"hpluv":[63.8264905250604926,144.286759049554206,58.2222766199063955],"hsluv":[63.8264905250604926,97.5015111084285877,58.2222766199063955]},"#aa8822":{"lch":[58.2930572278629,63.4916551128893474,63.0419050459203],"luv":[58.2930572278629,28.7832252220538578,56.5925455761676304],"rgb":[0.66666666666666663,0.533333333333333326,0.133333333333333331],"xyz":[0.2566967003165192,0.262706442473710389,0.0523214636724505036],"hpluv":[63.0419050459203,138.209896631886636,58.2930572278629],"hsluv":[63.0419050459203,92.9399945222758106,58.2930572278629]},"#aa8833":{"lch":[58.4093035212624585,59.1585039849960737,61.628621374019076],"luv":[58.4093035212624585,28.1112178941065629,52.0527426967384628],"rgb":[0.66666666666666663,0.533333333333333326,0.2],"xyz":[0.259784451048976905,0.263941542766693515,0.0685836175300616468],"hpluv":[61.628621374019076,128.521114132395894,58.4093035212624585],"hsluv":[61.628621374019076,85.621599137751673,58.4093035212624585]},"#aa8844":{"lch":[58.5764981609594315,53.1878639814319953,59.2736460930020499],"luv":[58.5764981609594315,27.1757201885359478,45.7212106919940453],"rgb":[0.66666666666666663,0.533333333333333326,0.266666666666666663],"xyz":[0.264242446293195821,0.265724740864381082,0.0920623924829482854],"hpluv":[59.2736460930020499,115.22015920662389,58.5764981609594315],"hsluv":[59.2736460930020499,75.4571473133808581,58.5764981609594315]},"#aa8855":{"lch":[58.7989500318507083,45.736161182952344,55.3795129841665315],"luv":[58.7989500318507083,25.9844527075537677,37.6378088793954433],"rgb":[0.66666666666666663,0.533333333333333326,0.333333333333333315],"xyz":[0.270204860332557806,0.268109706480125942,0.123464439756922201],"hpluv":[55.3795129841665315,98.7027982667044483,58.7989500318507083],"hsluv":[55.3795129841665315,62.5553187882680319,58.7989500318507083]},"#aa8866":{"lch":[59.0800404303715112,37.1980666756204,48.681601920545944],"luv":[59.0800404303715112,24.5597583059268025,27.9376884576795419],"rgb":[0.66666666666666663,0.533333333333333326,0.4],"xyz":[0.277789856106066,0.271143704789529261,0.163412084164066163],"hpluv":[48.681601920545944,79.8948730878687883,59.0800404303715112],"hsluv":[48.681601920545944,47.1909371341698645,59.0800404303715112]},"#aa8877":{"lch":[59.4223523155875881,28.4467220316745042,36.2691810942760355],"luv":[59.4223523155875881,22.9350730451589406,16.8285001934390941],"rgb":[0.66666666666666663,0.533333333333333326,0.466666666666666674],"xyz":[0.287103869126267897,0.274869309997610056,0.212465886070464072],"hpluv":[36.2691810942760355,60.7465636644032,59.4223523155875881],"hsluv":[36.2691810942760355,29.7643761063162415,59.4223523155875881]},"#aa8888":{"lch":[59.8277504540149323,21.6376696880998622,12.1770506300627677],"luv":[59.8277504540149323,21.1508320810015036,4.56410471095846049],"rgb":[0.66666666666666663,0.533333333333333326,0.533333333333333326],"xyz":[0.298244286228211697,0.279325476838387654,0.271138749474036211],"hpluv":[12.1770506300627677,45.8930730764781174,59.8277504540149323],"hsluv":[12.1770506300627677,15.9793094134510145,59.8277504540149323]},"#aa8899":{"lch":[60.2974403890441693,21.076671863141442,335.972081494736813],"luv":[60.2974403890441693,19.2503183610400761,-8.58203587880762697],"rgb":[0.66666666666666663,0.533333333333333326,0.6],"xyz":[0.311301250337284396,0.284548262482016812,0.339905427115154146],"hpluv":[335.972081494736813,44.3549898137704872,60.2974403890441693],"hsluv":[335.972081494736813,18.3674189175529285,60.2974403890441693]},"#aa88aa":{"lch":[60.8320193568852119,28.2409959286201691,307.715012949248376],"luv":[60.8320193568852119,17.2759870010776844,-22.3404145928166677],"rgb":[0.66666666666666663,0.533333333333333326,0.66666666666666663],"xyz":[0.326358943302536952,0.290571339668117934,0.419209276732152747],"hpluv":[307.715012949248376,58.9097393716334068,60.8320193568852119],"hsluv":[307.715012949248376,20.7885743891348937,60.8320193568852119]},"#aa88bb":{"lch":[61.4315255818646904,39.5305448534603343,292.718173175904553],"luv":[61.4315255818646904,15.2666424694527869,-36.4635928581008],"rgb":[0.66666666666666663,0.533333333333333326,0.733333333333333282],"xyz":[0.343496535409873627,0.297426376511052692,0.509467261830794493],"hpluv":[292.718173175904553,81.6546320542196185,61.4315255818646904],"hsluv":[292.718173175904553,35.3775178816614826,61.4315255818646904]},"#aa88cc":{"lch":[62.0954889075932783,52.4408733717370339,284.64164926901276],"luv":[62.0954889075932783,13.2556230251873277,-50.737891739849438],"rgb":[0.66666666666666663,0.533333333333333326,0.8],"xyz":[0.362788910853595326,0.305143326688541494,0.611073772501064649],"hpluv":[284.64164926901276,107.164068097081099,62.0954889075932783],"hsluv":[284.64164926901276,50.6369924233865092,62.0954889075932783]},"#aa88dd":{"lch":[62.8229837406334894,65.9589053782665644,279.83800714750987],"luv":[62.8229837406334894,11.2699451472508105,-64.988964717689413],"rgb":[0.66666666666666663,0.533333333333333326,0.866666666666666696],"xyz":[0.384307236404228925,0.313750656908795,0.724403620401070647],"hpluv":[279.83800714750987,133.227600809414753,62.8229837406334894],"hsluv":[279.83800714750987,66.50088929558828,62.8229837406334894]},"#aa88ee":{"lch":[63.6126841134072,79.6308922643202237,276.728713669089302],"luv":[63.6126841134072,9.33022805769535,-79.0823990986816767],"rgb":[0.66666666666666663,0.533333333333333326,0.933333333333333348],"xyz":[0.408119416670403634,0.323275529015265,0.84981443646959387],"hpluv":[276.728713669089302,158.846330872338797,63.6126841134072],"hsluv":[276.728713669089302,82.9476730407324112,63.6126841134072]},"#aa88ff":{"lch":[64.4629200033750323,93.219110130063271,274.584640952303687],"luv":[64.4629200033750323,7.4511637136690565,-92.9208407880221756],"rgb":[0.66666666666666663,0.533333333333333326,1],"xyz":[0.434290465080235055,0.333743948379197741,0.987648624761375715],"hpluv":[274.584640952303687,183.499254977583263,64.4629200033750323],"hsluv":[274.584640952303687,99.999999999998451,64.4629200033750323]},"#889900":{"lch":[59.9037942457991477,67.5360782410098892,95.4734085527772578],"luv":[59.9037942457991477,-6.44184579214223074,67.2281524881211396],"rgb":[0.533333333333333326,0.6,0],"xyz":[0.215438501120102766,0.280166683792846538,0.0427283862870331613],"hpluv":[95.4734085527772578,143.060860652479761,59.9037942457991477],"hsluv":[95.4734085527772578,100.000000000002359,59.9037942457991477]},"#889911":{"lch":[59.9403212197486,66.0293008977046867,95.6505578181906628],"luv":[59.9403212197486,-6.50131434341495318,65.7084582747741166],"rgb":[0.533333333333333326,0.6,0.0666666666666666657],"xyz":[0.216450166619739898,0.280571349992701391,0.048056491251788791],"hpluv":[95.6505578181906628,139.783837686775883,59.9403212197486],"hsluv":[95.6505578181906628,97.642419329775592,59.9403212197486]},"#889922":{"lch":[60.0079397017320275,63.2737960078627495,95.9966659299995655],"luv":[60.0079397017320275,-6.6102508868722456,62.9275602932231308],"rgb":[0.533333333333333326,0.6,0.133333333333333331],"xyz":[0.218325524758216899,0.281321493248092191,0.0579333774477679905],"hpluv":[95.9966659299995655,133.799503075015934,60.0079397017320275],"hsluv":[95.9966659299995655,93.3344688530494864,60.0079397017320275]},"#889933":{"lch":[60.1190111745068521,58.8410136656902196,96.6225595920901696],"luv":[60.1190111745068521,-6.78603238946032139,58.4483930798370039],"rgb":[0.533333333333333326,0.6,0.2],"xyz":[0.221413275490674633,0.282556593541075318,0.0741955313053791338],"hpluv":[96.6225595920901696,124.196009967059197,60.1190111745068521],"hsluv":[96.6225595920901696,86.4129060235578,60.1190111745068521]},"#889944":{"lch":[60.2788030378330859,52.6619605596060651,97.6740140778758104],"luv":[60.2788030378330859,-7.03230554676784081,52.1903129773946],"rgb":[0.533333333333333326,0.6,0.266666666666666663],"xyz":[0.22587127073489352,0.284339791638762884,0.0976743062582657723],"hpluv":[97.6740140778758104,110.859197411007315,60.2788030378330859],"hsluv":[97.6740140778758104,76.7791514013919,60.2788030378330859]},"#889955":{"lch":[60.491478208304315,44.7890969420590679,99.4433583384469557],"luv":[60.491478208304315,-7.34865909500015935,44.1821277711999301],"rgb":[0.533333333333333326,0.6,0.333333333333333315],"xyz":[0.231833684774255533,0.286724757254507745,0.129076353532239674],"hpluv":[99.4433583384469557,93.954467458231008,60.491478208304315],"hsluv":[99.4433583384469557,64.5165507795669555,60.491478208304315]},"#889966":{"lch":[60.7603321241253269,35.3998784596055387,102.614945913325585],"luv":[60.7603321241253269,-7.73125582812020351,34.5453191948634597],"rgb":[0.533333333333333326,0.6,0.4],"xyz":[0.23941868054776369,0.289758755563911063,0.169023997939383636],"hpluv":[102.614945913325585,73.9300429237522394,60.7603321241253269],"hsluv":[102.614945913325585,49.862982431557576,60.7603321241253269]},"#889977":{"lch":[61.0879169406466644,24.8557994274465628,109.198389045907604],"luv":[61.0879169406466644,-8.17358342252196,23.4734594640953418],"rgb":[0.533333333333333326,0.6,0.466666666666666674],"xyz":[0.248732693567965624,0.293484360771991859,0.218077799845781545],"hpluv":[109.198389045907604,51.6311437806165543,61.0879169406466644],"hsluv":[109.198389045907604,33.1759220302134779,61.0879169406466644]},"#889988":{"lch":[61.4761176658877702,14.1684419896747276,127.715012949229816],"luv":[61.4761176658877702,-8.66732250724137,11.2081340539023326],"rgb":[0.533333333333333326,0.6,0.533333333333333326],"xyz":[0.259873110669909424,0.297940527612769457,0.276750663249353712],"hpluv":[127.715012949229816,29.2452265306994263,61.4761176658877702],"hsluv":[127.715012949229816,14.8910328511789984,61.4761176658877702]},"#889999":{"lch":[61.9262069462763094,9.41507553536713537,192.177050630058915],"luv":[61.9262069462763094,-9.20324067004397861,-1.98595279549067061],"rgb":[0.533333333333333326,0.6,0.6],"xyz":[0.272930074778982124,0.303163313256398614,0.345517340890471647],"hpluv":[192.177050630058915,19.2925065058214678,61.9262069462763094],"hsluv":[192.177050630058915,19.2169899754877207,61.9262069462763094]},"#8899aa":{"lch":[62.4388911462841207,18.6148502867865133,238.334617604481764],"luv":[62.4388911462841207,-9.77200531832159669,-15.8436284751369474],"rgb":[0.533333333333333326,0.6,0.66666666666666663],"xyz":[0.28798776774423468,0.309186390442499737,0.424821190507470248],"hpluv":[238.334617604481764,37.8306403353000036,62.4388911462841207],"hsluv":[238.334617604481764,23.6900457250072343,62.4388911462841207]},"#8899bb":{"lch":[63.0143540484962,31.8509402607766567,251.009167860858838],"luv":[63.0143540484962,-10.3648329189902189,-30.1173145226625429],"rgb":[0.533333333333333326,0.6,0.733333333333333282],"xyz":[0.305125359851571354,0.316041427285434495,0.515079175606111939],"hpluv":[251.009167860858838,64.1389868285616132,63.0143540484962],"hsluv":[251.009167860858838,32.2218698989210282,63.0143540484962]},"#8899cc":{"lch":[63.6523012354060143,45.9199042321153357,256.173658840600297],"luv":[63.6523012354060143,-10.9739341944061159,-44.5893526863026821],"rgb":[0.533333333333333326,0.6,0.8],"xyz":[0.324417735295293053,0.323758377462923297,0.616685686276382095],"hpluv":[256.173658840600297,91.543221315317254,63.6523012354060143],"hsluv":[256.173658840600297,48.1563502503440546,63.6523012354060143]},"#8899dd":{"lch":[64.3520063546654,60.2052734177332738,258.898139298145679],"luv":[64.3520063546654,-11.5927562398827622,-59.0786166905309358],"rgb":[0.533333333333333326,0.6,0.866666666666666696],"xyz":[0.345936060845926652,0.332365707683176803,0.730015534176388092],"hpluv":[258.898139298145679,118.716686841439611,64.3520063546654],"hsluv":[258.898139298145679,64.7736147673059435,64.3520063546654]},"#8899ee":{"lch":[65.1123593572591091,74.4513212160393465,260.556144021857],"luv":[65.1123593572591091,-12.2160522582942246,-73.442271874149526],"rgb":[0.533333333333333326,0.6,0.933333333333333348],"xyz":[0.369748241112101361,0.34189057978964682,0.855426350244911315],"hpluv":[260.556144021857,145.093615685215838,65.1123593572591091],"hsluv":[260.556144021857,82.0482136329290626,65.1123593572591091]},"#8899ff":{"lch":[65.9319161385595862,88.5102230179824829,261.65889869963604],"luv":[65.9319161385595862,-12.8398242875011679,-87.5739601191992],"rgb":[0.533333333333333326,0.6,1],"xyz":[0.395919289521932782,0.352358999153579544,0.993260538536693161],"hpluv":[261.65889869963604,170.348009793708229,65.9319161385595862],"hsluv":[261.65889869963604,99.9999999999983373,65.9319161385595862]},"#aa9900":{"lch":[62.7844580943873609,69.6780489210530618,75.8779002673010297],"luv":[62.7844580943873609,17.0006834702273615,67.5722373685362072],"rgb":[0.66666666666666663,0.6,0],"xyz":[0.279679277130872483,0.313290833923400402,0.0457396726625379293],"hpluv":[75.8779002673010297,140.82610179048271,62.7844580943873609],"hsluv":[75.8779002673010297,100.000000000002217,62.7844580943873609]},"#aa9911":{"lch":[62.8183644916567232,68.2796688580209548,75.7117398414304],"luv":[62.8183644916567232,16.8514534980901978,66.1675274916835576],"rgb":[0.66666666666666663,0.6,0.0666666666666666657],"xyz":[0.280690942630509588,0.313695500123255255,0.0510677776272935591],"hpluv":[75.7117398414304,137.925354096716262,62.8183644916567232],"hsluv":[75.7117398414304,97.9039601429264792,62.8183644916567232]},"#aa9922":{"lch":[62.8811408657966098,65.7186920323652259,75.3888160486312415],"luv":[62.8811408657966098,16.5780820569936154,63.5933461751813311],"rgb":[0.66666666666666663,0.6,0.133333333333333331],"xyz":[0.282566300768986645,0.314445643378646056,0.0609446638232727586],"hpluv":[75.3888160486312415,132.619634057532949,62.8811408657966098],"hsluv":[75.3888160486312415,94.0678156084237287,62.8811408657966098]},"#aa9933":{"lch":[62.984284118013818,61.5887344728930373,74.8105333616033477],"luv":[62.984284118013818,16.1369729495721401,59.4371122952427768],"rgb":[0.66666666666666663,0.6,0.2],"xyz":[0.28565405150144435,0.315680743671629183,0.0772068176808839],"hpluv":[74.8105333616033477,124.08189266143988,62.984284118013818],"hsluv":[74.8105333616033477,87.8877322232676335,62.984284118013818]},"#aa9944":{"lch":[63.1327254984845325,55.810649390305,73.8551623649617284],"luv":[63.1327254984845325,15.5190685808424753,53.6095802609072862],"rgb":[0.66666666666666663,0.6,0.266666666666666663],"xyz":[0.290112046745663266,0.317463941769316749,0.10068559263377054],"hpluv":[73.8551623649617284,112.176494362550613,63.1327254984845325],"hsluv":[73.8551623649617284,79.2518346201028407,63.1327254984845325]},"#aa9955":{"lch":[63.330394330910508,48.4114193249398497,72.2912631539462893],"luv":[63.330394330910508,14.725704471349518,46.1174495053405593],"rgb":[0.66666666666666663,0.6,0.333333333333333315],"xyz":[0.296074460785025251,0.319848907385061609,0.132087639907744442],"hpluv":[72.2912631539462893,97.0007181904759,63.330394330910508],"hsluv":[72.2912631539462893,68.2014618333714253,63.330394330910508]},"#aa9966":{"lch":[63.5804407621292285,39.5252766283835086,69.6158026784446662],"luv":[63.5804407621292285,13.7671883687516523,37.0501284339143524],"rgb":[0.66666666666666663,0.6,0.4],"xyz":[0.303659456558533436,0.322882905694464928,0.172035284314888404],"hpluv":[69.6158026784446662,78.8843243984218105,63.5804407621292285],"hsluv":[69.6158026784446662,54.9106459007729129,63.5804407621292285]},"#aa9977":{"lch":[63.8853523521207762,29.4269320044373437,64.5162682653354835],"luv":[63.8853523521207762,12.6610788645847681,26.563911782313685],"rgb":[0.66666666666666663,0.6,0.466666666666666674],"xyz":[0.312973469578735342,0.326608510902545723,0.221089086221286313],"hpluv":[64.5162682653354835,58.4497984351079,63.8853523521207762],"hsluv":[64.5162682653354835,39.6604297676390303,63.8853523521207762]},"#aa9988":{"lch":[64.2470245358341288,18.7498828458428441,52.4386898809200943],"luv":[64.2470245358341288,11.4301164327749429,14.8630597477787205],"rgb":[0.66666666666666663,0.6,0.533333333333333326],"xyz":[0.324113886680679142,0.331064677743323321,0.279761949624858508],"hpluv":[52.4386898809200943,37.0326564248891472,64.2470245358341288],"hsluv":[52.4386898809200943,22.8076315183033955,64.2470245358341288]},"#aa9999":{"lch":[64.6668097656484,10.3324715423982241,12.1770506300641514],"luv":[64.6668097656484,10.0999956892392,2.17946214737001709],"rgb":[0.66666666666666663,0.6,0.6],"xyz":[0.337170850789751841,0.336287463386952479,0.348528627265976387],"hpluv":[12.1770506300641514,20.2750581327120152,64.6668097656484],"hsluv":[12.1770506300641514,9.39861318597140283,64.6668097656484]},"#aa99aa":{"lch":[65.1455571833188,14.2173372068657535,307.715012949255367],"luv":[65.1455571833188,8.69723339065650514,-11.2468132643064216],"rgb":[0.66666666666666663,0.6,0.66666666666666663],"xyz":[0.352228543755004397,0.342310540573053601,0.427832476882975],"hpluv":[307.715012949255367,27.6931773999722353,65.1455571833188],"hsluv":[307.715012949255367,11.6506794595111955,65.1455571833188]},"#aa99bb":{"lch":[65.6836488991384186,26.2061362707181722,286.054514249721478],"luv":[65.6836488991384186,7.24735484809431529,-25.1840708771488],"rgb":[0.66666666666666663,0.6,0.733333333333333282],"xyz":[0.369366135862341072,0.34916557741598836,0.51809046198161679],"hpluv":[286.054514249721478,50.6273330900370553,65.6836488991384186],"hsluv":[286.054514249721478,27.5721610485895,65.6836488991384186]},"#aa99cc":{"lch":[66.2810360009151651,39.8419200501833544,278.33213307587846],"luv":[66.2810360009151651,5.77353773601307907,-39.4213756139487757],"rgb":[0.66666666666666663,0.6,0.8],"xyz":[0.388658511306062771,0.356882527593477161,0.619696972651887],"hpluv":[278.33213307587846,76.2764194246967,66.2810360009151651],"hsluv":[278.33213307587846,44.416066179202609,66.2810360009151651]},"#aa99dd":{"lch":[66.937275739096421,53.9476968390211695,274.567192844176702],"luv":[66.937275739096421,4.29575598209881182,-53.7763932853180151],"rgb":[0.66666666666666663,0.6,0.866666666666666696],"xyz":[0.41017683685669637,0.365489857813730668,0.733026820551892944],"hpluv":[274.567192844176702,102.269045280662851,66.937275739096421],"hsluv":[274.567192844176702,62.1125641321495365,66.937275739096421]},"#aa99ee":{"lch":[67.6515703211096309,68.1578213039093299,272.380002942583644],"luv":[67.6515703211096309,2.83038594926376286,-68.0990273078393358],"rgb":[0.66666666666666663,0.6,0.933333333333333348],"xyz":[0.433989017122871079,0.375014729920200685,0.858437636620416167],"hpluv":[272.380002942583644,127.843056183363871,67.6515703211096309],"hsluv":[272.380002942583644,80.63443597048024,67.6515703211096309]},"#aa99ff":{"lch":[68.4228071241374778,82.2834014236355387,270.968064044661787],"luv":[68.4228071241374778,1.39018638405132466,-82.2716569157370543],"rgb":[0.66666666666666663,0.6,1],"xyz":[0.4601600655327025,0.385483149284133408,0.996271824912198],"hpluv":[270.968064044661787,152.598644218259693,68.4228071241374778],"hsluv":[270.968064044661787,99.9999999999981668,68.4228071241374778]},"#770000":{"lch":[23.4140868272264697,78.7423116347599432,12.177050630061796],"luv":[23.4140868272264697,76.9706458719381317,16.6093743302492847],"rgb":[0.466666666666666674,0,0],"xyz":[0.0760757904266185919,0.0392265794387260461,0.00356605267624767169],"hpluv":[12.177050630061796,426.746789183125429,23.4140868272264697],"hsluv":[12.177050630061796,100.000000000002359,23.4140868272264697]},"#770011":{"lch":[23.5491569362977273,75.7570426868466456,9.89164947332394462],"luv":[23.5491569362977273,74.6308667748156864,13.0139633123970793],"rgb":[0.466666666666666674,0,0.0666666666666666657],"xyz":[0.0770874559262557102,0.0396312456385809,0.00889415764100330228],"hpluv":[9.89164947332394462,408.213135586655085,23.5491569362977273],"hsluv":[9.89164947332394462,99.9999999999965183,23.5491569362977273]},"#770022":{"lch":[23.7971287372198219,70.9964864167640854,5.53723409440817704],"luv":[23.7971287372198219,70.6651956613751224,6.85063542055327357],"rgb":[0.466666666666666674,0,0.133333333333333331],"xyz":[0.0789628140647327392,0.0403813888939717203,0.0187710438369825],"hpluv":[5.53723409440817704,378.574731225432288,23.7971287372198219],"hsluv":[5.53723409440817704,99.9999999999967741,23.7971287372198219]},"#770033":{"lch":[24.198804347572846,65.0463245726941182,358.140059561726389],"luv":[24.198804347572846,65.0120550988218895,-2.11116845467566527],"rgb":[0.466666666666666674,0,0.2],"xyz":[0.0820505647971904728,0.0416164891869548331,0.0350331976945936416],"hpluv":[358.140059561726389,341.089366306392606,24.198804347572846],"hsluv":[358.140059561726389,99.9999999999971578,24.198804347572846]},"#770044":{"lch":[24.764944554878376,59.7650645123016702,347.391874641304071],"luv":[24.764944554878376,58.3238787679626398,-13.0456161839744915],"rgb":[0.466666666666666674,0,0.266666666666666663],"xyz":[0.0865085600414093464,0.0433996872846424062,0.0585119726474802801],"hpluv":[347.391874641304071,306.231145677972847,24.764944554878376],"hsluv":[347.391874641304071,99.9999999999975557,24.764944554878376]},"#770055":{"lch":[25.4983947844981387,57.0853266397623571,333.997796644431901],"luv":[25.4983947844981387,51.3069893372134587,-25.0265331742018731],"rgb":[0.466666666666666674,0,0.333333333333333315],"xyz":[0.0924709740807713454,0.0457846529003872391,0.0899140199214541885],"hpluv":[333.997796644431901,284.086748448009075,25.4983947844981387],"hsluv":[333.997796644431901,99.999999999998,25.4983947844981387]},"#770066":{"lch":[26.3955149445472088,58.0812929265372375,320.022905340944305],"luv":[26.3955149445472088,44.5077732621065394,-37.3161453966930949],"rgb":[0.466666666666666674,0,0.4],"xyz":[0.100055969854279517,0.0488186512097905506,0.129861664328598164],"hpluv":[320.022905340944305,279.219318659546161,26.3955149445472088],"hsluv":[320.022905340944305,99.9999999999984,26.3955149445472088]},"#770077":{"lch":[27.4476614837194361,62.5213221502200156,307.715012949243601],"luv":[27.4476614837194361,38.2464397320582776,-49.4583215569799322],"rgb":[0.466666666666666674,0,0.466666666666666674],"xyz":[0.109369982874481436,0.052544256417871367,0.178915466234996073],"hpluv":[307.715012949243601,289.04278373048345,27.4476614837194361],"hsluv":[307.715012949243601,99.9999999999988631,27.4476614837194361]},"#770088":{"lch":[28.6427236217895711,69.3985842918787341,298.067280282401043],"luv":[28.6427236217895711,32.6525926425722872,-61.2370124633397808],"rgb":[0.466666666666666674,0,0.533333333333333326],"xyz":[0.120510399976425264,0.0570004232586489579,0.237588329638568241],"hpluv":[298.067280282401043,307.450798390810235,28.6427236217895711],"hsluv":[298.067280282401043,99.9999999999991473,28.6427236217895711]},"#770099":{"lch":[29.9665727349335924,77.70857748467688,290.909274437861086],"luv":[29.9665727349335924,27.7333531267432782,-72.5912125469701],"rgb":[0.466666666666666674,0,0.6],"xyz":[0.133567364085497964,0.0622232089022781223,0.30635500727968612],"hpluv":[290.909274437861086,329.057057444315717,29.9665727349335924],"hsluv":[290.909274437861086,99.9999999999993605,29.9665727349335924]},"#7700aa":{"lch":[31.4042918618800115,86.7647813143177,285.668616902051383],"luv":[31.4042918618800115,23.4328336498598695,-83.5405864455078415],"rgb":[0.466666666666666674,0,0.66666666666666663],"xyz":[0.14862505705075052,0.0682462860883792238,0.385658856896684721],"hpluv":[285.668616902051383,350.585377409449279,31.4042918618800115],"hsluv":[285.668616902051383,99.9999999999996447,31.4042918618800115]},"#7700bb":{"lch":[32.9411141237069387,96.170393631615,281.802895608829544],"luv":[32.9411141237069387,19.6712233173334745,-94.1370680681067853],"rgb":[0.466666666666666674,0,0.733333333333333282],"xyz":[0.165762649158087166,0.0751013229313139824,0.475916841995326467],"hpluv":[281.802895608829544,370.460950364720645,32.9411141237069387],"hsluv":[281.802895608829544,99.9999999999998295,32.9411141237069387]},"#7700cc":{"lch":[34.5630635499026226,105.713400517707811,278.906152205018032],"luv":[34.5630635499026226,16.3661753747823724,-104.438840249301762],"rgb":[0.466666666666666674,0,0.8],"xyz":[0.185055024601808893,0.082818273108802784,0.577523352665596623],"hpluv":[278.906152205018032,388.112061604616713,34.5630635499026226],"hsluv":[278.906152205018032,99.9999999999998721,34.5630635499026226]},"#7700dd":{"lch":[36.2573361534597964,115.285120662302717,276.696107756350386],"luv":[36.2573361534597964,13.4426218553338188,-114.498711624961956],"rgb":[0.466666666666666674,0,0.866666666666666696],"xyz":[0.206573350152442436,0.091425603329056318,0.690853200565602621],"hpluv":[276.696107756350386,403.475057258468723,36.2573361534597964],"hsluv":[276.696107756350386,100.000000000000156,36.2573361534597964]},"#7700ee":{"lch":[38.012479203832,124.831519574090535,274.979891409884715],"luv":[38.012479203832,10.8361388436516783,-124.360308676593633],"rgb":[0.466666666666666674,0,0.933333333333333348],"xyz":[0.230385530418617201,0.100950475435526349,0.816264016634125844],"hpluv":[274.979891409884715,416.713325299391272,38.012479203832],"hsluv":[274.979891409884715,100.000000000000156,38.012479203832]},"#7700ff":{"lch":[39.8184284160989037,134.326708962856742,273.625091115001112],"luv":[39.8184284160989037,8.49315165227522861,-134.057939398617776],"rgb":[0.466666666666666674,0,1],"xyz":[0.256556578828448567,0.111418894799459045,0.954098204925907689],"hpluv":[273.625091115001112,428.072753406140123,39.8184284160989037],"hsluv":[273.625091115001112,100.000000000000313,39.8184284160989037]},"#771100":{"lch":[24.7134353555624457,74.5310598854495794,14.479461840222152],"luv":[24.7134353555624457,72.1637543524892351,18.6352205622059],"rgb":[0.466666666666666674,0.0666666666666666657,0],"xyz":[0.078080190687547,0.0432353799605829231,0.00423418609655712257],"hpluv":[14.479461840222152,382.686818993669249,24.7134353555624457],"hsluv":[14.479461840222152,100.000000000002174,24.7134353555624457]},"#771111":{"lch":[24.8400617115613187,71.7342088143168723,12.1770506300618244],"luv":[24.8400617115613187,70.1202221387804912,15.1311321924069837],"rgb":[0.466666666666666674,0.0666666666666666657,0.0666666666666666657],"xyz":[0.0790918561871841175,0.043640046160437776,0.00956229106131275403],"hpluv":[12.1770506300618244,366.448517223619376,24.8400617115613187],"hsluv":[12.1770506300618244,85.8702458957174173,24.8400617115613187]},"#771122":{"lch":[25.0727380413203562,67.2476760425649616,7.76714475492354417],"luv":[25.0727380413203562,66.6307123231625,9.0883501491595],"rgb":[0.466666666666666674,0.0666666666666666657,0.133333333333333331],"xyz":[0.0809672143256611465,0.0443901894158286,0.0194391772572919501],"hpluv":[7.76714475492354417,340.341449223453765,25.0727380413203562],"hsluv":[7.76714475492354417,86.6206298981217,25.0727380413203562]},"#771133":{"lch":[25.4501908259833556,61.6001849310061189,0.209311103178295294],"luv":[25.4501908259833556,61.599773884646936,0.225035318388215971],"rgb":[0.466666666666666674,0.0666666666666666657,0.2],"xyz":[0.0840549650581188801,0.0456252897088117101,0.0357013311149031],"hpluv":[0.209311103178295294,307.135699817562568,25.4501908259833556],"hsluv":[0.209311103178295294,87.6964449022470802,25.4501908259833556]},"#771144":{"lch":[25.9833113937366775,56.5829308746863688,349.098656617234155],"luv":[25.9833113937366775,55.5618510799655,-10.7008771106518541],"rgb":[0.466666666666666674,0.0666666666666666657,0.266666666666666663],"xyz":[0.0885129603023377537,0.0474084878064992832,0.0591801060677897353],"hpluv":[349.098656617234155,276.331419289390624,25.9833113937366775],"hsluv":[349.098656617234155,88.9762099121112442,25.9833113937366775]},"#771155":{"lch":[26.6758393728738312,54.157242934368746,335.112354986374442],"luv":[26.6758393728738312,49.127918835603694,-22.7915456504066185],"rgb":[0.466666666666666674,0.0666666666666666657,0.333333333333333315],"xyz":[0.0944753743416997527,0.0497934534222441161,0.0905821533417636438],"hpluv":[335.112354986374442,257.618934567198892,26.6758393728738312],"hsluv":[335.112354986374442,90.3225181656420375,26.6758393728738312]},"#771166":{"lch":[27.5255776115618076,55.4731266930874796,320.490705765847224],"luv":[27.5255776115618076,42.7987039146097388,-35.2921907557026557],"rgb":[0.466666666666666674,0.0666666666666666657,0.4],"xyz":[0.102060370115207924,0.0528274517316474276,0.130529797748907606],"hpluv":[320.490705765847224,255.732268141411282,27.5255776115618076],"hsluv":[320.490705765847224,91.6238582413064364,27.5255776115618076]},"#771177":{"lch":[28.525624322061,60.3055315504910538,307.715012949243658],"luv":[28.525624322061,36.8909645322892956,-47.7054909990940672],"rgb":[0.466666666666666674,0.0666666666666666657,0.466666666666666674],"xyz":[0.111374383135409843,0.056553056939728244,0.179583599655305515],"hpluv":[307.715012949243658,268.263334170626,28.525624322061],"hsluv":[307.715012949243658,92.8109433172232201,28.525624322061]},"#771188":{"lch":[29.665668786552871,67.5901402176946,297.828537901307072],"luv":[29.665668786552871,31.5529142063876336,-59.77324367751811],"rgb":[0.466666666666666674,0.0666666666666666657,0.533333333333333326],"xyz":[0.122514800237353672,0.0610092237805058418,0.238256463058877682],"hpluv":[297.828537901307072,289.113605882780575,29.665668786552871],"hsluv":[297.828537901307072,93.8529472884676892,29.665668786552871]},"#771199":{"lch":[30.9332504381216253,76.2730393291315494,290.583951381139741],"luv":[30.9332504381216253,26.816032696200331,-71.4036197887723461],"rgb":[0.466666666666666674,0.0666666666666666657,0.6],"xyz":[0.135571764346426371,0.066232009424135,0.307023140699995589],"hpluv":[290.583951381139741,312.885056330098905,30.9332504381216253],"hsluv":[290.583951381139741,94.745562802664864,30.9332504381216253]},"#7711aa":{"lch":[32.3148680584756391,85.6471240548678452,285.332056603477554],"luv":[32.3148680584756391,22.6461849228904,-82.5989114172104166],"rgb":[0.466666666666666674,0.0666666666666666657,0.66666666666666663],"xyz":[0.150629457311678927,0.0722550866102361078,0.38632699031699419],"hpluv":[285.332056603477554,336.317699636744408,32.3148680584756391],"hsluv":[285.332056603477554,95.4992611083078771,32.3148680584756391]},"#7711bb":{"lch":[33.796865882550442,95.3131880713117,281.486339493443666],"luv":[33.796865882550442,18.9801244444786903,-93.4042755787407],"rgb":[0.466666666666666674,0.0666666666666666657,0.733333333333333282],"xyz":[0.167767049419015574,0.0791101234531708664,0.476584975415635936],"hpluv":[281.486339493443666,357.862255189103962,33.796865882550442],"hsluv":[281.486339493443666,96.130904738193,33.796865882550442]},"#7711cc":{"lch":[35.36607449089243,105.064609202725904,278.619980375929231],"luv":[35.36607449089243,15.7470979978009513,-103.877817707002151],"rgb":[0.466666666666666674,0.0666666666666666657,0.8],"xyz":[0.1870594248627373,0.086827073630659668,0.578191486085906092],"hpluv":[278.619980375929231,376.971848031202455,35.36607449089243],"hsluv":[278.619980375929231,96.6587778670915441,35.36607449089243]},"#7711dd":{"lch":[37.0102245888209,114.800572621107989,276.441726024966442],"luv":[37.0102245888209,12.8797770828984923,-114.075776641796878],"rgb":[0.466666666666666674,0.0666666666666666657,0.866666666666666696],"xyz":[0.208577750413370844,0.0954344038509132,0.69152133398591209],"hpluv":[276.441726024966442,393.605954910771402,37.0102245888209],"hsluv":[276.441726024966442,97.1000737310191084,37.0102245888209]},"#7711ee":{"lch":[38.7181742300654648,124.475046910670883,274.755182332196796],"luv":[38.7181742300654648,10.3187754184265525,-124.046604859938796],"rgb":[0.466666666666666674,0.0666666666666666657,0.933333333333333348],"xyz":[0.232389930679545609,0.104959275957383219,0.816932150054435313],"hpluv":[274.755182332196796,407.949828918098,38.7181742300654648],"hsluv":[274.755182332196796,97.4698666617264706,38.7181742300654648]},"#7711ff":{"lch":[40.4799968781786,134.069342311184641,273.42679883886251],"luv":[40.4799968781786,8.01376323316973682,-133.829623576382744],"rgb":[0.466666666666666674,0.0666666666666666657,1],"xyz":[0.258560979089377,0.115427695321315929,0.954766338346217158],"hpluv":[273.42679883886251,420.269946860795244,40.4799968781786],"hsluv":[273.42679883886251,99.99999999999946,40.4799968781786]},"#772200":{"lch":[26.9238486490213944,67.8779226750429814,18.9619118830866213],"luv":[26.9238486490213944,64.1945131058521241,22.0562207502031953],"rgb":[0.466666666666666674,0.133333333333333331,0],"xyz":[0.0817958144223149414,0.0506666274301188907,0.00547272734147973266],"hpluv":[18.9619118830866213,319.912145739235086,26.9238486490213944],"hsluv":[18.9619118830866213,100.000000000002203,26.9238486490213944]},"#772211":{"lch":[27.0378210495853537,65.3114997865878451,16.6506371445360628],"luv":[27.0378210495853537,62.5729698674152957,18.7140440938083152],"rgb":[0.466666666666666674,0.133333333333333331,0.0666666666666666657],"xyz":[0.0828074799219520596,0.0510712936299737436,0.0108008323062353633],"hpluv":[16.6506371445360628,306.518925183772069,27.0378210495853537],"hsluv":[16.6506371445360628,87.77659617077137,27.0378210495853537]},"#772222":{"lch":[27.2475131582451553,61.1491638550902934,12.1770506300618262],"luv":[27.2475131582451553,59.7733358183195094,12.8983939049434628],"rgb":[0.466666666666666674,0.133333333333333331,0.133333333333333331],"xyz":[0.0846828380604290887,0.0518214368853645649,0.0206777185022145593],"hpluv":[12.1770506300618262,284.775733052529233,27.2475131582451553],"hsluv":[12.1770506300618262,66.7317810633447,27.2475131582451553]},"#772233":{"lch":[27.5884028886125066,55.830319472153235,4.36926883706767555],"luv":[27.5884028886125066,55.668063043001986,4.25339034219168255],"rgb":[0.466666666666666674,0.133333333333333331,0.2],"xyz":[0.0877705887928868222,0.0530565371783476777,0.0369398723598257],"hpluv":[4.36926883706767555,256.792821962959806,27.5884028886125066],"hsluv":[4.36926883706767555,69.0869865520346,27.5884028886125066]},"#772244":{"lch":[28.0713586292933357,51.0577981227000137,352.597218961633928],"luv":[28.0713586292933357,50.6322267647614197,-6.57847717790113862],"rgb":[0.466666666666666674,0.133333333333333331,0.266666666666666663],"xyz":[0.0922285840371057,0.0548397352760352508,0.0604186473127123411],"hpluv":[352.597218961633928,230.801153887638264,28.0713586292933357],"hsluv":[352.597218961633928,71.9536276136468871,28.0713586292933357]},"#772255":{"lch":[28.7011983995690869,48.8793621784160877,337.425357822166575],"luv":[28.7011983995690869,45.134235573623549,-18.7641367015226166],"rgb":[0.466666666666666674,0.133333333333333331,0.333333333333333315],"xyz":[0.0981909980764677,0.0572247008917800837,0.0918206945866862495],"hpluv":[337.425357822166575,216.105005327694982,28.7011983995690869],"hsluv":[337.425357822166575,75.0482997779786416,28.7011983995690869]},"#772266":{"lch":[29.4776386596593341,50.6214045611569148,321.457127980188602],"luv":[29.4776386596593341,39.5931335065919541,-31.5421999688275427],"rgb":[0.466666666666666674,0.133333333333333331,0.4],"xyz":[0.105775993849975866,0.0602586992011833952,0.131768338993830225],"hpluv":[321.457127980188602,217.911839443782668,29.4776386596593341],"hsluv":[321.457127980188602,78.1196257410634871,29.4776386596593341]},"#772277":{"lch":[30.3962065887853328,56.0773495547330114,307.715012949243828],"luv":[30.3962065887853328,34.3044404103525125,-44.3607315225559375],"rgb":[0.466666666666666674,0.133333333333333331,0.466666666666666674],"xyz":[0.115090006870177786,0.0639843044092642116,0.180822140900228134],"hpluv":[307.715012949243828,234.103236488433623,30.3962065887853328],"hsluv":[307.715012949243828,80.9925899090149,30.3962065887853328]},"#772288":{"lch":[31.4492100235983827,64.0564791390884,297.353574907339521],"luv":[31.4492100235983827,29.432687880373738,-56.8941948166328118],"rgb":[0.466666666666666674,0.133333333333333331,0.533333333333333326],"xyz":[0.126230423972121614,0.0684404712500418094,0.239495004303800302],"hpluv":[297.353574907339521,258.459589193709576,31.4492100235983827],"hsluv":[297.353574907339521,83.5725358287189692,31.4492100235983827]},"#772299":{"lch":[32.6267183371791276,73.3979299617999885,289.947447059718741],"luv":[32.6267183371791276,25.040297814612174,-68.9944896932561136],"rgb":[0.466666666666666674,0.133333333333333331,0.6],"xyz":[0.139287388081194341,0.073663256893670967,0.308261681944918209],"hpluv":[289.947447059718741,285.462946683821,32.6267183371791276],"hsluv":[289.947447059718741,85.8272099061853169,32.6267183371791276]},"#7722aa":{"lch":[33.91747454857272,83.3484305918169213,284.681710760769079],"luv":[33.91747454857272,21.1245907707188039,-80.6269963900962],"rgb":[0.466666666666666674,0.133333333333333331,0.66666666666666663],"xyz":[0.154345081046446869,0.0796863340797720754,0.38756553156191681],"hpluv":[284.681710760769079,311.826661765562392,33.91747454857272],"hsluv":[284.681710760769079,87.7639475735253,33.91747454857272]},"#7722bb":{"lch":[35.3096729107126137,93.4985765466947,280.880145280973409],"luv":[35.3096729107126137,17.6483381470917493,-91.8178630599952186],"rgb":[0.466666666666666674,0.133333333333333331,0.733333333333333282],"xyz":[0.171482673153783516,0.086541370922706834,0.477823516660558556],"hpluv":[280.880145280973409,336.008784107710085,35.3096729107126137],"hsluv":[280.880145280973409,89.410850129911168,35.3096729107126137]},"#7722cc":{"lch":[36.7915673195940158,103.646851370476796,278.075561058441508],"luv":[36.7915673195940158,14.5601992392030191,-102.619054746808203],"rgb":[0.466666666666666674,0.133333333333333331,0.8],"xyz":[0.19077504859750527,0.0942583211001956356,0.579430027330828712],"hpluv":[278.075561058441508,357.476214898523438,36.7915673195940158],"hsluv":[278.075561058441508,90.8041771911133395,36.7915673195940158]},"#7722dd":{"lch":[38.351906528896663,113.703099806952181,275.960131804992216],"luv":[38.351906528896663,11.8065226659589069,-113.088465053903391],"rgb":[0.466666666666666674,0.133333333333333331,0.866666666666666696],"xyz":[0.212293374148138814,0.10286565132044917,0.69275987523083471],"hpluv":[275.960131804992216,376.205095027198126,38.351906528896663],"hsluv":[275.960131804992216,91.9810564333708101,38.351906528896663]},"#7722ee":{"lch":[39.9802139341708269,123.633267676123751,274.331320845995606],"luv":[39.9802139341708269,9.33725773346982812,-123.280170726255989],"rgb":[0.466666666666666674,0.133333333333333331,0.933333333333333348],"xyz":[0.236105554414313523,0.112390523426919187,0.818170691299357933],"hpluv":[274.331320845995606,392.400507860275241,39.9802139341708269],"hsluv":[274.331320845995606,92.975835565241681,39.9802139341708269]},"#7722ff":{"lch":[41.6669409214524222,133.430100966175758,273.053819065229],"luv":[41.6669409214524222,7.10835060884393233,-133.240621416539511],"rgb":[0.466666666666666674,0.133333333333333331,1],"xyz":[0.262276602824144944,0.122858942790851897,0.956004879591139778],"hpluv":[273.053819065229,406.351179140502,41.6669409214524222],"hsluv":[273.053819065229,99.9999999999994,41.6669409214524222]},"#eeaa00":{"lch":[74.1441199778221716,94.3993067628715323,52.9277228913731435],"luv":[74.1441199778221716,56.9059790518510553,75.3189130661151438],"rgb":[0.933333333333333348,0.66666666666666663,0],"xyz":[0.496332043879122442,0.469286695915611562,0.0644413600602487119],"hpluv":[52.9277228913731435,161.559096825574699,74.1441199778221716],"hsluv":[52.9277228913731435,100.00000000000226,74.1441199778221716]},"#eeaa11":{"lch":[74.170022976797469,93.4032488378738748,52.6298301838218165],"luv":[74.170022976797469,56.6922374254564474,74.2304325001913412],"rgb":[0.933333333333333348,0.66666666666666663,0.0666666666666666657],"xyz":[0.497343709378759546,0.469691362115466415,0.0697694650250043485],"hpluv":[52.6298301838218165,159.798572537124,74.170022976797469],"hsluv":[52.6298301838218165,98.6103970010943698,74.170022976797469]},"#eeaa22":{"lch":[74.2180009061856794,91.5777923210439866,52.06484069365154],"luv":[74.2180009061856794,56.2992155036066038,72.2280442769616],"rgb":[0.933333333333333348,0.66666666666666663,0.133333333333333331],"xyz":[0.499219067517236603,0.470441505370857216,0.0796463512209835411],"hpluv":[52.06484069365154,156.574215350823607,74.2180009061856794],"hsluv":[52.06484069365154,96.0561964998804427,74.2180009061856794]},"#eeaa33":{"lch":[74.296884894391,88.6315089581908353,51.0969321655322659],"luv":[74.296884894391,55.6610065739707096,68.9738843866158646],"rgb":[0.933333333333333348,0.66666666666666663,0.2],"xyz":[0.502306818249694365,0.471676605663840343,0.0959085050785946913],"hpluv":[51.0969321655322659,151.375944062314744,74.296884894391],"hsluv":[51.0969321655322659,91.9112466174575786,74.296884894391]},"#eeaa44":{"lch":[74.4105324975616,84.5080331915566,49.6113532778883268],"luv":[74.4105324975616,54.7585847399730952,64.3669563610119582],"rgb":[0.933333333333333348,0.66666666666666663,0.266666666666666663],"xyz":[0.506764813493913224,0.473459803761527909,0.11938728003148133],"hpluv":[49.6113532778883268,144.112916810009352,74.4105324975616],"hsluv":[49.6113532778883268,86.056132752536,74.4105324975616]},"#eeaa55":{"lch":[74.5620870475656545,79.2349762990306203,47.4460085751506284],"luv":[74.5620870475656545,53.5853993814341081,58.3676832008958897],"rgb":[0.933333333333333348,0.66666666666666663,0.333333333333333315],"xyz":[0.512727227533275154,0.475844769377272769,0.150789327305455245],"hpluv":[47.4460085751506284,134.846041865267,74.5620870475656545],"hsluv":[47.4460085751506284,78.4547380743125302,74.5620870475656545]},"#eeaa66":{"lch":[74.7541548019056705,72.9335579755352512,44.3584242628533616],"luv":[74.7541548019056705,52.1460491859645643,50.9911113162453518],"rgb":[0.933333333333333348,0.66666666666666663,0.4],"xyz":[0.520312223306783395,0.478878767686676088,0.190736971712599179],"hpluv":[44.3584242628533616,123.803063546095515,74.7541548019056705],"hsluv":[44.3584242628533616,69.1456590086766,74.7541548019056705]},"#eeaa77":{"lch":[74.988898345165353,65.8409092602829702,39.9757578623994689],"luv":[74.988898345165353,50.4549646902964213,42.3003767160737851],"rgb":[0.933333333333333348,0.66666666666666663,0.466666666666666674],"xyz":[0.529626236326985245,0.482604372894756883,0.239790773618997088],"hpluv":[39.9757578623994689,111.41359114675457,74.988898345165353],"hsluv":[39.9757578623994689,69.3768546233612398,74.988898345165353]},"#eeaa88":{"lch":[75.268091919562039,58.355059996267,33.7246537035848917],"luv":[75.268091919562039,48.5347963512250544,32.3988668060016],"rgb":[0.933333333333333348,0.66666666666666663,0.533333333333333326],"xyz":[0.540766653428929156,0.487060539735534481,0.298463637022569284],"hpluv":[33.7246537035848917,98.3800275430836706,75.268091919562039],"hsluv":[33.7246537035848917,69.7313730072723388,75.268091919562039]},"#eeaa99":{"lch":[75.5931575717450102,51.1191249468368198,24.7740386445795764],"luv":[75.5931575717450102,46.4145012045046172,21.4209946843594],"rgb":[0.933333333333333348,0.66666666666666663,0.6],"xyz":[0.5538236175380018,0.492283325379163639,0.367230314663687163],"hpluv":[24.7740386445795764,85.8104641434512274,75.5931575717450102],"hsluv":[24.7740386445795764,70.1099573125584925,75.5931575717450102]},"#eeaaaa":{"lch":[75.9651912478537,45.142946910964838,12.1770506300622827],"luv":[75.9651912478537,44.1272513869876164,9.52215001119964199],"rgb":[0.933333333333333348,0.66666666666666663,0.66666666666666663],"xyz":[0.568881310503254412,0.498306402565264761,0.446534164280685764],"hpluv":[12.1770506300622827,75.4075094474617771,75.9651912478537],"hsluv":[12.1770506300622827,70.5013292017584661,75.9651912478537]},"#eeaabb":{"lch":[76.3849837125259512,41.8257198613105743,355.706426922992932],"luv":[76.3849837125259512,41.7083375548448743,-3.13136077895000353],"rgb":[0.933333333333333348,0.66666666666666663,0.733333333333333282],"xyz":[0.586018902610591,0.505161439408199464,0.53679214937932751],"hpluv":[355.706426922992932,71.0120800923082243,76.3849837125259512],"hsluv":[355.706426922992932,70.8933377227291857,76.3849837125259512]},"#eeaacc":{"lch":[76.8530390510081,42.4751513806234229,337.329003704434115],"luv":[76.8530390510081,39.1932374848878169,-16.3715796507258275],"rgb":[0.933333333333333348,0.66666666666666663,0.8],"xyz":[0.605311278054312729,0.512878389585688321,0.638398660049597666],"hpluv":[337.329003704434115,73.8860979443606283,76.8530390510081],"hsluv":[337.329003704434115,71.273377003825658,76.8530390510081]},"#eeaadd":{"lch":[77.3695923472492666,47.3596417233686893,320.637369166639587],"luv":[77.3695923472492666,36.6159833837478814,-30.0367345929437413],"rgb":[0.933333333333333348,0.66666666666666663,0.866666666666666696],"xyz":[0.626829603604946328,0.521485719805941828,0.751728507949603664],"hpluv":[320.637369166639587,84.6581146126829,77.3695923472492666],"hsluv":[320.637369166639587,71.6287050870027144,77.3695923472492666]},"#eeaaee":{"lch":[77.9346274334411078,55.5926087174301244,307.715012949246329],"luv":[77.9346274334411078,34.00790779424905,-43.9772708506012506],"rgb":[0.933333333333333348,0.66666666666666663,0.933333333333333348],"xyz":[0.650641783871121,0.531010591912411845,0.877139324018126887],"hpluv":[307.715012949246329,102.440850498764817,77.9346274334411078],"hsluv":[307.715012949246329,71.9466349992656,77.9346274334411078]},"#eeaaff":{"lch":[78.5478951631237123,66.0054362136172,298.40296943037481],"luv":[78.5478951631237123,31.3967924706888546,-58.0599606639755166],"rgb":[0.933333333333333348,0.66666666666666663,1],"xyz":[0.676812832280952459,0.541479011276344568,1.01497351230990884],"hpluv":[298.40296943037481,125.797711632464541,78.5478951631237123],"hsluv":[298.40296943037481,99.9999999999967457,78.5478951631237123]},"#773300":{"lch":[30.1331354048611715,59.6402239078303253,26.8671398719653283],"luv":[30.1331354048611715,53.2024709950710601,26.952799257122777],"rgb":[0.466666666666666674,0.2,0],"xyz":[0.0879135365113257461,0.0629020716081407,0.0075119680378166135],"hpluv":[26.8671398719653283,251.150628123644026,30.1331354048611715],"hsluv":[26.8671398719653283,100.000000000002174,30.1331354048611715]},"#773311":{"lch":[30.23185303241101,57.2493346092074376,24.6191658238461528],"luv":[30.23185303241101,52.0451874365790204,23.8492091669378929],"rgb":[0.466666666666666674,0.2,0.0666666666666666657],"xyz":[0.0889252020109628644,0.0633067378079955473,0.012840073002572245],"hpluv":[24.6191658238461528,240.295148301589592,30.23185303241101],"hsluv":[24.6191658238461528,89.9983576544591131,30.23185303241101]},"#773322":{"lch":[30.4137421865898716,53.2944669038914185,20.1857997859538507],"luv":[30.4137421865898716,50.0210446853216055,18.3900867632275506],"rgb":[0.466666666666666674,0.2,0.133333333333333331],"xyz":[0.0908005601494399,0.0640568810633863617,0.022716959198551441],"hpluv":[20.1857997859538507,222.35740076876786,30.4137421865898716],"hsluv":[20.1857997859538507,72.5478159849102,30.4137421865898716]},"#773333":{"lch":[30.7101510688592612,48.0738359215612618,12.1770506300619186],"luv":[30.7101510688592612,46.9921967440780932,10.1403720532853221],"rgb":[0.466666666666666674,0.2,0.2],"xyz":[0.093888310881897627,0.0652919813563694745,0.0389791130561625843],"hpluv":[12.1770506300619186,198.639745699191,30.7101510688592612],"hsluv":[12.1770506300619186,46.5474493854848177,30.7101510688592612]},"#773344":{"lch":[31.1315732769052218,43.177963340605487,359.450637080068248],"luv":[31.1315732769052218,43.1759786068728815,-0.413992248148033204],"rgb":[0.466666666666666674,0.2,0.266666666666666663],"xyz":[0.0983463061261165,0.0670751794540570545,0.0624578880090492228],"hpluv":[359.450637080068248,175.995032884643848,31.1315732769052218],"hsluv":[359.450637080068248,50.753084379908266,31.1315732769052218]},"#773355":{"lch":[31.6836931484193158,40.8566925980369149,342.103665666318761],"luv":[31.6836931484193158,38.8798033655970627,-12.5550874271345432],"rgb":[0.466666666666666674,0.2,0.333333333333333315],"xyz":[0.1043087201654785,0.0694601450698018874,0.0938599352830231382],"hpluv":[342.103665666318761,163.631433468067485,31.6836931484193158],"hsluv":[342.103665666318761,55.4419897041632623,31.6836931484193158]},"#773366":{"lch":[32.368092831934419,42.8604868736005429,323.403106692152903],"luv":[32.368092831934419,34.4105334223914952,-25.55262265656037],"rgb":[0.466666666666666674,0.2,0.4],"xyz":[0.111893715938986671,0.0724941433792052,0.1338075796901671],"hpluv":[323.403106692152903,168.027093700417197,32.368092831934419],"hsluv":[323.403106692152903,60.2559031079253913,32.368092831934419]},"#773377":{"lch":[33.18286532501061,49.0630735877418189,307.715012949244226],"luv":[33.18286532501061,30.0135669321659,-38.8119954380674201],"rgb":[0.466666666666666674,0.2,0.466666666666666674],"xyz":[0.12120772895918859,0.0762197485872860153,0.182861381596565],"hpluv":[307.715012949244226,187.620458725202155,33.18286532501061],"hsluv":[307.715012949244226,64.9109644958811458,33.18286532501061]},"#773388":{"lch":[34.1232577260479,58.0074356166469371,296.464975996700218],"luv":[34.1232577260479,25.8510525803809479,-51.9286594021626868],"rgb":[0.466666666666666674,0.2,0.533333333333333326],"xyz":[0.132348146061132432,0.0806759154280636132,0.241534245000137177],"hpluv":[296.464975996700218,215.711106662248483,34.1232577260479],"hsluv":[296.464975996700218,69.2226633917654226,34.1232577260479]},"#773399":{"lch":[35.1823459678372572,68.3160830057283,288.793689920994325],"luv":[35.1823459678372572,22.0088074868374761,-64.6737936899706369],"rgb":[0.466666666666666674,0.2,0.6],"xyz":[0.145405110170205132,0.0858987010716927707,0.310300922641255084],"hpluv":[288.793689920994325,246.398176299420243,35.1823459678372572],"hsluv":[288.793689920994325,73.0971646513407,35.1823459678372572]},"#7733aa":{"lch":[36.3517007299652,79.1457370086552316,283.529620316849901],"luv":[36.3517007299652,18.5159885211015585,-76.9493720294691741],"rgb":[0.466666666666666674,0.2,0.66666666666666663],"xyz":[0.160462803135457688,0.0919217782577938791,0.389604772258253684],"hpluv":[283.529620316849901,276.275338575971432,36.3517007299652],"hsluv":[283.529620316849901,76.5077273075914093,36.3517007299652]},"#7733bb":{"lch":[37.6219984216960484,90.0609255961329183,279.823655256592],"luv":[37.6219984216960484,15.3658639022925581,-88.7404110074345596],"rgb":[0.466666666666666674,0.2,0.733333333333333282],"xyz":[0.177600395242794307,0.0987768151007286377,0.479862757356895431],"hpluv":[279.823655256592,303.762299466947354,37.6219984216960484],"hsluv":[279.823655256592,79.4699002038008615,37.6219984216960484]},"#7733cc":{"lch":[38.9835424310364687,100.85881095677091,277.137789072490136],"luv":[38.9835424310364687,12.5323059717609908,-100.077175492935524],"rgb":[0.466666666666666674,0.2,0.8],"xyz":[0.196892770686516061,0.106493765278217439,0.581469268027165587],"hpluv":[277.137789072490136,328.300745951509327,38.9835424310364687],"hsluv":[277.137789072490136,82.0218198813884,38.9835424310364687]},"#7733dd":{"lch":[40.4266769703902469,111.457640409912926,275.137669231249674],"luv":[40.4266769703902469,9.98093438608736,-111.009848907770674],"rgb":[0.466666666666666674,0.2,0.866666666666666696],"xyz":[0.218411096237149605,0.115101095498470973,0.694799115927171584],"hpluv":[275.137669231249674,349.849394775278881,40.4266769703902469],"hsluv":[275.137669231249674,84.2108753320266459,40.4266769703902469]},"#7733ee":{"lch":[41.9420918590451066,121.83559331992231,273.612094072304103],"luv":[41.9420918590451066,7.67578650940870766,-121.593561100411392],"rgb":[0.466666666666666674,0.2,0.933333333333333348],"xyz":[0.242223276503324342,0.12462596760494099,0.820209931995694808],"hpluv":[273.612094072304103,368.606867281158145,41.9420918590451066],"hsluv":[273.612094072304103,91.3228806729277665,41.9420918590451066]},"#7733ff":{"lch":[43.521028110395612,131.998699032970592,272.424037139620168],"luv":[43.521028110395612,5.58285979872954208,-131.88058319125102],"rgb":[0.466666666666666674,0.2,1],"xyz":[0.268394324913155735,0.135094386968873714,0.958044120287476653],"hpluv":[272.424037139620168,384.866252510120546,43.521028110395612],"hsluv":[272.424037139620168,99.9999999999993605,43.521028110395612]},"#eebb00":{"lch":[78.2979307719844115,92.4506686575273307,61.8965912674010781],"luv":[78.2979307719844115,43.5502151824584587,81.5506277890334275],"rgb":[0.933333333333333348,0.733333333333333282,0],"xyz":[0.530286541787721277,0.537195691732810121,0.0757595260297813378],"hpluv":[61.8965912674010781,173.778692590363192,78.2979307719844115],"hsluv":[61.8965912674010781,100.000000000002373,78.2979307719844115]},"#eebb11":{"lch":[78.3216028454340858,91.4822746680663528,61.6861071172261504],"luv":[78.3216028454340858,43.3901974999079059,80.5375523551748],"rgb":[0.933333333333333348,0.733333333333333282,0.0666666666666666657],"xyz":[0.531298207287358437,0.537600357932665,0.0810876309945369744],"hpluv":[61.6861071172261504,172.182825477748111,78.3216028454340858],"hsluv":[61.6861071172261504,98.7812238781787642,78.3216028454340858]},"#eebb22":{"lch":[78.3654531575016335,89.702527227679937,61.2866058237147371],"luv":[78.3654531575016335,43.0956539167563477,78.672155204492924],"rgb":[0.933333333333333348,0.733333333333333282,0.133333333333333331],"xyz":[0.533173565425835383,0.53835050118805583,0.090964517190516167],"hpluv":[61.2866058237147371,169.241982225815036,78.3654531575016335],"hsluv":[61.2866058237147371,96.5386826089343,78.3654531575016335]},"#eebb33":{"lch":[78.4375634156200192,86.8156112143301897,60.6012126372659665],"luv":[78.4375634156200192,42.6165086308843897,75.6358614853528906],"rgb":[0.933333333333333348,0.733333333333333282,0.2],"xyz":[0.5362613161582932,0.539585601481039,0.107226671048127303],"hpluv":[60.6012126372659665,164.44952499458185,78.4375634156200192],"hsluv":[60.6012126372659665,92.89304460263088,78.4375634156200192]},"#eebb44":{"lch":[78.5414800230656,82.7424491039972878,59.5464137785053],"luv":[78.5414800230656,41.9372005918819397,71.3273025583039839],"rgb":[0.933333333333333348,0.733333333333333282,0.266666666666666663],"xyz":[0.540719311402512059,0.541368799578726523,0.130705446001013942],"hpluv":[59.5464137785053,157.640041580932575,78.5414800230656],"hsluv":[59.5464137785053,87.729612164687,78.5414800230656]},"#eebb55":{"lch":[78.6801087960333,77.4695312482544,58.0014729567720551],"luv":[78.6801087960333,41.0509080282697809,65.6989438414256455],"rgb":[0.933333333333333348,0.733333333333333282,0.333333333333333315],"xyz":[0.546681725441874,0.543753765194471272,0.162107493274987857],"hpluv":[58.0014729567720551,148.738759066450825,78.6801087960333],"hsluv":[58.0014729567720551,81.0022494643358613,78.6801087960333]},"#eebb66":{"lch":[78.8558787138066748,71.0520814803831229,55.7790951769469174],"luv":[78.8558787138066748,39.9586324736418845,58.7512210386423703],"rgb":[0.933333333333333348,0.733333333333333282,0.4],"xyz":[0.55426672121538223,0.546787763503874591,0.202055137682131819],"hpluv":[55.7790951769469174,137.768430134850121,78.8558787138066748],"hsluv":[55.7790951769469174,72.7264864885570574,78.8558787138066748]},"#eebb77":{"lch":[79.0708286262536,63.6259938562226566,52.5733668905169],"luv":[79.0708286262536,38.6683825737350801,50.5274507898760348],"rgb":[0.933333333333333348,0.733333333333333282,0.466666666666666674],"xyz":[0.56358073423558408,0.550513368711955442,0.251108939588529756],"hpluv":[52.5733668905169,124.876553308513152,79.0708286262536],"hsluv":[52.5733668905169,64.3532422469102841,79.0708286262536]},"#eebb88":{"lch":[79.3266586201773833,55.4370708593257149,47.8613800964459557],"luv":[79.3266586201773833,37.1942049853437169,41.1079060640423961],"rgb":[0.933333333333333348,0.733333333333333282,0.533333333333333326],"xyz":[0.574721151337528,0.554969535552733,0.309781802992101896],"hpluv":[47.8613800964459557,110.403075040931697,79.3266586201773833],"hsluv":[47.8613800964459557,64.6428486235092379,79.3266586201773833]},"#eebb99":{"lch":[79.6247632766216071,46.9114913521919519,40.7190885070752131],"luv":[79.6247632766216071,35.5550187983100727,30.6027557441907163],"rgb":[0.933333333333333348,0.733333333333333282,0.6],"xyz":[0.587778115446600635,0.560192321196362197,0.378548480633219775],"hpluv":[40.7190885070752131,95.0436922052712845,79.6247632766216071],"hsluv":[40.7190885070752131,64.94797236425741,79.6247632766216071]},"#eebbaa":{"lch":[79.9662551563314,38.821829319770238,29.5464132636418633],"luv":[79.9662551563314,33.7733033676501,19.1441482278540249],"rgb":[0.933333333333333348,0.733333333333333282,0.66666666666666663],"xyz":[0.602835808411853247,0.566215398382463264,0.457852330250218431],"hpluv":[29.5464132636418633,80.2381481795300573,79.9662551563314],"hsluv":[29.5464132636418633,65.2570717669902081,79.9662551563314]},"#eebbbb":{"lch":[80.3519829843595,32.6073830473385868,12.1770506300627979],"luv":[80.3519829843595,31.8737319395561,6.87798236703069765],"rgb":[0.933333333333333348,0.733333333333333282,0.733333333333333282],"xyz":[0.61997340051918981,0.573070435225398,0.548110315348860122],"hpluv":[12.1770506300627979,68.9527679352530498,80.3519829843595],"hsluv":[12.1770506300627979,65.5572779496269646,80.3519829843595]},"#eebbcc":{"lch":[80.7825470949933,30.4869713003172755,348.56539147946927],"luv":[80.7825470949933,29.8818538307637169,-6.04402437976891349],"rgb":[0.933333333333333348,0.733333333333333282,0.8],"xyz":[0.639265775962911564,0.58078738540288688,0.649716826019130278],"hpluv":[348.56539147946927,66.1649916626687542,80.7825470949933],"hsluv":[348.56539147946927,65.8346704867411,80.7825470949933]},"#eebbdd":{"lch":[81.2583136554081165,33.9595526191752555,325.014354592586812],"luv":[81.2583136554081165,27.8229160969035512,-19.4714291709468021],"rgb":[0.933333333333333348,0.733333333333333282,0.866666666666666696],"xyz":[0.660784101513545163,0.589394715623140386,0.763046673919136276],"hpluv":[325.014354592586812,75.8902298772919721,81.2583136554081165],"hsluv":[325.014354592586812,66.0744631525984119,81.2583136554081165]},"#eebbee":{"lch":[81.7794285687783429,42.0458499431423576,307.715012949247921],"luv":[81.7794285687783429,25.7208902583653902,-33.2609275540891716],"rgb":[0.933333333333333348,0.733333333333333282,0.933333333333333348],"xyz":[0.684596281779719873,0.598919587729610403,0.888457489987659499],"hpluv":[307.715012949247921,97.0917602325266245,81.7794285687783429],"hsluv":[307.715012949247921,66.2610602343042103,81.7794285687783429]},"#eebbff":{"lch":[82.3458315671937697,52.842459086223478,296.523687653639684],"luv":[82.3458315671937697,23.5977388768935938,-47.2807804734349446],"rgb":[0.933333333333333348,0.733333333333333282,1],"xyz":[0.710767330189551294,0.609388007093543127,1.02629167827944134],"hpluv":[296.523687653639684,126.563624284615543,82.3458315671937697],"hsluv":[296.523687653639684,99.9999999999958504,82.3458315671937697]},"#774400":{"lch":[34.1007355557283631,52.2824067620925845,38.9690248280103901],"luv":[34.1007355557283631,40.6488429776156863,32.8804139483986475],"rgb":[0.466666666666666674,0.266666666666666663,0],"xyz":[0.0967461069942917862,0.0805672125740730105,0.0104561581988052085],"hpluv":[38.9690248280103901,194.549962435525771,34.1007355557283631],"hsluv":[38.9690248280103901,100.000000000002302,34.1007355557283631]},"#774411":{"lch":[34.1844760931178726,49.9480603042207,37.0032460066389604],"luv":[34.1844760931178726,39.8885915773263164,30.0617529450848728],"rgb":[0.466666666666666674,0.266666666666666663,0.0666666666666666657],"xyz":[0.0977577724939289,0.0809718787739278634,0.0157842631635608383],"hpluv":[37.0032460066389604,185.408237524396696,34.1844760931178726],"hsluv":[37.0032460066389604,92.0774266797174477,34.1844760931178726]},"#774422":{"lch":[34.3389737161705639,45.9687551907429608,33.0232295817012798],"luv":[34.3389737161705639,38.542488289151045,25.0520069109664867],"rgb":[0.466666666666666674,0.266666666666666663,0.133333333333333331],"xyz":[0.0996331306324059335,0.0817220220293186778,0.0256611493595400378],"hpluv":[33.0232295817012798,169.869245826721482,34.3389737161705639],"hsluv":[33.0232295817012798,78.0803941927279794,34.3389737161705639]},"#774433":{"lch":[34.5913049894652787,40.4066166426811861,25.4401077009201266],"luv":[34.5913049894652787,36.4885814660887746,17.357364174931714],"rgb":[0.466666666666666674,0.266666666666666663,0.2],"xyz":[0.102720881364863667,0.0829571223223017906,0.041923303217151181],"hpluv":[25.4401077009201266,148.226163260119392,34.5913049894652787],"hsluv":[25.4401077009201266,56.8050953227402715,34.5913049894652787]},"#774444":{"lch":[34.9512320153617324,34.6101233100924119,12.1770506300620909],"luv":[34.9512320153617324,33.8314114683579277,7.30042694631360689],"rgb":[0.466666666666666674,0.266666666666666663,0.266666666666666663],"xyz":[0.107178876609082541,0.0847403204199893706,0.0654020781700378195],"hpluv":[12.1770506300620909,125.655060642768362,34.9512320153617324],"hsluv":[12.1770506300620909,29.4448754689639038,34.9512320153617324]},"#774455":{"lch":[35.4248138391838907,31.0799263948782318,351.580242092888511],"luv":[35.4248138391838907,30.7449438027498871,-4.55085214842230634],"rgb":[0.466666666666666674,0.266666666666666663,0.333333333333333315],"xyz":[0.11314129064844454,0.0871252860357342,0.0968041254440117349],"hpluv":[351.580242092888511,111.329877567225012,35.4248138391838907],"hsluv":[351.580242092888511,35.0525071981411855,35.4248138391838907]},"#774466":{"lch":[36.0149447056398699,32.55773059028094,327.386935336661793],"luv":[36.0149447056398699,27.4243377055297302,-17.5474078599198116],"rgb":[0.466666666666666674,0.266666666666666663,0.4],"xyz":[0.120726286421952711,0.090159284345137522,0.136751769851155697],"hpluv":[327.386935336661793,114.712488009680612,36.0149447056398699],"hsluv":[327.386935336661793,41.0162201785438469,36.0149447056398699]},"#774477":{"lch":[36.7217587051522898,39.3078830273429531,307.715012949244965],"luv":[36.7217587051522898,24.0459818745983789,-31.0950224919964064],"rgb":[0.466666666666666674,0.266666666666666663,0.466666666666666674],"xyz":[0.130040299442154617,0.0938848895532183314,0.185805571757553606],"hpluv":[307.715012949244965,135.82994003022975,36.7217587051522898],"hsluv":[307.715012949244965,46.9930223744603381,36.7217587051522898]},"#774488":{"lch":[37.5430301686231331,49.3077922843884906,294.880307130505798],"luv":[37.5430301686231331,20.7449732069104158,-44.731470651041306],"rgb":[0.466666666666666674,0.266666666666666663,0.533333333333333326],"xyz":[0.141180716544098472,0.0983410563939959292,0.244478435161125773],"hpluv":[294.880307130505798,166.657768282509579,37.5430301686231331],"hsluv":[294.880307130505798,52.7229750286883814,37.5430301686231331]},"#774499":{"lch":[38.4745988052595678,60.7540316024919775,286.849160899925266],"luv":[38.4745988052595678,17.609743748149274,-58.1459309073396042],"rgb":[0.466666666666666674,0.266666666666666663,0.6],"xyz":[0.154237680653171172,0.103563842037625087,0.313245112802243653],"hpluv":[286.849160899925266,200.373520820200838,38.4745988052595678],"hsluv":[286.849160899925266,58.0391908614757739,38.4745988052595678]},"#7744aa":{"lch":[39.5108096650206306,72.6607854160185695,281.662296555210446],"luv":[39.5108096650206306,14.6878600390207232,-71.1607792589909423],"rgb":[0.466666666666666674,0.266666666666666663,0.66666666666666663],"xyz":[0.169295373618423728,0.109586919223726181,0.392548962419242253],"hpluv":[281.662296555210446,233.358425064810547,39.5108096650206306],"hsluv":[281.662296555210446,62.855979622580108,39.5108096650206306]},"#7744bb":{"lch":[40.6449442050895,84.5532389367896684,278.156646558388104],"luv":[40.6449442050895,11.9964108827533504,-83.6978873128468],"rgb":[0.466666666666666674,0.266666666666666663,0.733333333333333282],"xyz":[0.186432965725760347,0.11644195606666094,0.482806947517884],"hpluv":[278.156646558388104,263.975148792079324,40.6449442050895],"hsluv":[278.156646558388104,67.1480450168623832,40.6449442050895]},"#7744cc":{"lch":[41.8696179576200223,96.2178725735773099,275.685728840067554],"luv":[41.8696179576200223,9.53248740063005151,-95.7445073439828747],"rgb":[0.466666666666666674,0.266666666666666663,0.8],"xyz":[0.205725341169482101,0.124158906244149742,0.584413458188154156],"hpluv":[275.685728840067554,291.605746800226,41.8696179576200223],"hsluv":[275.685728840067554,71.7563947172966721,41.8696179576200223]},"#7744dd":{"lch":[43.1771261833787037,107.572507589609089,273.881356516641858],"luv":[43.1771261833787037,7.28165300546471084,-107.325774717094461],"rgb":[0.466666666666666674,0.266666666666666663,0.866666666666666696],"xyz":[0.227243666720115645,0.132766236464403276,0.697743306088160153],"hpluv":[273.881356516641858,316.145413845169799,43.1771261833787037],"hsluv":[273.881356516641858,81.1040313116107683,43.1771261833787037]},"#7744ee":{"lch":[44.5597272061305958,118.600491111934247,272.524492751992966],"luv":[44.5597272061305958,5.22393127379498168,-118.485387428318177],"rgb":[0.466666666666666674,0.266666666666666663,0.933333333333333348],"xyz":[0.251055846986290354,0.14229110857087332,0.823154122156683377],"hpluv":[272.524492751992966,337.740615485066769,44.5597272061305958],"hsluv":[272.524492751992966,90.4775463334620866,44.5597272061305958]},"#7744ff":{"lch":[46.0098610845945188,129.316457315512423,271.478956563127554],"luv":[46.0098610845945188,3.33763127257498882,-129.273378350389976],"rgb":[0.466666666666666674,0.266666666666666663,1],"xyz":[0.277226895396121775,0.152759527934806016,0.960988310448465222],"hpluv":[271.478956563127554,356.649979093308843,46.0098610845945188],"hsluv":[271.478956563127554,99.9999999999992752,46.0098610845945188]},"#eecc00":{"lch":[82.5742071813858161,93.0890420253441278,70.6743105766144737],"luv":[82.5742071813858161,30.8066573410433797,87.8437226480516529],"rgb":[0.933333333333333348,0.8,0],"xyz":[0.568510285097338142,0.613643178352045071,0.088500773799653279],"hpluv":[70.6743105766144737,226.330948640265689,82.5742071813858161],"hsluv":[70.6743105766144737,100.000000000002331,82.5742071813858161]},"#eecc11":{"lch":[82.5958706312260773,92.1609271203023,70.5494354113464226],"luv":[82.5958706312260773,30.6889817522442812,86.9012248859824297],"rgb":[0.933333333333333348,0.8,0.0666666666666666657],"xyz":[0.569521950596975302,0.6140478445519,0.0938288787644089156],"hpluv":[70.5494354113464226,224.395635781555484,82.5958706312260773],"hsluv":[70.5494354113464226,98.9293851282895389,82.5958706312260773]},"#eecc22":{"lch":[82.636003730849751,90.4517890224530277,70.3125751850760849],"luv":[82.636003730849751,30.4721781878481224,85.1643851257694848],"rgb":[0.933333333333333348,0.8,0.133333333333333331],"xyz":[0.571397308735452247,0.61479798780729078,0.103705764960388108],"hpluv":[70.3125751850760849,220.820363432361461,82.636003730849751],"hsluv":[70.3125751850760849,96.9576791715233668,82.636003730849751]},"#eecc33":{"lch":[82.7020112487531,87.6695564091762236,69.9066450473675332],"luv":[82.7020112487531,30.1189443150749909,82.3334701948554084],"rgb":[0.933333333333333348,0.8,0.2],"xyz":[0.574485059467910064,0.616033088100273907,0.119967918817999258],"hpluv":[69.9066450473675332,214.968262161852493,82.7020112487531],"hsluv":[69.9066450473675332,93.7473974454290726,82.7020112487531]},"#eecc44":{"lch":[82.7971553193909102,83.7217279628800242,69.2828434677537786],"luv":[82.7971553193909102,29.6169744667019792,78.3081257375581],"rgb":[0.933333333333333348,0.8,0.266666666666666663],"xyz":[0.578943054712128924,0.617816286197961473,0.143446693770885897],"hpluv":[69.2828434677537786,206.594355258371763,82.7971553193909102],"hsluv":[69.2828434677537786,89.1900904304584685,82.7971553193909102]},"#eecc55":{"lch":[82.9241214704336471,78.5673404382155098,68.3706518767947387],"luv":[82.9241214704336471,28.9599810639926183,73.0352413585910085],"rgb":[0.933333333333333348,0.8,0.333333333333333315],"xyz":[0.584905468751490853,0.620201251813706222,0.174848741044859812],"hpluv":[68.3706518767947387,195.532369916851508,82.9241214704336471],"hsluv":[68.3706518767947387,83.2339277722755497,82.9241214704336471]},"#eecc66":{"lch":[83.0851700146488241,72.2150018940459688,67.0599726095305186],"luv":[83.0851700146488241,28.1470538355007811,66.503758231685552],"rgb":[0.933333333333333348,0.8,0.4],"xyz":[0.592490464524999094,0.623235250123109541,0.214796385452003746],"hpluv":[67.0599726095305186,181.688085793908328,83.0851700146488241],"hsluv":[67.0599726095305186,75.8779818086204898,83.0851700146488241]},"#eecc77":{"lch":[83.2822165713090925,64.7250307453925586,65.1677162202921778],"luv":[83.2822165713090925,27.1821511319325673,58.740618526133936],"rgb":[0.933333333333333348,0.8,0.466666666666666674],"xyz":[0.601804477545200944,0.626960855331190392,0.263850187358401655],"hpluv":[65.1677162202921778,165.044758034407693,83.2822165713090925],"hsluv":[65.1677162202921778,67.1675472191497533,83.2822165713090925]},"#eecc88":{"lch":[83.5168798492942699,56.2182636624862511,62.3679934299132839],"luv":[83.5168798492942699,26.0735255024375405,49.8062690541919793],"rgb":[0.933333333333333348,0.8,0.533333333333333326],"xyz":[0.612944894647144856,0.631417022171967934,0.322523050761973851],"hpluv":[62.3679934299132839,145.689263900370548,83.5168798492942699],"hsluv":[62.3679934299132839,57.1887031148042198,83.5168798492942699]},"#eecc99":{"lch":[83.79051243806407,46.9027423702446598,58.0311593919332083],"luv":[83.79051243806407,24.8330316313984234,39.7892923013655633],"rgb":[0.933333333333333348,0.8,0.6],"xyz":[0.6260018587562175,0.636639807815597147,0.39128972840309173],"hpluv":[58.0311593919332083,123.89218615802821,83.79051243806407],"hsluv":[58.0311593919332083,56.9799526918745158,83.79051243806407]},"#eeccaa":{"lch":[84.1042222244633,37.1556922719042646,50.8162292091241454],"luv":[84.1042222244633,23.475329457535171,28.8002495660129298],"rgb":[0.933333333333333348,0.8,0.66666666666666663],"xyz":[0.641059551721470111,0.642662885001698214,0.470593578020090331],"hpluv":[50.8162292091241454,100.353156070069275,84.1042222244633],"hsluv":[50.8162292091241454,57.1375361174420533,84.1042222244633]},"#eeccbb":{"lch":[84.4588885299527,27.7950211383377486,37.6158086991229084],"luv":[84.4588885299527,22.0170273242058485,16.9650731765535063],"rgb":[0.933333333333333348,0.8,0.733333333333333282],"xyz":[0.658197143828806674,0.649517921844633,0.560851563118732077],"hpluv":[37.6158086991229084,77.0182985337263517,84.4588885299527],"hsluv":[37.6158086991229084,57.2612530554736736,84.4588885299527]},"#eecccc":{"lch":[84.8551753311588897,20.9471233587290264,12.1770506300631585],"luv":[84.8551753311588897,20.4758227261490333,4.41844550641173317],"rgb":[0.933333333333333348,0.8,0.8],"xyz":[0.677489519272528429,0.65723487202212183,0.662458073789002233],"hpluv":[12.1770506300631585,59.764130158742411,84.8551753311588897],"hsluv":[12.1770506300631585,57.3329985994000637,84.8551753311588897]},"#eeccdd":{"lch":[85.2935429882433596,20.7797326136980232,335.241604291037675],"luv":[85.2935429882433596,18.8696973425293919,-8.70240252448279],"rgb":[0.933333333333333348,0.8,0.866666666666666696],"xyz":[0.699007844823162,0.665842202242375336,0.775787921689008231],"hpluv":[335.241604291037675,61.2821093808529582,85.2935429882433596],"hsluv":[335.241604291037675,57.3323512744098664,85.2935429882433596]},"#eeccee":{"lch":[85.7742593547863805,28.14328338963319,307.715012949251047],"luv":[85.7742593547863805,17.2162128855465397,-22.2631177921859056],"rgb":[0.933333333333333348,0.8,0.933333333333333348],"xyz":[0.722820025089336737,0.675367074348845353,0.901198737757531454],"hpluv":[307.715012949251047,86.153290074940827,85.7742593547863805],"hsluv":[307.715012949251047,57.2362127773837557,85.7742593547863805]},"#eeccff":{"lch":[86.2974107975625344,39.333162863939684,293.258584701896098],"luv":[86.2974107975625344,15.5319389668875889,-36.1366375415599919],"rgb":[0.933333333333333348,0.8,1],"xyz":[0.748991073499168158,0.685835493712778077,1.03903292604931341],"hpluv":[293.258584701896098,125.558261528980708,86.2974107975625344],"hsluv":[293.258584701896098,99.9999999999940314,86.2974107975625344]},"#775500":{"lch":[38.5848153490983421,48.2339285723334328,54.8056311564330656],"luv":[38.5848153490983421,27.7997213245256276,39.4168410682499868],"rgb":[0.466666666666666674,0.333333333333333315,0],"xyz":[0.108559363708637752,0.104193726002765275,0.0143939104369204193],"hpluv":[54.8056311564330656,158.626424871442595,38.5848153490983421],"hsluv":[54.8056311564330656,100.000000000002302,38.5848153490983421]},"#775511":{"lch":[38.6553893217116595,45.9150245993572952,53.4685955296553956],"luv":[38.6553893217116595,27.3315290852913257,36.8941323494598521],"rgb":[0.466666666666666674,0.333333333333333315,0.0666666666666666657],"xyz":[0.10957102920827487,0.104598392202620127,0.0197220154016760491],"hpluv":[53.4685955296553956,150.724584795248319,38.6553893217116595],"hsluv":[53.4685955296553956,93.8009130268131344,38.6553893217116595]},"#775522":{"lch":[38.7857346943923531,41.8305053308362176,50.7011784026830412],"luv":[38.7857346943923531,26.4939762066725,32.3706719268134577],"rgb":[0.466666666666666674,0.333333333333333315,0.133333333333333331],"xyz":[0.111446387346751899,0.105348535458010942,0.0295989015976552486],"hpluv":[50.7011784026830412,136.854920013655288,38.7857346943923531],"hsluv":[50.7011784026830412,82.7342982429400138,38.7857346943923531]},"#775533":{"lch":[38.9990050188249739,35.7224202133018096,45.1472123185964946],"luv":[38.9990050188249739,25.1945818654867857,25.3243825298663161],"rgb":[0.466666666666666674,0.333333333333333315,0.2],"xyz":[0.114534138079209633,0.106583635750994055,0.0458610554552663918],"hpluv":[45.1472123185964946,116.232257903435652,38.9990050188249739],"hsluv":[45.1472123185964946,65.6272728324870656,38.9990050188249739]},"#775544":{"lch":[39.3040305977305735,28.372964966311546,34.1730058033032336],"luv":[39.3040305977305735,23.4742392428959334,15.9369141601135258],"rgb":[0.466666666666666674,0.333333333333333315,0.266666666666666663],"xyz":[0.118992133323428506,0.108366833848681635,0.0693398304081530303],"hpluv":[34.1730058033032336,91.6024225041024,39.3040305977305735],"hsluv":[34.1730058033032336,43.1049791856067799,39.3040305977305735]},"#775555":{"lch":[39.7068052905653701,21.9117916496410494,12.1770506300624941],"luv":[39.7068052905653701,21.4187864245998618,4.62192615633957704],"rgb":[0.466666666666666674,0.333333333333333315,0.333333333333333315],"xyz":[0.124954547362790505,0.110751799464426468,0.100741877682126946],"hpluv":[12.1770506300624941,70.0248633547080601,39.7068052905653701],"hsluv":[12.1770506300624941,16.4089959502104463,39.7068052905653701]},"#775566":{"lch":[40.21091767922141,20.7753835118276839,337.09176723456028],"luv":[40.21091767922141,19.1368182791551824,-8.08694912894311],"rgb":[0.466666666666666674,0.333333333333333315,0.4],"xyz":[0.132539543136298676,0.113785797773829786,0.140689522089270908],"hpluv":[337.09176723456028,65.5608222190156482,40.21091767922141],"hsluv":[337.09176723456028,22.8015335286909036,40.21091767922141]},"#775577":{"lch":[40.8178321801082404,27.3616881241227183,307.715012949246557],"luv":[40.8178321801082404,16.7380842217685313,-21.6448264854847388],"rgb":[0.466666666666666674,0.333333333333333315,0.466666666666666674],"xyz":[0.141853556156500582,0.117511402981910595,0.189743323995668817],"hpluv":[307.715012949246557,85.0613515767839,40.8178321801082404],"hsluv":[307.715012949246557,29.4286369924042717,40.8178321801082404]},"#775588":{"lch":[41.5271394874135922,38.3484586217177892,291.922773984013077],"luv":[41.5271394874135922,14.317648223710199,-35.5754020076188269],"rgb":[0.466666666666666674,0.333333333333333315,0.533333333333333326],"xyz":[0.152993973258444438,0.121967569822688193,0.248416187399240984],"hpluv":[291.922773984013077,117.180466459805771,41.5271394874135922],"hsluv":[291.922773984013077,36.0000576829853429,41.5271394874135922]},"#775599":{"lch":[42.336815252734,50.9328741768069335,283.566916489070877],"luv":[42.336815252734,11.9478768110398388,-49.5116744982298442],"rgb":[0.466666666666666674,0.333333333333333315,0.6],"xyz":[0.166050937367517137,0.127190355466317351,0.317182865040358863],"hpluv":[283.566916489070877,152.657914615048412,42.336815252734],"hsluv":[283.566916489070877,42.2975255710275704,42.336815252734]},"#7755aa":{"lch":[43.2434937800222059,63.9392804809027098,278.705184193400783],"luv":[43.2434937800222059,9.67722671121172517,-63.202712533524668],"rgb":[0.466666666666666674,0.333333333333333315,0.66666666666666663],"xyz":[0.181108630332769693,0.133213432652418445,0.396486714657357464],"hpluv":[278.705184193400783,187.623095354238075,43.2434937800222059],"hsluv":[278.705184193400783,48.1780536314011272,43.2434937800222059]},"#7755bb":{"lch":[44.2427493107278096,76.8690732738289171,275.624120681329657],"luv":[44.2427493107278096,7.53331271169703509,-76.4990432983646116],"rgb":[0.466666666666666674,0.333333333333333315,0.733333333333333282],"xyz":[0.198246222440106312,0.140068469495353204,0.486744699755999211],"hpluv":[275.624120681329657,220.469676556121556,44.2427493107278096],"hsluv":[275.624120681329657,58.1137757976744496,44.2427493107278096]},"#7755cc":{"lch":[45.3293721892173949,89.4999308488430785,273.541003165926895],"luv":[45.3293721892173949,5.52776894932058127,-89.3290624175056536],"rgb":[0.466666666666666674,0.333333333333333315,0.8],"xyz":[0.217538597883828067,0.147785419672842,0.588351210426269366],"hpluv":[273.541003165926895,250.543028147628775,45.3293721892173949],"hsluv":[273.541003165926895,68.560007412736141,45.3293721892173949]},"#7755dd":{"lch":[46.4976270234735622,101.740884988783861,272.062259876532949],"luv":[46.4976270234735622,3.66119191329505167,-101.674988822595736],"rgb":[0.466666666666666674,0.333333333333333315,0.866666666666666696],"xyz":[0.23905692343446161,0.15639274989309554,0.701681058326275364],"hpluv":[272.062259876532949,277.654072578046794,46.4976270234735622],"hsluv":[272.062259876532949,78.9623412233913911,46.4976270234735622]},"#7755ee":{"lch":[47.7414825998049253,113.569026574645434,270.972372145675877],"luv":[47.7414825998049253,1.92729827623402139,-113.552672000560818],"rgb":[0.466666666666666674,0.333333333333333315,0.933333333333333348],"xyz":[0.26286910370063632,0.165917621999565584,0.827091874394798587],"hpluv":[270.972372145675877,301.858443342198598,47.7414825998049253],"hsluv":[270.972372145675877,89.4067229175139175,47.7414825998049253]},"#7755ff":{"lch":[49.0548071408334749,124.996939079083958,270.144864217432826],"luv":[49.0548071408334749,0.31603661949764611,-124.996539552082652],"rgb":[0.466666666666666674,0.333333333333333315,1],"xyz":[0.289040152110467741,0.17638604136349828,0.964926062686580432],"hpluv":[270.144864217432826,323.338286172745597,49.0548071408334749],"hsluv":[270.144864217432826,99.9999999999992184,49.0548071408334749]},"#eedd00":{"lch":[86.9434330779808562,96.0018853881048528,78.7633058197047831],"luv":[86.9434330779808562,18.7071720605167293,94.1615829920517],"rgb":[0.933333333333333348,0.866666666666666696,0],"xyz":[0.611144275644513346,0.69891115944639659,0.102712103982044597],"hpluv":[78.7633058197047831,323.365375109368927,86.9434330779808562],"hsluv":[78.7633058197047831,100.000000000002331,86.9434330779808562]},"#eedd11":{"lch":[86.9632971622836,95.1251800329902153,78.7103442402005555],"luv":[86.9632971622836,18.6225708681111755,93.2845095960255293],"rgb":[0.933333333333333348,0.866666666666666696,0.0666666666666666657],"xyz":[0.612155941144150506,0.699315825646251499,0.108040208946800234],"hpluv":[78.7103442402005555,320.953864246165836,86.9632971622836],"hsluv":[78.7103442402005555,99.0572185708442134,86.9632971622836]},"#eedd22":{"lch":[87.0000996195567,93.508678235103929,78.6100630695382421],"luv":[87.0000996195567,18.466577094457584,91.6671066178629559],"rgb":[0.933333333333333348,0.866666666666666696,0.133333333333333331],"xyz":[0.614031299282627452,0.700065968901642299,0.117917095142779427],"hpluv":[78.6100630695382421,316.490280961531141,87.0000996195567],"hsluv":[78.6100630695382421,97.3195837272491104,87.0000996195567]},"#eedd33":{"lch":[87.0606371109171704,90.8714304533391157,78.438725785200063],"luv":[87.0606371109171704,18.2120693177914781,89.0277339024194561],"rgb":[0.933333333333333348,0.866666666666666696,0.2],"xyz":[0.617119050015085269,0.701301069194625426,0.134179249000390577],"hpluv":[78.438725785200063,309.159510866930361,87.0606371109171704],"hsluv":[78.438725785200063,94.4866487647953335,87.0606371109171704]},"#eedd44":{"lch":[87.1479139339873399,87.1163282896156375,78.1766823729436737],"luv":[87.1479139339873399,17.8496481580416315,85.2680755927926839],"rgb":[0.933333333333333348,0.866666666666666696,0.266666666666666663],"xyz":[0.621577045259304128,0.703084267292313,0.157658023953277215],"hpluv":[78.1766823729436737,298.614243514229941,87.1479139339873399],"hsluv":[78.1766823729436737,90.4569971269957449,87.1479139339873399]},"#eedd55":{"lch":[87.2644132886328,82.1887294441124823,77.7961103956051119],"luv":[87.2644132886328,17.3739699699556027,80.3313912186301],"rgb":[0.933333333333333348,0.866666666666666696,0.333333333333333315],"xyz":[0.627539459298666058,0.705469232908057742,0.189060071227251103],"hpluv":[77.7961103956051119,284.577035202400168,87.2644132886328],"hsluv":[77.7961103956051119,85.1762064326895114,87.2644132886328]},"#eedd66":{"lch":[87.4122373516825775,76.0722975624531,77.2543738936701],"luv":[87.4122373516825775,16.7832968217641607,74.1978126646801428],"rgb":[0.933333333333333348,0.866666666666666696,0.4],"xyz":[0.635124455072174299,0.70850323121746106,0.229007715634395093],"hpluv":[77.2543738936701,266.820521177772889,87.4122373516825775],"hsluv":[77.2543738936701,78.6319742502837187,87.4122373516825775]},"#eedd77":{"lch":[87.5931821049200323,68.7867162946957,76.4818073814204666],"luv":[87.5931821049200323,16.0791769624109904,66.8810317415814524],"rgb":[0.933333333333333348,0.866666666666666696,0.466666666666666674],"xyz":[0.644438468092376149,0.712228836425541911,0.278061517540793],"hpluv":[76.4818073814204666,245.153905791490757,87.5931821049200323],"hsluv":[76.4818073814204666,70.850552214552053,87.5931821049200323]},"#eedd88":{"lch":[87.8087818591101694,60.3863988515096,75.3563176494847],"luv":[87.8087818591101694,15.266108392374667,58.4248500280990655],"rgb":[0.933333333333333348,0.866666666666666696,0.533333333333333326],"xyz":[0.65557888519432006,0.716685003266319454,0.336734380944365141],"hpluv":[75.3563176494847,219.413652035392374,87.8087818591101694],"hsluv":[75.3563176494847,61.8928475378351,87.8087818591101694]},"#eedd99":{"lch":[88.0603378936253165,50.9615259485641658,73.6438422487017164],"luv":[88.0603378936253165,14.3511385044238935,48.8990996914362483],"rgb":[0.933333333333333348,0.866666666666666696,0.6],"xyz":[0.668635849303392704,0.721907788909948667,0.405501058585483076],"hpluv":[73.6438422487017164,189.463858183723431,88.0603378936253165],"hsluv":[73.6438422487017164,51.8496821371243328,88.0603378936253165]},"#eeddaa":{"lch":[88.3489381850503719,40.6474355343677374,70.8361013393810595],"luv":[88.3489381850503719,13.3433963411670824,38.3948927541556],"rgb":[0.933333333333333348,0.866666666666666696,0.66666666666666663],"xyz":[0.683693542268645316,0.727930866096049733,0.484804908202481677],"hpluv":[70.8361013393810595,155.230940371192503,88.3489381850503719],"hsluv":[70.8361013393810595,42.897511243529749,88.3489381850503719]},"#eeddbb":{"lch":[88.6754719765582422,29.6681200622416164,65.6052069824857256],"luv":[88.6754719765582422,12.2535763784239329,27.0193858917206811],"rgb":[0.933333333333333348,0.866666666666666696,0.733333333333333282],"xyz":[0.700831134375981879,0.734785902938984492,0.575062893301123368],"hpluv":[65.6052069824857256,116.881954111652547,88.6754719765582422],"hsluv":[65.6052069824857256,42.5880034653653823,88.6754719765582422]},"#eeddcc":{"lch":[89.0406413623298,18.5684245799280596,53.3136761054906927],"luv":[89.0406413623298,11.093403559257359,14.8903589228712931],"rgb":[0.933333333333333348,0.866666666666666696,0.8],"xyz":[0.720123509819703633,0.742502853116473349,0.676669403971393524],"hpluv":[53.3136761054906927,75.8171941810365837,89.0406413623298],"hsluv":[53.3136761054906927,42.1389745374101,89.0406413623298]},"#eedddd":{"lch":[89.4449712115231677,10.1024117660870978,12.1770506300652031],"luv":[89.4449712115231677,9.87511215198720294,2.13093488339032255],"rgb":[0.933333333333333348,0.866666666666666696,0.866666666666666696],"xyz":[0.741641835370337232,0.751110183336726855,0.789999251871399522],"hpluv":[12.1770506300652031,42.9711785560074802,89.4449712115231677],"hsluv":[12.1770506300652031,41.5103310668104939,89.4449712115231677]},"#eeddee":{"lch":[89.8888182614484919,14.0763196099440542,307.715012949260654],"luv":[89.8888182614484919,8.61096808409750203,-11.1352594229299271],"rgb":[0.933333333333333348,0.866666666666666696,0.933333333333333348],"xyz":[0.765454015636511942,0.760635055443196872,0.915410067939922745],"hpluv":[307.715012949260654,62.7286135322124423,89.8888182614484919],"hsluv":[307.715012949260654,40.6526002298302203,89.8888182614484919]},"#eeddff":{"lch":[90.3723799019863776,25.8444533047225526,286.436741223308786],"luv":[90.3723799019863776,7.31285770395748802,-24.7882609075678033],"rgb":[0.933333333333333348,0.866666666666666696,1],"xyz":[0.791625064046343363,0.771103474807129596,1.05324425623170459],"hpluv":[286.436741223308786,121.429851146909542,90.3723799019863776],"hsluv":[286.436741223308786,99.9999999999912461,90.3723799019863776]},"#776600":{"lch":[43.3967364031710616,48.7618731822316747,71.5665709091534836],"luv":[43.3967364031710616,15.4186312136361749,46.2599836547520695],"rgb":[0.466666666666666674,0.4,0],"xyz":[0.123587421414484214,0.134249841414458615,0.0194032630055357667],"hpluv":[71.5665709091534836,142.581321953300886,43.3967364031710616],"hsluv":[71.5665709091534836,100.000000000002203,43.3967364031710616]},"#776611":{"lch":[43.4563559440565683,46.5521225716425278,71.0105555334865812],"luv":[43.4563559440565683,15.1477793781447385,44.0186880294754204],"rgb":[0.466666666666666674,0.4,0.0666666666666666657],"xyz":[0.124599086914121332,0.134654507614313468,0.0247313679702914],"hpluv":[71.0105555334865812,135.933189968578517,43.4563559440565683],"hsluv":[71.0105555334865812,95.1446041192036,43.4563559440565683]},"#776622":{"lch":[43.5665595032511135,42.5748985848782695,69.8598868578742582],"luv":[43.5665595032511135,14.6592646006394602,39.9715892964128727],"rgb":[0.466666666666666674,0.4,0.133333333333333331],"xyz":[0.126474445052598361,0.135404650869704296,0.0346082541662705925],"hpluv":[69.8598868578742582,124.005139157578384,43.5665595032511135],"hsluv":[69.8598868578742582,86.4059851293991699,43.5665595032511135]},"#776633":{"lch":[43.7471247164395862,36.3538810550032,67.535659471968259],"luv":[43.7471247164395862,13.8911218179866047,33.5952586297408544],"rgb":[0.466666666666666674,0.4,0.2],"xyz":[0.129562195785056095,0.136639751162687395,0.0508704080238817358],"hpluv":[67.535659471968259,105.448545621014873,43.7471247164395862],"hsluv":[67.535659471968259,72.7162107178341,43.7471247164395862]},"#776644":{"lch":[44.0059094002531381,28.0798421405657628,62.7556004259007807],"luv":[44.0059094002531381,12.8545871201011757,24.9647175952547435],"rgb":[0.466666666666666674,0.4,0.266666666666666663],"xyz":[0.134020191029274982,0.138422949260375,0.0743491829767683743],"hpluv":[62.7556004259007807,80.969785387169,44.0059094002531381],"hsluv":[62.7556004259007807,54.3487361937933,44.0059094002531381]},"#776655":{"lch":[44.348573895236818,18.4503377813959695,51.0995937541716287],"luv":[44.348573895236818,11.5862323365157813,14.3587668165439446],"rgb":[0.466666666666666674,0.4,0.333333333333333315],"xyz":[0.139982605068636967,0.140807914876119822,0.10575123025074229],"hpluv":[51.0995937541716287,52.7914984191523473,44.348573895236818],"hsluv":[51.0995937541716287,32.0544530960382303,44.348573895236818]},"#776666":{"lch":[44.7789425039584543,10.3722772339139464,12.177050630063178],"luv":[44.7789425039584543,10.1389057710203723,2.18785849257654696],"rgb":[0.466666666666666674,0.4,0.4],"xyz":[0.147567600842145152,0.143841913185523113,0.145698874657886251],"hpluv":[12.177050630063178,29.3927086392471182,44.7789425039584543],"hsluv":[12.177050630063178,6.88762268030489189,44.7789425039584543]},"#776677":{"lch":[45.2992151274866899,14.0123007519981453,307.715012949251729],"luv":[45.2992151274866899,8.57180555029232849,-11.0846164558105222],"rgb":[0.466666666666666674,0.4,0.466666666666666674],"xyz":[0.156881613862347058,0.147567518393603936,0.194752676564284161],"hpluv":[307.715012949251729,39.2516664249610088,45.2992151274866899],"hsluv":[307.715012949251729,13.5798811229143528,45.2992151274866899]},"#776688":{"lch":[45.9101336093725934,25.9566305949561666,285.511882327844],"luv":[45.9101336093725934,6.94179491604529719,-25.0111606125461954],"rgb":[0.466666666666666674,0.4,0.533333333333333326],"xyz":[0.168022030964290886,0.152023685234381534,0.253425539967856328],"hpluv":[285.511882327844,71.7429261821633304,45.9101336093725934],"hsluv":[285.511882327844,20.4210179876919788,45.9101336093725934]},"#776699":{"lch":[46.6111419677041781,39.5636276789354753,277.694853057332239],"luv":[46.6111419677041781,5.29745753469698322,-39.2073663842078446],"rgb":[0.466666666666666674,0.4,0.6],"xyz":[0.181078995073363613,0.157246470878010691,0.322192217608974207],"hpluv":[277.694853057332239,107.707436484347127,46.6111419677041781],"hsluv":[277.694853057332239,30.3115853005661187,46.6111419677041781]},"#7766aa":{"lch":[47.4005539940279945,53.5010996637438936,273.94010537559177],"luv":[47.4005539940279945,3.67625443841083355,-53.3746458398921959],"rgb":[0.466666666666666674,0.4,0.66666666666666663],"xyz":[0.196136688038616142,0.163269548064111786,0.401496067225972808],"hpluv":[273.94010537559177,143.224929654224553,47.4005539940279945],"hsluv":[273.94010537559177,41.7476492103462178,47.4005539940279945]},"#7766bb":{"lch":[48.2757296522395052,67.3356727079262356,271.790784098674919],"luv":[48.2757296522395052,2.10423911354751,-67.3027859511178],"rgb":[0.466666666666666674,0.4,0.733333333333333282],"xyz":[0.213274280145952788,0.170124584907046544,0.491754052324614555],"hpluv":[271.790784098674919,176.992833999799871,48.2757296522395052],"hsluv":[271.790784098674919,53.26174830093764,48.2757296522395052]},"#7766cc":{"lch":[49.2332558923506838,80.8618894300095263,270.423298283194697],"luv":[49.2332558923506838,0.597398061184884921,-80.8596826468393886],"rgb":[0.466666666666666674,0.4,0.8],"xyz":[0.232566655589674542,0.177841535084535346,0.59336056299488471],"hpluv":[270.423298283194697,208.412927467485218,49.2332558923506838],"hsluv":[270.423298283194697,64.812294986267446,49.2332558923506838]},"#7766dd":{"lch":[50.2691251722936698,93.9789905273776327,269.490145829531343],"luv":[50.2691251722936698,-0.836273601566472236,-93.9752696564806769],"rgb":[0.466666666666666674,0.4,0.866666666666666696],"xyz":[0.254084981140308086,0.18644886530478888,0.706690410894890708],"hpluv":[269.490145829531343,237.229544488008315,50.2691251722936698],"hsluv":[269.490145829531343,76.411365903071939,50.2691251722936698]},"#7766ee":{"lch":[51.378904811117593,106.647241299318011,268.82087794331261],"luv":[51.378904811117593,-2.19459861633770803,-106.624658562961542],"rgb":[0.466666666666666674,0.4,0.933333333333333348],"xyz":[0.277897161406482796,0.195973737411258925,0.832101226963413931],"hpluv":[268.82087794331261,263.392927722023558,51.378904811117593],"hsluv":[268.82087794331261,88.1124589032604177,51.378904811117593]},"#7766ff":{"lch":[52.5578914047646748,118.864223743766644,268.322642340607558],"luv":[52.5578914047646748,-3.47930230784918848,-118.81329109850806],"rgb":[0.466666666666666674,0.4,1],"xyz":[0.304068209816314217,0.206442156775191621,0.969935415255195776],"hpluv":[268.322642340607558,286.980608281330717,52.5578914047646748],"hsluv":[268.322642340607558,99.9999999999990621,52.5578914047646748]},"#eeee00":{"lch":[91.3819857871042416,100.73955854358779,85.8743202181747591],"luv":[91.3819857871042416,7.24765584469138,100.478505862268193],"rgb":[0.933333333333333348,0.933333333333333348,0],"xyz":[0.658323051985028163,0.793268712127427555,0.118438362762215782],"hpluv":[85.8743202181747591,533.074105620447313,91.3819857871042416],"hsluv":[85.8743202181747591,100.000000000002302,91.3819857871042416]},"#eeee11":{"lch":[91.4002420948697,99.9206079899190485,85.8743202181747449],"luv":[91.4002420948697,7.18873686735402107,99.6616775060856526],"rgb":[0.933333333333333348,0.933333333333333348,0.0666666666666666657],"xyz":[0.659334717484665322,0.793673378327282464,0.123766467726971419],"hpluv":[85.8743202181747449,529.940172906192515,91.4002420948697],"hsluv":[85.8743202181747449,99.1672499526241182,91.4002420948697]},"#eeee22":{"lch":[91.4340680155716,98.4094794247264559,85.8743202181747],"luv":[91.4340680155716,7.08001949817026599,98.1544648222952105],"rgb":[0.933333333333333348,0.933333333333333348,0.133333333333333331],"xyz":[0.661210075623142268,0.794423521582673264,0.133643353922950597],"hpluv":[85.8743202181747,524.128135432551403,91.4340680155716],"hsluv":[85.8743202181747,97.631382664670781,91.4340680155716]},"#eeee33":{"lch":[91.4897155548310224,95.9410009888260475,85.874320218174617],"luv":[91.4897155548310224,6.90242608380469225,95.6923831080380864],"rgb":[0.933333333333333348,0.933333333333333348,0.2],"xyz":[0.664297826355600085,0.795658621875656391,0.149905507780561748],"hpluv":[85.874320218174617,514.550466890897383,91.4897155548310224],"hsluv":[85.874320218174617,95.1245282264191,91.4897155548310224]},"#eeee44":{"lch":[91.569956182858661,92.4193611961338917,85.8743202181745],"luv":[91.569956182858661,6.64906351605686385,92.1798691594911],"rgb":[0.933333333333333348,0.933333333333333348,0.266666666666666663],"xyz":[0.668755821599819,0.797441819973344,0.173384282733448386],"hpluv":[85.8743202181745,500.701064757674544,91.569956182858661],"hsluv":[85.8743202181745,91.5525623856835438,91.569956182858661]},"#eeee55":{"lch":[91.6770884747666912,87.7855710128071536,85.8743202181743612],"luv":[91.6770884747666912,6.31568785915728625,87.5580868047623682],"rgb":[0.933333333333333348,0.933333333333333348,0.333333333333333315],"xyz":[0.674718235639180874,0.799826785589088707,0.204786330007422301],"hpluv":[85.8743202181743612,482.129233036801622,91.6770884747666912],"hsluv":[85.8743202181743612,86.8606098102410584,91.6770884747666912]},"#eeee66":{"lch":[91.8130678710263197,82.0131153940214261,85.8743202181741481],"luv":[91.8130678710263197,5.90039150181238092,81.8005897091115912],"rgb":[0.933333333333333348,0.933333333333333348,0.4],"xyz":[0.682303231412689115,0.802860783898492,0.244733974414566263],"hpluv":[85.8743202181741481,458.402522986492727,91.8130678710263197],"hsluv":[85.8743202181741481,81.0287908474737435,91.8130678710263197]},"#eeee77":{"lch":[91.9795762822891163,75.1051560234190703,85.8743202181738923],"luv":[91.9795762822891163,5.40340190972927914,74.9105313631138],"rgb":[0.933333333333333348,0.933333333333333348,0.466666666666666674],"xyz":[0.691617244432891,0.806586389106572876,0.2937877763209642],"hpluv":[85.8743202181738923,429.072804464814112,91.9795762822891163],"hsluv":[85.8743202181738923,74.0694118243717838,91.9795762822891163]},"#eeee88":{"lch":[92.1780636375363542,67.0918310376028444,85.8743202181734233],"luv":[92.1780636375363542,4.82688735568056,66.9179718045445497],"rgb":[0.933333333333333348,0.933333333333333348,0.533333333333333326],"xyz":[0.702757661534834877,0.811042555947350419,0.35246063972453634],"hpluv":[85.8743202181734233,393.637417052406249,92.1780636375363542],"hsluv":[85.8743202181734233,66.0241185279663085,92.1780636375363542]},"#eeee99":{"lch":[92.4097746137617264,58.0271343519240759,85.8743202181728549],"luv":[92.4097746137617264,4.17473240419888647,57.8767650309654],"rgb":[0.933333333333333348,0.933333333333333348,0.6],"xyz":[0.715814625643907521,0.816265341590979632,0.421227317365654219],"hpluv":[85.8743202181728549,351.489405737917593,92.4097746137617264],"hsluv":[85.8743202181728549,56.9604957584853295,92.4097746137617264]},"#eeeeaa":{"lch":[92.6757669457712,47.9852530272659195,85.8743202181718885],"luv":[92.6757669457712,3.45227440531043239,47.8609058577161903],"rgb":[0.933333333333333348,0.933333333333333348,0.66666666666666663],"xyz":[0.730872318609160132,0.822288418777080699,0.500531166982652875],"hpluv":[85.8743202181718885,301.850049763156903,92.6757669457712],"hsluv":[85.8743202181718885,46.9680087594427178,92.6757669457712]},"#eeeebb":{"lch":[92.9769247593952741,37.0564456712956627,85.8743202181703253],"luv":[92.9769247593952741,2.66600696822725,36.9604189997225347],"rgb":[0.933333333333333348,0.933333333333333348,0.733333333333333282],"xyz":[0.748009910716496695,0.829143455620015457,0.590789152081294566],"hpluv":[85.8743202181703253,243.673832720465015,92.9769247593952741],"hsluv":[85.8743202181703253,36.1533987495139,92.9769247593952741]},"#eeeecc":{"lch":[93.3139689281547788,25.3426537884513579,85.8743202181670711],"luv":[93.3139689281547788,1.82326422217474082,25.2769817940640493],"rgb":[0.933333333333333348,0.933333333333333348,0.8],"xyz":[0.76730228616021845,0.836860405797504314,0.692395662751564722],"hpluv":[85.8743202181670711,175.509740066336235,93.3139689281547788],"hsluv":[85.8743202181670711,24.635760697738192,93.3139689281547788]},"#eeeedd":{"lch":[93.6874656794852143,12.9530841337210045,85.8743202181571377],"luv":[93.6874656794852143,0.931902991100789779,12.919518001474831],"rgb":[0.933333333333333348,0.933333333333333348,0.866666666666666696],"xyz":[0.788820611710852,0.84546773601775782,0.80572551065157072],"hpluv":[85.8743202181571377,95.2907564198152812,93.6874656794852143],"hsluv":[85.8743202181571377,12.5415797244653469,93.6874656794852143]},"#eeeeee":{"lch":[94.0978342288501466,4.90671076366048496e-12,0],"luv":[94.0978342288501466,4.6515081442594671e-12,1.56182025281704723e-12],"rgb":[0.933333333333333348,0.933333333333333348,0.933333333333333348],"xyz":[0.812632791977026758,0.854992608124227838,0.931136326720093943],"hpluv":[0,3.87295813278393312e-11,94.0978342288501466],"hsluv":[0,3.8714510065860851e-11,94.0978342288501466]},"#eeeeff":{"lch":[94.5453539438838391,13.4050739145486393,265.874320218197],"luv":[94.5453539438838391,-0.964421163933715353,-13.3703365130825738],"rgb":[0.933333333333333348,0.933333333333333348,1],"xyz":[0.838803840386858179,0.865461027488160561,1.06897051501187579],"hpluv":[265.874320218197,114.885858328026472,94.5453539438838391],"hsluv":[265.874320218197,99.999999999981938,94.5453539438838391]},"#777700":{"lch":[48.4055282063088868,53.3622847060179737,85.8743202181747],"luv":[48.4055282063088868,3.83912219020021839,53.2240036999738706],"rgb":[0.466666666666666674,0.466666666666666674,0],"xyz":[0.142041159467901856,0.171157317521294372,0.0255545090233414707],"hpluv":[85.8743202181747,139.887458074797621,48.4055282063088868],"hsluv":[85.8743202181747,100.000000000002331,48.4055282063088868]},"#777711":{"lch":[48.4562461221814829,51.3697569370731628,85.874320218174617],"luv":[48.4562461221814829,3.69577080233359201,51.2366392921178502],"rgb":[0.466666666666666674,0.466666666666666674,0.0666666666666666657],"xyz":[0.143052824967539,0.171561983721149225,0.0308826139880971],"hpluv":[85.874320218174617,134.523163178361983,48.4562461221814829],"hsluv":[85.874320218174617,96.1652781669932324,48.4562461221814829]},"#777722":{"lch":[48.5500530694338579,47.7524066126053768,85.8743202181744323],"luv":[48.5500530694338579,3.43552238949120969,47.6286628324468282],"rgb":[0.466666666666666674,0.466666666666666674,0.133333333333333331],"xyz":[0.144928183106016,0.172312126976540053,0.0407595001840763],"hpluv":[85.8743202181744323,124.808706278838557,48.5500530694338579],"hsluv":[85.8743202181744323,89.2207979160694293,48.5500530694338579]},"#777733":{"lch":[48.7039135074563063,42.0024110114446501,85.874320218174],"luv":[48.7039135074563063,3.02184190658892726,41.8935675523809934],"rgb":[0.466666666666666674,0.466666666666666674,0.2],"xyz":[0.148015933838473723,0.173547227269523152,0.0570216540416874432],"hpluv":[85.874320218174,109.433348296247431,48.7039135074563063],"hsluv":[85.874320218174,78.2295638238963704,48.7039135074563063]},"#777744":{"lch":[48.9247697387985312,34.1210359912247227,85.8743202181732528],"luv":[48.9247697387985312,2.45482042510454956,34.0326160292585],"rgb":[0.466666666666666674,0.466666666666666674,0.266666666666666663],"xyz":[0.152473929082692611,0.175330425367210746,0.0805004289945740747],"hpluv":[85.8743202181732528,88.497855114462908,48.9247697387985312],"hsluv":[85.8743202181732528,63.2636094274766378,48.9247697387985312]},"#777755":{"lch":[49.2178287935421537,24.2815247917763841,85.8743202181716327],"luv":[49.2178287935421537,1.74692184102758041,24.2186025669317253],"rgb":[0.466666666666666674,0.466666666666666674,0.333333333333333315],"xyz":[0.158436343122054624,0.177715390982955579,0.11190247626854799],"hpluv":[85.8743202181716327,62.6026663147617,49.2178287935421537],"hsluv":[85.8743202181716327,44.7521651878825324,49.2178287935421537]},"#777766":{"lch":[49.5868745078829676,12.7836483150604128,85.8743202181664742],"luv":[49.5868745078829676,0.919713018071489197,12.750521252385596],"rgb":[0.466666666666666674,0.466666666666666674,0.4],"xyz":[0.166021338895562781,0.18074938929235887,0.151850120675691952],"hpluv":[85.8743202181664742,32.7135296885410085,49.5868745078829676],"hsluv":[85.8743202181664742,23.385605928338574,49.5868745078829676]},"#777777":{"lch":[50.0344387925380687,2.67192546523751356e-12,0],"luv":[50.0344387925380687,2.52749706171116152e-12,8.66570421158112546e-13],"rgb":[0.466666666666666674,0.466666666666666674,0.466666666666666674],"xyz":[0.175335351915764714,0.184474994500439693,0.200903922582089861],"hpluv":[0,6.77633132918180515e-12,50.0344387925380687],"hsluv":[0,1.94020402484744743e-12,50.0344387925380687]},"#777788":{"lch":[50.5619220099523545,13.6772258441596737,265.874320218187563],"luv":[50.5619220099523545,-0.984000994856362388,-13.6417831984777926],"rgb":[0.466666666666666674,0.466666666666666674,0.533333333333333326],"xyz":[0.186475769017708515,0.188931161341217291,0.259576785985662029],"hpluv":[265.874320218187563,34.3252548472133,50.5619220099523545],"hsluv":[265.874320218187563,11.1797639211738336,50.5619220099523545]},"#777799":{"lch":[51.1696982290560669,27.8798810968622455,265.87432021818239],"luv":[51.1696982290560669,-2.00580373888746255,-27.8076342276045096],"rgb":[0.466666666666666674,0.466666666666666674,0.6],"xyz":[0.199532733126781242,0.194153946984846448,0.328343463626779908],"hpluv":[265.87432021818239,69.1380916549642563,51.1696982290560669],"hsluv":[265.87432021818239,22.9846011782403536,51.1696982290560669]},"#7777aa":{"lch":[51.8572203345112,42.2927406525888614,265.874320218180628],"luv":[51.8572203345112,-3.04272952363285398,-42.1831448442758443],"rgb":[0.466666666666666674,0.466666666666666674,0.66666666666666663],"xyz":[0.21459042609203377,0.200177024170947543,0.407647313243778564],"hpluv":[265.874320218180628,103.489412577951782,51.8572203345112],"hsluv":[265.874320218180628,35.2207148819814435,51.8572203345112]},"#7777bb":{"lch":[52.6231302285762439,56.6671214785474,265.874320218179832],"luv":[52.6231302285762439,-4.07688697591046,-56.5202764435038816],"rgb":[0.466666666666666674,0.466666666666666674,0.733333333333333282],"xyz":[0.231728018199370445,0.207032061013882301,0.497905298342420255],"hpluv":[265.874320218179832,136.645017565491173,52.6231302285762439],"hsluv":[265.874320218179832,47.751077300634,52.6231302285762439]},"#7777cc":{"lch":[53.4653742998309696,70.8221320427834513,265.874320218179378],"luv":[53.4653742998309696,-5.09526194727884452,-70.6386062488075],"rgb":[0.466666666666666674,0.466666666666666674,0.8],"xyz":[0.251020393643092143,0.214749011191371103,0.599511809012690411],"hpluv":[265.874320218179378,168.087613695837888,53.4653742998309696],"hsluv":[265.874320218179378,60.4968982098403671,53.4653742998309696]},"#7777dd":{"lch":[54.3813217092404102,84.6378263199215581,265.874320218179037],"luv":[54.3813217092404102,-6.08922498249284594,-84.4184990584042083],"rgb":[0.466666666666666674,0.466666666666666674,0.866666666666666696],"xyz":[0.272538719193725743,0.223356341411624637,0.712841656912696409],"hpluv":[265.874320218179037,197.494074150637061,54.3813217092404102],"hsluv":[265.874320218179037,73.4330970128385445,54.3813217092404102]},"#7777ee":{"lch":[55.3678819060931,98.0443353361264656,265.874320218178809],"luv":[55.3678819060931,-7.05374939408338086,-97.7902669542745713],"rgb":[0.466666666666666674,0.466666666666666674,0.933333333333333348],"xyz":[0.296350899459900452,0.232881213518094682,0.838252472981219632],"hpluv":[265.874320218178809,224.700440227144242,55.3678819060931],"hsluv":[265.874320218178809,86.5809092876847,55.3678819060931]},"#7777ff":{"lch":[56.4216176153771158,111.010032393554411,265.874320218178696],"luv":[56.4216176153771158,-7.98655981550332,-110.722365194803288],"rgb":[0.466666666666666674,0.466666666666666674,1],"xyz":[0.322521947869731873,0.243349632882027378,0.976086661273001477],"hpluv":[265.874320218178696,249.664056525023511,56.4216176153771158],"hsluv":[265.874320218178696,99.99999999999892,56.4216176153771158]},"#eeff00":{"lch":[95.8710857598618702,106.837421111995667,91.929871543819857],"luv":[95.8710857598618702,-3.59788306357601462,106.776822332015158],"rgb":[0.933333333333333348,1,0],"xyz":[0.710175424414702,0.896973456986776663,0.135722486905439893],"hpluv":[91.929871543819857,1221.941869030823,95.8710857598618702],"hsluv":[91.929871543819857,100.000000000002217,95.8710857598618702]},"#eeff11":{"lch":[95.8879066370154192,106.077593073364397,91.9648080695471748],"luv":[95.8879066370154192,-3.63693915095535747,106.015227330089402],"rgb":[0.933333333333333348,1,0.0666666666666666657],"xyz":[0.71118708991433921,0.897378123186631571,0.14105059187019553],"hpluv":[91.9648080695471748,1218.36968740939687,95.8879066370154192],"hsluv":[91.9648080695471748,99.9999999999846096,95.8879066370154192]},"#eeff22":{"lch":[95.9190746883988083,104.674935415410417,92.0306447189025221],"luv":[95.9190746883988083,-3.7090534526558554,104.609201443781629],"rgb":[0.933333333333333348,1,0.133333333333333331],"xyz":[0.713062448052816156,0.898128266442022372,0.150927478066174708],"hpluv":[92.0306447189025221,1211.72771901411761,95.9190746883988083],"hsluv":[92.0306447189025221,99.9999999999843254,95.9190746883988083]},"#eeff33":{"lch":[95.9703546560603,102.38192729680722,92.1421884898051076],"luv":[95.9703546560603,-3.826988551916231,102.31037677397255],"rgb":[0.933333333333333348,1,0.2],"xyz":[0.716150198785274,0.899363366735005498,0.167189631923785859],"hpluv":[92.1421884898051076,1200.73225066318059,95.9703546560603],"hsluv":[92.1421884898051076,99.9999999999843,95.9703546560603]},"#eeff44":{"lch":[96.0443082677326316,99.1069805797193482,92.3105231291127666],"luv":[96.0443082677326316,-3.99552836231266495,99.0264073504377],"rgb":[0.933333333333333348,1,0.266666666666666663],"xyz":[0.720608194029492832,0.901146564832693064,0.190668406876672497],"hpluv":[92.3105231291127666,1184.71704479359755,96.0443082677326316],"hsluv":[92.3105231291127666,99.999999999984,96.0443082677326316]},"#eeff55":{"lch":[96.1430663154878,94.7914212488158086,92.5502587525383831],"luv":[96.1430663154878,-4.21781218752730513,94.6975374691506744],"rgb":[0.933333333333333348,1,0.333333333333333315],"xyz":[0.726570608068854762,0.903531530448437814,0.222070454150646412],"hpluv":[92.5502587525383831,1163.01160371768833,96.1430663154878],"hsluv":[92.5502587525383831,99.9999999999832312,96.1430663154878]},"#eeff66":{"lch":[96.2684490440968261,89.4056432425818315,92.8821944044194083],"luv":[96.2684490440968261,-4.49554545672610839,89.2925479234763912],"rgb":[0.933333333333333348,1,0.4],"xyz":[0.734155603842363,0.906565528757841133,0.262018098557790347],"hpluv":[92.8821944044194083,1134.86447310352946,96.2684490440968261],"hsluv":[92.8821944044194083,99.9999999999826912,96.2684490440968261]},"#eeff77":{"lch":[96.4220309754045104,82.947030730659,93.3376121292550494],"luv":[96.4220309754045104,-4.82912482473711879,82.8063370791148827],"rgb":[0.933333333333333348,1,0.466666666666666674],"xyz":[0.743469616862564853,0.910291133965922,0.311071900464188311],"hpluv":[93.3376121292550494,1099.34916045901696,96.4220309754045104],"hsluv":[93.3376121292550494,99.9999999999824354,96.4220309754045104]},"#eeff88":{"lch":[96.6051797330544559,75.4384320618763553,93.966065888554354],"luv":[96.6051797330544559,-5.21774760700183382,75.2577713054536446],"rgb":[0.933333333333333348,1,0.533333333333333326],"xyz":[0.754610033964508764,0.914747300806699526,0.369744763867760451],"hpluv":[93.966065888554354,1055.22684316018899,96.6051797330544559],"hsluv":[93.966065888554354,99.9999999999810711,96.6051797330544559]},"#eeff99":{"lch":[96.8190810543072,66.9270103141668926,94.8508818247366],"luv":[96.8190810543072,-5.65953211211599072,66.6872881879637589],"rgb":[0.933333333333333348,1,0.6],"xyz":[0.767666998073581408,0.919970086450328739,0.43851144150887833],"hpluv":[94.8508818247366,1000.72847038880911,96.8190810543072],"hsluv":[94.8508818247366,99.9999999999804,96.8190810543072]},"#eeffaa":{"lch":[97.0647558759300182,57.4841926777339438,96.1432585072641785],"luv":[97.0647558759300182,-6.15165762861061438,57.1540857352402938],"rgb":[0.933333333333333348,1,0.66666666666666663],"xyz":[0.782724691038834,0.925993163636429806,0.517815291125877],"hpluv":[96.1432585072641785,933.191048721381,97.0647558759300182],"hsluv":[96.1432585072641785,99.9999999999786127,97.0647558759300182]},"#eeffbb":{"lch":[97.3430726615411857,47.2094061136043166,98.1473956779809242],"luv":[97.3430726615411857,-6.69052372550339935,46.7329104366258861],"rgb":[0.933333333333333348,1,0.733333333333333282],"xyz":[0.799862283146170583,0.932848200479364564,0.608073276224518677],"hpluv":[98.1473956779809242,848.432918810296883,97.3430726615411857],"hsluv":[98.1473956779809242,99.9999999999760689,97.3430726615411857]},"#eeffcc":{"lch":[97.6547568121604,36.2474903433398126,101.573139749476653],"luv":[97.6547568121604,-7.27192346215819718,35.5105573787715443],"rgb":[0.933333333333333348,1,0.8],"xyz":[0.819154658589892337,0.940565150656853421,0.709679786894788833],"hpluv":[101.573139749476653,739.717147432346792,97.6547568121604],"hsluv":[101.573139749476653,99.999999999972971,97.6547568121604]},"#eeffdd":{"lch":[98.0003982932414743,24.8675243497069864,108.50155795297276],"luv":[98.0003982932414743,-7.89122250686935445,23.5822470225029335],"rgb":[0.933333333333333348,1,0.866666666666666696],"xyz":[0.840672984140525936,0.949172480877106928,0.823009634794794831],"hpluv":[108.50155795297276,596.728870831386416,98.0003982932414743],"hsluv":[108.50155795297276,99.9999999999688072,98.0003982932414743]},"#eeffee":{"lch":[98.3804582036479,13.96608756186059,127.715012949221688],"luv":[98.3804582036479,-8.54353535492541205,11.0480588984987129],"rgb":[0.933333333333333348,1,0.933333333333333348],"xyz":[0.864485164406700646,0.958697352983577,0.948420450863318],"hpluv":[127.715012949221688,414.943064796341446,98.3804582036479],"hsluv":[127.715012949221688,99.9999999999608491,98.3804582036479]},"#eeffff":{"lch":[98.7952747621608438,9.43620053547767768,192.177050630058204],"luv":[98.7952747621608438,-9.22389036737693679,-1.99040876112424892],"rgb":[0.933333333333333348,1,1],"xyz":[0.890656212816532067,0.969165772347509669,1.0862546391551],"hpluv":[192.177050630058204,378.040319927501173,98.7952747621608438],"hsluv":[192.177050630058204,99.999999999948713,98.7952747621608438]},"#778800":{"lch":[53.5249548615687303,60.5938372915660253,96.5029793655947259],"luv":[53.5249548615687303,-6.86254771619202231,60.2039745910497572],"rgb":[0.466666666666666674,0.533333333333333326,0],"xyz":[0.164113529192872309,0.215302056971235917,0.0329119655983314136],"hpluv":[96.5029793655947259,143.651932639250902,53.5249548615687303],"hsluv":[96.5029793655947259,100.000000000002373,53.5249548615687303]},"#778811":{"lch":[53.5684856288310272,58.8481082257442409,96.7583563096261088],"luv":[53.5684856288310272,-6.9253766303469888,58.4391906196240143],"rgb":[0.466666666666666674,0.533333333333333326,0.0666666666666666657],"xyz":[0.165125194692509442,0.21570672317109077,0.0382400705630870433],"hpluv":[96.7583563096261088,139.399900460742,53.5684856288310272],"hsluv":[96.7583563096261088,96.9357421545617,53.5684856288310272]},"#778822":{"lch":[53.6490362820541407,55.6690512282284615,97.2652817371477],"luv":[53.6490362820541407,-7.04010577997538,55.2220986133077147],"rgb":[0.466666666666666674,0.533333333333333326,0.133333333333333331],"xyz":[0.167000552830986443,0.216456866426481598,0.0481169567590662428],"hpluv":[97.2652817371477,131.671329649176641,53.6490362820541407],"hsluv":[97.2652817371477,91.3605066517003337,53.6490362820541407]},"#778833":{"lch":[53.7812573057213,50.5917713326567053,98.2096275165039856],"luv":[53.7812573057213,-7.22426441450666346,50.0733195448945381],"rgb":[0.466666666666666674,0.533333333333333326,0.2],"xyz":[0.170088303563444176,0.217691966719464697,0.064379110616677393],"hpluv":[98.2096275165039856,119.368094402160139,53.7812573057213],"hsluv":[98.2096275165039856,82.4672262716137539,53.7812573057213]},"#778844":{"lch":[53.9712743947247162,43.5928841845235198,99.8805739619221811],"luv":[53.9712743947247162,-7.48032491712259429,42.9462954241638357],"rgb":[0.466666666666666674,0.533333333333333326,0.266666666666666663],"xyz":[0.174546298807663064,0.219475164817152291,0.0878578855695640315],"hpluv":[99.8805739619221811,102.492540276722124,53.9712743947247162],"hsluv":[99.8805739619221811,70.2195807792145672,53.9712743947247162]},"#778855":{"lch":[54.2238135722873,34.8221097745323078,102.954066597198249],"luv":[54.2238135722873,-7.80606678579386326,33.9358903004666175],"rgb":[0.466666666666666674,0.533333333333333326,0.333333333333333315],"xyz":[0.180508712847025077,0.221860130432897124,0.119259932843537933],"hpluv":[102.954066597198249,81.4900057495692636,54.2238135722873],"hsluv":[102.954066597198249,54.8454134878709638,54.2238135722873]},"#778866":{"lch":[54.542475349788262,24.6519214642532667,109.417534351990682],"luv":[54.542475349788262,-8.19552569001744224,23.2497438812554442],"rgb":[0.466666666666666674,0.533333333333333326,0.4],"xyz":[0.188093708620533234,0.224894128742300414,0.159207577250681909],"hpluv":[109.417534351990682,57.3528835536874197,54.542475349788262],"hsluv":[109.417534351990682,36.7830408334215164,54.542475349788262]},"#778877":{"lch":[54.9298804020046703,14.1239929232838151,127.715012949231166],"luv":[54.9298804020046703,-8.6401314869560828,11.1729720300858784],"rgb":[0.466666666666666674,0.533333333333333326,0.466666666666666674],"xyz":[0.197407721640735168,0.228619733950381238,0.208261379157079818],"hpluv":[127.715012949231166,32.6278280107521041,54.9298804020046703],"hsluv":[127.715012949231166,16.6133799052879709,54.9298804020046703]},"#778888":{"lch":[55.3877640712208574,9.3400800844087577,192.177050630059369],"luv":[55.3877640712208574,-9.12993258220805437,-1.97013375878514596],"rgb":[0.466666666666666674,0.533333333333333326,0.533333333333333326],"xyz":[0.208548138742678968,0.233075900791158835,0.266934242560651958],"hpluv":[192.177050630059369,21.3981433643613,55.3877640712208574],"hsluv":[192.177050630059369,21.3143847536295468,55.3877640712208574]},"#778899":{"lch":[55.9170512374386703,18.5603965019494623,238.655736169794807],"luv":[55.9170512374386703,-9.65472976501325597,-15.851640655596027],"rgb":[0.466666666666666674,0.533333333333333326,0.6],"xyz":[0.221605102851751695,0.238298686434788,0.335700920201769892],"hpluv":[238.655736169794807,42.1194135101242679,55.9170512374386703],"hsluv":[238.655736169794807,26.1912729818073053,55.9170512374386703]},"#7788aa":{"lch":[56.5179258756863732,31.8473117719276075,251.310804784322386],"luv":[56.5179258756863732,-10.2049729927717898,-30.1680260095876527],"rgb":[0.466666666666666674,0.533333333333333326,0.66666666666666663],"xyz":[0.236662795817004223,0.244321763620889087,0.415004769818768493],"hpluv":[251.310804784322386,71.5032678590983721,56.5179258756863732],"hsluv":[251.310804784322386,31.1149405392867244,56.5179258756863732]},"#7788bb":{"lch":[57.1899017055338845,45.9393215269311881,256.438388794294667],"luv":[57.1899017055338845,-10.7723499078102041,-44.6584565319768387],"rgb":[0.466666666666666674,0.533333333333333326,0.733333333333333282],"xyz":[0.253800387924340898,0.251176800463823846,0.505262754917410239],"hpluv":[256.438388794294667,101.930593576715296,57.1899017055338845],"hsluv":[256.438388794294667,41.4357647235180622,57.1899017055338845]},"#7788cc":{"lch":[57.9318961804226547,60.1932243037694406,259.131204763586595],"luv":[57.9318961804226547,-11.3500713849249486,-59.1134513595764233],"rgb":[0.466666666666666674,0.533333333333333326,0.8],"xyz":[0.273092763368062652,0.258893750641312648,0.606869265587680395],"hpluv":[259.131204763586595,131.8466774878151,57.9318961804226547],"hsluv":[259.131204763586595,55.5026255722761661,57.9318961804226547]},"#7788dd":{"lch":[58.7423077351926679,74.3397271130694861,260.762999043897821],"luv":[58.7423077351926679,-11.9329115646152975,-73.3757497327060264],"rgb":[0.466666666666666674,0.533333333333333326,0.866666666666666696],"xyz":[0.29461108891869614,0.267501080861566209,0.720199113487686393],"hpluv":[260.762999043897821,160.586593274196787,58.7423077351926679],"hsluv":[260.762999043897821,69.9489143241080598,58.7423077351926679]},"#7788ee":{"lch":[59.6190949291064101,88.2283098571320465,261.84384456781811],"luv":[59.6190949291064101,-12.5170812067924775,-87.3358880318318285],"rgb":[0.466666666666666674,0.533333333333333326,0.933333333333333348],"xyz":[0.318423269184870905,0.277025952968036226,0.845609929556209616],"hpluv":[261.84384456781811,187.785436290663455,59.6190949291064101],"hsluv":[261.84384456781811,84.7689484415743237,59.6190949291064101]},"#7788ff":{"lch":[60.55985551741054,101.77153783075579,262.604380260147],"luv":[60.55985551741054,-13.1000102630052879,-100.924901008354297],"rgb":[0.466666666666666674,0.533333333333333326,1],"xyz":[0.344594317594702271,0.28749437233196895,0.983444117847991461],"hpluv":[262.604380260147,213.245970352856943,60.55985551741054],"hsluv":[262.604380260147,99.9999999999987921,60.55985551741054]},"#779900":{"lch":[58.6994568897504223,69.1976359459353603,103.993850276975294],"luv":[58.6994568897504223,-16.7332165977800322,67.1439668384135899],"rgb":[0.466666666666666674,0.6,0],"xyz":[0.189983129645339782,0.267041257876171612,0.0415351657491536685],"hpluv":[103.993850276975294,149.587912305351722,58.6994568897504223],"hsluv":[103.993850276975294,100.000000000002444,58.6994568897504223]},"#779911":{"lch":[58.7371702745588493,67.6759907780605232,104.326162498332039],"luv":[58.7371702745588493,-16.7458460058928829,65.5714600214076],"rgb":[0.466666666666666674,0.6,0.0666666666666666657],"xyz":[0.190994795144976914,0.267445924076026464,0.0468632707139093],"hpluv":[104.326162498332039,146.20456366036808,58.7371702745588493],"hsluv":[104.326162498332039,97.5197891999702,58.7371702745588493]},"#779922":{"lch":[58.8069803361006223,64.8997387816913,104.97431376012679],"luv":[58.8069803361006223,-16.7691829588827659,62.6958578920751464],"rgb":[0.466666666666666674,0.6,0.133333333333333331],"xyz":[0.192870153283453916,0.268196067331417265,0.0567401569098885],"hpluv":[104.97431376012679,140.04041716275114,58.8069803361006223],"hsluv":[104.97431376012679,92.9911396041894704,58.8069803361006223]},"#779933":{"lch":[58.9216385591388132,60.4528100001228097,106.14237332279157],"luv":[58.9216385591388132,-16.8074000849803582,58.0693855598141369],"rgb":[0.466666666666666674,0.6,0.2],"xyz":[0.195957904015911677,0.269431167624400392,0.0730023107674996341],"hpluv":[106.14237332279157,130.191012221085145,58.9216385591388132],"hsluv":[106.14237332279157,85.724115661044948,58.9216385591388132]},"#779944":{"lch":[59.0865618982540752,54.3006768161790845,108.091337704968765],"luv":[59.0865618982540752,-16.8621369683366211,51.6161974534756354],"rgb":[0.466666666666666674,0.6,0.266666666666666663],"xyz":[0.200415899260130537,0.271214365722087958,0.0964810857203862726],"hpluv":[108.091337704968765,116.615384645059635,59.0865618982540752],"hsluv":[108.091337704968765,75.6282332091309399,59.0865618982540752]},"#779955":{"lch":[59.3060149965037056,46.5647823410072945,111.326222899357617],"luv":[59.3060149965037056,-16.9345685221747893,43.3762532203180413],"rgb":[0.466666666666666674,0.6,0.333333333333333315],"xyz":[0.206378313299492522,0.273599331337832818,0.127883132994360188],"hpluv":[111.326222899357617,99.6318422422000367,59.3060149965037056],"hsluv":[111.326222899357617,62.8087826319283806,59.3060149965037056]},"#779966":{"lch":[59.5833535636433282,37.5662597340720836,116.949978591108717],"luv":[59.5833535636433282,-17.0254963867212936,33.4866591823296957],"rgb":[0.466666666666666674,0.6,0.4],"xyz":[0.213963309073000707,0.276633329647236137,0.16783077740150415],"hpluv":[116.949978591108717,80.0041177209304522,59.5833535636433282],"hsluv":[116.949978591108717,47.5357009492008,59.5833535636433282]},"#779977":{"lch":[59.921152065724,28.0111989307655129,127.71501294923614],"luv":[59.921152065724,-17.1354122862910181,22.1586306282167591],"rgb":[0.466666666666666674,0.6,0.466666666666666674],"xyz":[0.223277322093202613,0.280358934855316932,0.216884579307902059],"hpluv":[127.71501294923614,59.3185968765002301,59.921152065724],"hsluv":[127.71501294923614,30.2037385091367128,59.921152065724]},"#779988":{"lch":[60.3212826107906608,19.7788738743410271,150.794869664161695],"luv":[60.3212826107906608,-17.2645515875173317,9.65086059473676272],"rgb":[0.466666666666666674,0.6,0.533333333333333326],"xyz":[0.234417739195146468,0.28481510169609453,0.275557442711474199],"hpluv":[150.794869664161695,41.6073752981458043,60.3212826107906608],"hsluv":[150.794869664161695,33.5278156565034706,60.3212826107906608]},"#779999":{"lch":[60.7849725890424537,17.8137422376051369,192.177050630060307],"luv":[60.7849725890424537,-17.4129412378011317,-3.75751113860251662],"rgb":[0.466666666666666674,0.6,0.6],"xyz":[0.247474703304219168,0.290037887339723688,0.344324120352592133],"hpluv":[192.177050630060307,37.1876097830212373,60.7849725890424537],"hsluv":[192.177050630060307,37.0420465685486562,60.7849725890424537]},"#7799aa":{"lch":[61.3128540464897895,25.0117677757311512,225.340924984985747],"luv":[61.3128540464897895,-17.5804418295499474,-17.7909131959243076],"rgb":[0.466666666666666674,0.6,0.66666666666666663],"xyz":[0.262532396269471724,0.29606096452582481,0.423627969969590734],"hpluv":[225.340924984985747,51.7645188682129742,61.3128540464897895],"hsluv":[225.340924984985747,40.6599304384258815,61.3128540464897895]},"#7799bb":{"lch":[61.9050111975332129,36.7727368637825478,241.108601392342877],"luv":[61.9050111975332129,-17.766782778670386,-32.1958942436537],"rgb":[0.466666666666666674,0.6,0.733333333333333282],"xyz":[0.279669988376808343,0.302916001368759569,0.513885955068232425],"hpluv":[241.108601392342877,75.37710856774234,61.9050111975332129],"hsluv":[241.108601392342877,44.3026829048042927,61.9050111975332129]},"#7799cc":{"lch":[62.5610290710097274,50.0883036089361084,248.973595844380469],"luv":[62.5610290710097274,-17.971590279241223,-46.7531827927901],"rgb":[0.466666666666666674,0.6,0.8],"xyz":[0.298962363820530097,0.31063295154624837,0.615492465738502581],"hpluv":[248.973595844380469,101.594866952252644,62.5610290710097274],"hsluv":[248.973595844380469,49.5852758814030068,62.5610290710097274]},"#7799dd":{"lch":[63.2800443412030518,63.9273589508424962,253.464421950176984],"luv":[63.2800443412030518,-18.1944086519195096,-61.2835272829234228],"rgb":[0.466666666666666674,0.6,0.866666666666666696],"xyz":[0.320480689371163641,0.319240281766501877,0.728822313638508579],"hpluv":[253.464421950176984,128.191525099113591,63.2800443412030518],"hsluv":[253.464421950176984,65.7895471985927429,63.2800443412030518]},"#7799ee":{"lch":[64.0607982423263138,77.8622331281598292,256.304567564122067],"luv":[64.0607982423263138,-18.434716379612933,-75.6484539148497106],"rgb":[0.466666666666666674,0.6,0.933333333333333348],"xyz":[0.344292869637338406,0.328765153872971894,0.854233129707031802],"hpluv":[256.304567564122067,154.231767587931557,64.0607982423263138],"hsluv":[256.304567564122067,82.5871459557978085,64.0607982423263138]},"#7799ff":{"lch":[64.9016907971027,91.67329289213788,258.23504341307023],"luv":[64.9016907971027,-18.6919383586334327,-89.7474460365571929],"rgb":[0.466666666666666674,0.6,1],"xyz":[0.370463918047169771,0.339233573236904618,0.992067317998813758],"hpluv":[258.23504341307023,179.236372955016122,64.9016907971027],"hsluv":[258.23504341307023,99.9999999999984368,64.9016907971027]},"#660000":{"lch":[19.330201679573328,65.0080772249371819,12.1770506300617765],"luv":[19.330201679573328,63.5454254137925432,13.7123671721378795],"rgb":[0.4,0,0],"xyz":[0.0547936733227042463,0.0282529878070199789,0.00256845343700170745],"hpluv":[12.1770506300617765,426.746789183125202,19.330201679573328],"hsluv":[12.1770506300617765,100.000000000002217,19.330201679573328]},"#660011":{"lch":[19.4980803058243595,61.695772445130423,8.9911342856641614],"luv":[19.4980803058243595,60.9376877881905799,9.641916024853316],"rgb":[0.4,0,0.0666666666666666657],"xyz":[0.0558053388223413716,0.0286576540068748317,0.0078965584017573389],"hpluv":[8.9911342856641614,401.51602003210553,19.4980803058243595],"hsluv":[8.9911342856641614,99.9999999999966178,19.4980803058243595]},"#660022":{"lch":[19.8051492014688648,56.728751528179842,2.87530221933591967],"luv":[19.8051492014688648,56.6573341637173584,2.84565201787440492],"rgb":[0.4,0,0.133333333333333331],"xyz":[0.0576806969608183867,0.029407797262265653,0.0177734445977365332],"hpluv":[2.87530221933591967,363.466537566247382,19.8051492014688648],"hsluv":[2.87530221933591967,99.9999999999968594,19.8051492014688648]},"#660033":{"lch":[20.2995520444984123,51.2727836305606957,352.516911450402631],"luv":[20.2995520444984123,50.836110988726972,-6.67743669143524787],"rgb":[0.4,0,0.2],"xyz":[0.0607684476932761272,0.0306428975552487659,0.0340355984553476765],"hpluv":[352.516911450402631,320.508659944055125,20.2995520444984123],"hsluv":[352.516911450402631,99.9999999999973852,20.2995520444984123]},"#660044":{"lch":[20.9904438433464762,47.7800185043531087,338.095292373375855],"luv":[20.9904438433464762,44.3305689635839855,-17.8250055719836844],"rgb":[0.4,0,0.266666666666666663],"xyz":[0.0652264429374950078,0.0324260956529363389,0.057514373408234315],"hpluv":[338.095292373375855,288.844444062118953,20.9904438433464762],"hsluv":[338.095292373375855,99.999999999997911,20.9904438433464762]},"#660055":{"lch":[21.8759682447435324,48.0792454528985687,322.009867044845],"luv":[21.8759682447435324,37.8920594608334085,-29.5940141436867741],"rgb":[0.4,0,0.333333333333333315],"xyz":[0.071188856976857,0.0348110612686811718,0.0889164206822082304],"hpluv":[322.009867044845,278.887908627948889,21.8759682447435324],"hsluv":[322.009867044845,99.9999999999984,21.8759682447435324]},"#660066":{"lch":[22.9458380566939866,52.2668983658326383,307.715012949243601],"luv":[22.9458380566939866,31.9734565677830815,-41.3464235441515271],"rgb":[0.4,0,0.4],"xyz":[0.0787738527503651781,0.0378450595780844834,0.128864065089352192],"hpluv":[307.715012949243601,289.042783730483393,22.9458380566939866],"hsluv":[307.715012949243601,99.9999999999988,22.9458380566939866]},"#660077":{"lch":[24.1840444716539054,59.1802438936044553,296.875135467660698],"luv":[24.1840444716539054,26.7522904844618061,-52.7884099129864097],"rgb":[0.4,0,0.466666666666666674],"xyz":[0.0880878657705671,0.0415706647861653,0.177917866995750101],"hpluv":[296.875135467660698,310.518260327731298,24.1840444716539054],"hsluv":[296.875135467660698,99.9999999999992326,24.1840444716539054]},"#660088":{"lch":[25.5714349826340381,67.6035320092512819,289.201479741547303],"luv":[25.5714349826340381,22.2341957091879898,-63.8426039670327725],"rgb":[0.4,0,0.533333333333333326],"xyz":[0.0992282828725109256,0.0460268316269428907,0.236590730399322269],"hpluv":[289.201479741547303,335.469941782198191,25.5714349826340381],"hsluv":[289.201479741547303,99.9999999999995168,25.5714349826340381]},"#660099":{"lch":[27.0878540213863559,76.7583277742970296,283.827270614430063],"luv":[27.0878540213863559,18.3449067131383,-74.5339203342523291],"rgb":[0.4,0,0.6],"xyz":[0.112285246981583625,0.0512496172705720551,0.305357408040440148],"hpluv":[283.827270614430063,359.575614235331898,27.0878540213863559],"hsluv":[283.827270614430063,99.9999999999996732,27.0878540213863559]},"#6600aa":{"lch":[28.7136916664512327,86.2331190336617226,280.0081392435834],"luv":[28.7136916664512327,14.9862877024472088,-84.9209161465722246],"rgb":[0.4,0,0.66666666666666663],"xyz":[0.127342939946836181,0.0572726944566731566,0.384661257657438749],"hpluv":[280.0081392435834,381.087223541781498,28.7136916664512327],"hsluv":[280.0081392435834,99.9999999999998863,28.7136916664512327]},"#6600bb":{"lch":[30.4308478844127208,95.8259209373334784,277.232006261077231],"luv":[30.4308478844127208,12.063278317584528,-95.06358103774852],"rgb":[0.4,0,0.733333333333333282],"xyz":[0.144480532054172828,0.0641277312996079152,0.474919242756080495],"hpluv":[277.232006261077231,399.584170303460496,30.4308478844127208],"hsluv":[277.232006261077231,100.000000000000071,30.4308478844127208]},"#6600cc":{"lch":[32.2232190058254631,105.440117399912424,275.16595430901134],"luv":[32.2232190058254631,9.49391256045434,-105.011827817640437],"rgb":[0.4,0,0.8],"xyz":[0.163772907497894554,0.0718446814770967168,0.576525753426350707],"hpluv":[275.16595430901134,415.218107165999243,32.2232190058254631],"hsluv":[275.16595430901134,100.000000000000284,32.2232190058254631]},"#6600dd":{"lch":[34.0768449366564425,115.029794578821409,273.594219506454294],"luv":[34.0768449366564425,7.21119822634443164,-114.803537667557165],"rgb":[0.4,0,0.866666666666666696],"xyz":[0.185291233048528098,0.0804520116973502508,0.689855601326356704],"hpluv":[273.594219506454294,428.341637585051217,34.0768449366564425],"hsluv":[273.594219506454294,100.000000000000313,34.0768449366564425]},"#6600ee":{"lch":[35.9798440153965657,124.573148355199,272.374748889870204],"luv":[35.9798440153965657,5.16172842086039729,-124.466163477612255],"rgb":[0.4,0,0.933333333333333348],"xyz":[0.209103413314702835,0.0899768838038202817,0.815266417394879928],"hpluv":[272.374748889870204,439.343788723350144,35.9798440153965657],"hsluv":[272.374748889870204,100.000000000000313,35.9798440153965657]},"#6600ff":{"lch":[37.9222328155672699,134.059876636217865,271.411957283269032],"luv":[37.9222328155672699,3.30334385288953181,-134.01917192367489],"rgb":[0.4,0,1],"xyz":[0.235274461724534228,0.100445303167752992,0.953100605686661773],"hpluv":[271.411957283269032,448.58447779597617,37.9222328155672699],"hsluv":[271.411957283269032,100.00000000000054,37.9222328155672699]},"#661100":{"lch":[20.9278595225824304,60.6482483509225645,15.3961031612090817],"luv":[20.9278595225824304,58.4717927536604165,16.1015365791022269],"rgb":[0.4,0.0666666666666666657,0],"xyz":[0.0567980735836326536,0.0322617883288768559,0.00323658685731115833],"hpluv":[15.3961031612090817,367.733145903292666,20.9278595225824304],"hsluv":[15.3961031612090817,100.00000000000216,20.9278595225824304]},"#661111":{"lch":[21.0816163302651134,57.5811303886473453,12.1770506300618102],"luv":[21.0816163302651134,56.2855814623301782,12.1457768908291825],"rgb":[0.4,0.0666666666666666657,0.0666666666666666657],"xyz":[0.0578097390832697788,0.0326664545287317087,0.00856469182206678892],"hpluv":[12.1770506300618102,346.589664487627374,21.0816163302651134],"hsluv":[12.1770506300618102,81.2167011616125762,21.0816163302651134]},"#661122":{"lch":[21.363314856368774,52.932385078801687,5.93410154371749865],"luv":[21.363314856368774,52.6487447994206548,5.4723908098767966],"rgb":[0.4,0.0666666666666666657,0.133333333333333331],"xyz":[0.059685097221746794,0.0334165977841225301,0.018441578018045985],"hpluv":[5.93410154371749865,314.406957937895,21.363314856368774],"hsluv":[5.93410154371749865,82.5199513610387356,21.363314856368774]},"#661133":{"lch":[21.8180817632255923,47.7742586248590229,355.183549580278111],"luv":[21.8180817632255923,47.6055578330604661,-4.01131531521171425],"rgb":[0.4,0.0666666666666666657,0.2],"xyz":[0.0627728479542045414,0.0346516980771056429,0.0347037318756571317],"hpluv":[355.183549580278111,277.854041301729922,21.8180817632255923],"hsluv":[355.183549580278111,84.3121175303292603,21.8180817632255923]},"#661144":{"lch":[22.4559756968324393,44.5402485804784689,339.935360677682411],"luv":[22.4559756968324393,41.8369301419790247,-15.2808710453946635],"rgb":[0.4,0.0666666666666666657,0.266666666666666663],"xyz":[0.0672308431984234151,0.036434896174793216,0.0581825068285437702],"hpluv":[339.935360677682411,251.686564911624259,22.4559756968324393],"hsluv":[339.935360677682411,86.3348863624116518,22.4559756968324393]},"#661155":{"lch":[23.2773926977910151,45.1903944783221903,322.792583995755933],"luv":[23.2773926977910151,35.9919645110905364,-27.3267313035930464],"rgb":[0.4,0.0666666666666666657,0.333333333333333315],"xyz":[0.073193257237785414,0.0388198617905380489,0.0895845541025176717],"hpluv":[322.792583995755933,246.349182588766354,23.2773926977910151],"hsluv":[322.792583995755933,88.344826800164725,23.2773926977910151]},"#661166":{"lch":[24.275087751098269,49.8658315110702119,307.715012949243715],"luv":[24.275087751098269,30.5046415204515107,-39.4470277460696508],"rgb":[0.4,0.0666666666666666657,0.4],"xyz":[0.0807782530112935854,0.0418538600999413604,0.129532198509661634],"hpluv":[307.715012949243715,260.664316843383688,24.275087751098269],"hsluv":[307.715012949243715,90.1819147598703239,24.275087751098269]},"#661177":{"lch":[25.4363091503391701,57.3032374709331265,296.512546946797],"luv":[25.4363091503391701,25.5798087859014238,-51.2770358652572114],"rgb":[0.4,0.0666666666666666657,0.466666666666666674],"xyz":[0.0900922660314955,0.0455794653080221768,0.178586000416059543],"hpluv":[296.512546946797,285.867241464858182,25.4363091503391701],"hsluv":[296.512546946797,91.7740463972148461,25.4363091503391701]},"#661188":{"lch":[26.7449145171680129,66.1973281861227179,288.734792076243366],"luv":[26.7449145171680129,21.2617948521868456,-62.6898902427238127],"rgb":[0.4,0.0666666666666666657,0.533333333333333326],"xyz":[0.101232683133439333,0.0500356321487997746,0.23725886381963171],"hpluv":[288.734792076243366,314.078764213635395,26.7449145171680129],"hsluv":[288.734792076243366,93.110372692245349,26.7449145171680129]},"#661199":{"lch":[28.1832309630650286,75.7381406209258614,283.36677781159608],"luv":[28.1832309630650286,17.5094321789343716,-73.6864012521064637],"rgb":[0.4,0.0666666666666666657,0.6],"xyz":[0.114289647242512032,0.0552584177924289321,0.306025541460749617],"hpluv":[283.36677781159608,341.006914961476241,28.1832309630650286],"hsluv":[283.36677781159608,94.2123428080992,28.1832309630650286]},"#6611aa":{"lch":[29.733500038717203,85.5146667147819102,279.591039159426828],"luv":[29.733500038717203,14.2479867443400359,-84.3193518539685],"rgb":[0.4,0.0666666666666666657,0.66666666666666663],"xyz":[0.129347340207764588,0.0612814949785300336,0.385329391077748218],"hpluv":[279.591039159426828,364.950446526832081,29.733500038717203],"hsluv":[279.591039159426828,95.1136535912152254,29.733500038717203]},"#6611bb":{"lch":[31.378866229854367,95.3367425151459287,276.866082014695],"luv":[31.378866229854367,11.3974241300945351,-94.6530147253534153],"rgb":[0.4,0.0666666666666666657,0.733333333333333282],"xyz":[0.146484932315101235,0.0681365318214647853,0.475587376176389964],"hpluv":[276.866082014695,385.533736621086632,31.378866229854367],"hsluv":[276.866082014695,95.8493220980777636,31.378866229854367]},"#6611cc":{"lch":[33.1039576367877899,105.121866511028642,274.848446148865946],"luv":[33.1039576367877899,8.88494143701037409,-104.745714157780327],"rgb":[0.4,0.0666666666666666657,0.8],"xyz":[0.165777307758822962,0.0758534819989535869,0.577193886846660176],"hpluv":[274.848446148865946,402.951217622234481,33.1039576367877899],"hsluv":[274.848446148865946,96.4508528344463372,33.1039576367877899]},"#6611dd":{"lch":[34.8951509835915559,114.837148656435488,273.319244536407894],"luv":[34.8951509835915559,6.64899595047804048,-114.644500803094743],"rgb":[0.4,0.0666666666666666657,0.866666666666666696],"xyz":[0.187295633309456505,0.0844608122192071209,0.690523734746666173],"hpluv":[273.319244536407894,417.596303228590671,34.8951509835915559],"hsluv":[273.319244536407894,96.944722371929771,34.8951509835915559]},"#6611ee":{"lch":[36.7406193088150914,124.471664845310258,272.136065946829319],"luv":[36.7406193088150914,4.63940101804097527,-124.385173182164465],"rgb":[0.4,0.0666666666666666657,0.933333333333333348],"xyz":[0.211107813575631242,0.0939856843256771657,0.815934550815189397],"hpluv":[272.136065946829319,429.895948632666091,36.7406193088150914],"hsluv":[272.136065946829319,97.3524117238680446,36.7406193088150914]},"#6611ff":{"lch":[38.6302462525687815,134.023748920536207,271.203906716280642],"luv":[38.6302462525687815,2.81591803113255,-133.994163605572282],"rgb":[0.4,0.0666666666666666657,1],"xyz":[0.237278861985462636,0.104454103689609862,0.953768739106971242],"hpluv":[271.203906716280642,440.244168299440901,38.6302462525687815],"hsluv":[271.203906716280642,99.999999999999531,38.6302462525687815]},"#662200":{"lch":[23.5697003211059126,54.0433218319152,21.7646438431993481],"luv":[23.5697003211059126,50.1908335966774928,20.038983444740694],"rgb":[0.4,0.133333333333333331,0],"xyz":[0.0605136973184005889,0.0396930357984128235,0.00447512810223376842],"hpluv":[21.7646438431993481,290.955989204018863,23.5697003211059126],"hsluv":[21.7646438431993481,100.000000000002302,23.5697003211059126]},"#662211":{"lch":[23.7037155268300239,51.2256671637292627,18.5481266113504795],"luv":[23.7037155268300239,48.5648418325832196,16.2949413667354186],"rgb":[0.4,0.133333333333333331,0.0666666666666666657],"xyz":[0.0615253628180377071,0.0400977019982676763,0.0098032330669894],"hpluv":[18.5481266113504795,274.227196288753476,23.7037155268300239],"hsluv":[18.5481266113504795,84.4421944630679775,23.7037155268300239]},"#662222":{"lch":[23.9497782760704823,46.8639841586094761,12.177050630061828],"luv":[23.9497782760704823,45.8095660888384515,9.88517404858116],"rgb":[0.4,0.133333333333333331,0.133333333333333331],"xyz":[0.0634007209565147362,0.0408478452536585,0.0196801192629685942],"hpluv":[12.177050630061828,248.300181449835577,23.9497782760704823],"hsluv":[12.177050630061828,58.184428739378582,23.9497782760704823]},"#662233":{"lch":[24.3484354577474491,41.8866591548313139,0.79920805816821483],"luv":[24.3484354577474491,41.8825842907357284,0.584250188216085209],"rgb":[0.4,0.133333333333333331,0.2],"xyz":[0.0664884716889724697,0.0420829455466416105,0.0359422731205797374],"hpluv":[0.79920805816821483,218.295100847162672,24.3484354577474491],"hsluv":[0.79920805816821483,61.8388407102714908,24.3484354577474491]},"#662244":{"lch":[24.9104705449366364,38.7518995195090881,343.921953822216381],"luv":[24.9104705449366364,37.2361321960480467,-10.7322027305005232],"rgb":[0.4,0.133333333333333331,0.266666666666666663],"xyz":[0.0709464669331913433,0.0438661436443291836,0.059421048073466376],"hpluv":[343.921953822216381,197.40147375767063,24.9104705449366364],"hsluv":[343.921953822216381,66.1143919991375,24.9104705449366364]},"#662255":{"lch":[25.6388481254070371,39.7515606661792376,324.488651014584605],"luv":[25.6388481254070371,32.3577893991285421,-23.0902585650003651],"rgb":[0.4,0.133333333333333331,0.333333333333333315],"xyz":[0.0769088809725533423,0.0462511092600740165,0.0908230953474402913],"hpluv":[324.488651014584605,196.74105716675524,25.6388481254070371],"hsluv":[324.488651014584605,70.5303777194930746,25.6388481254070371]},"#662266":{"lch":[26.530115175026431,45.1550068711170525,307.715012949244],"luv":[26.530115175026431,27.6228683191850166,-35.7204674010796381],"rgb":[0.4,0.133333333333333331,0.4],"xyz":[0.0844938767460615137,0.049285107569477328,0.130770739754584253],"hpluv":[307.715012949244,215.976303505553034,26.530115175026431],"hsluv":[307.715012949244,74.7212231760600076,26.530115175026431]},"#662277":{"lch":[27.5758503181253047,53.47184404785515,295.772994892671647],"luv":[27.5758503181253047,23.2499163509258366,-48.1526686233805137],"rgb":[0.4,0.133333333333333331,0.466666666666666674],"xyz":[0.0938078897662634331,0.0530107127775581444,0.179824541660982162],"hpluv":[295.772994892671647,246.056915236342576,27.5758503181253047],"hsluv":[295.772994892671647,78.4792949436714622,27.5758503181253047]},"#662288":{"lch":[28.7641691288539221,63.1969785740596492,287.807032602413699],"luv":[28.7641691288539221,19.3264050913403267,-60.169329123196718],"rgb":[0.4,0.133333333333333331,0.533333333333333326],"xyz":[0.104948306868207261,0.0574668796183357422,0.23849740506455433],"hpluv":[287.807032602413699,278.794247273594806,28.7641691288539221],"hsluv":[287.807032602413699,81.7283139306751565,28.7641691288539221]},"#662299":{"lch":[30.081149723697223,73.446586603294,282.467625610713],"luv":[30.081149723697223,15.8562317990126083,-71.7145800853016766],"rgb":[0.4,0.133333333333333331,0.6],"xyz":[0.118005270977279975,0.0626896652619649,0.307264082705672237],"hpluv":[282.467625610713,309.825038390781458,30.081149723697223],"hsluv":[282.467625610713,84.475317587044259,30.081149723697223]},"#6622aa":{"lch":[31.512047889249807,83.7990879252892569,278.786617054458873],"luv":[31.512047889249807,12.8007301136733549,-82.8156292354725565],"rgb":[0.4,0.133333333333333331,0.66666666666666663],"xyz":[0.133062963942532531,0.068712742448066,0.386567932322670837],"hpluv":[278.786617054458873,337.444217562648532,31.512047889249807],"hsluv":[278.786617054458873,86.7692530837111349,31.512047889249807]},"#6622bb":{"lch":[33.0422299311305281,94.07636648958254,276.16643073789237],"luv":[33.0422299311305281,10.1053888262289746,-93.5320471739658643],"rgb":[0.4,0.133333333333333331,0.733333333333333282],"xyz":[0.150200556049869149,0.0755677792910007529,0.476825917421312584],"hpluv":[276.16643073789237,361.285484259324733,33.0422299311305281],"hsluv":[276.16643073789237,88.6739591516067662,33.0422299311305281]},"#6622cc":{"lch":[34.6578144612334853,104.214655833315277,274.245119058655746],"luv":[34.6578144612334853,7.71433729467952212,-103.928742369761551],"rgb":[0.4,0.133333333333333331,0.8],"xyz":[0.169492931493590904,0.0832847294684895545,0.578432428091582684],"hpluv":[274.245119058655746,381.563613242959605,34.6578144612334853],"hsluv":[274.245119058655746,90.2534916489383079,34.6578144612334853]},"#6622dd":{"lch":[36.346058304563158,114.200305800004017,272.799119030217753],"luv":[36.346058304563158,5.5769048208672336,-114.064052082299],"rgb":[0.4,0.133333333333333331,0.866666666666666696],"xyz":[0.191011257044224447,0.0918920596887430885,0.691762275991588682],"hpluv":[272.799119030217753,398.702789727268566,36.346058304563158],"hsluv":[272.799119030217753,91.5654894217155118,36.346058304563158]},"#6622ee":{"lch":[38.0955422395423,124.039689220569301,271.686141036519132],"luv":[38.0955422395423,3.64980151132168062,-123.985980864222597],"rgb":[0.4,0.133333333333333331,0.933333333333333348],"xyz":[0.214823437310399185,0.101416931795213133,0.817173092060111905],"hpluv":[271.686141036519132,413.167199445381073,38.0955422395423],"hsluv":[271.686141036519132,92.6590152569973498,38.0955422395423]},"#6622ff":{"lch":[39.8962147757429264,133.745689778340022,270.812765394378914],"luv":[39.8962147757429264,1.89717678294479941,-133.732233416399],"rgb":[0.4,0.133333333333333331,1],"xyz":[0.240994485720230578,0.111885351159145829,0.95500728035189375],"hpluv":[270.812765394378914,425.390148773484384,39.8962147757429264],"hsluv":[270.812765394378914,99.99999999999946,39.8962147757429264]},"#ddaa00":{"lch":[72.3107430320736881,86.5721801417344494,59.9465914104400071],"luv":[72.3107430320736881,43.355958426121056,74.9333253195491267],"rgb":[0.866666666666666696,0.66666666666666663,0],"xyz":[0.441922241377765923,0.441231641500849037,0.0618909005679976823],"hpluv":[59.9465914104400071,151.919966798177825,72.3107430320736881],"hsluv":[59.9465914104400071,100.000000000002402,72.3107430320736881]},"#ddaa11":{"lch":[72.3377322217577188,85.4954146103564625,59.6744594052448178],"luv":[72.3377322217577188,43.1676990261245663,73.7971251485224],"rgb":[0.866666666666666696,0.66666666666666663,0.0666666666666666657],"xyz":[0.442933906877403,0.44163630770070389,0.067219005532753312],"hpluv":[59.6744594052448178,149.974443711406025,72.3377322217577188],"hsluv":[59.6744594052448178,98.5180859943944398,72.3377322217577188]},"#ddaa22":{"lch":[72.3877194091470386,83.5208789068112623,59.1557200492863586],"luv":[72.3877194091470386,42.8217010650181038,71.708013019916109],"rgb":[0.866666666666666696,0.66666666666666663,0.133333333333333331],"xyz":[0.444809265015880084,0.44238645095609469,0.0770958917287325],"hpluv":[59.1557200492863586,146.409577733002152,72.3877194091470386],"hsluv":[59.1557200492863586,95.7957425728033911,72.3877194091470386]},"#ddaa33":{"lch":[72.4698996386445771,80.3304907566891,58.2589820164620633],"luv":[72.4698996386445771,42.2603136650720543,68.3158373595774435],"rgb":[0.866666666666666696,0.66666666666666663,0.2],"xyz":[0.44789701574833779,0.443621551249077817,0.0933580455863436548],"hpluv":[58.2589820164620633,140.657238526484292,72.4698996386445771],"hsluv":[58.2589820164620633,91.3821490755410082,72.4698996386445771]},"#ddaa44":{"lch":[72.5882801580772679,75.8571050863154,56.8623293870095949],"luv":[72.5882801580772679,41.467485474955744,63.5196665644635701],"rgb":[0.866666666666666696,0.66666666666666663,0.266666666666666663],"xyz":[0.452355010992556705,0.445404749346765383,0.116836820539230293],"hpluv":[56.8623293870095949,132.607804442486071,72.5882801580772679],"hsluv":[56.8623293870095949,85.1564308385751332,72.5882801580772679]},"#ddaa55":{"lch":[72.7461171317656579,70.1198989219024469,54.780917696258733],"luv":[72.7461171317656579,40.4384565855633085,57.2846528644045065],"rgb":[0.866666666666666696,0.66666666666666663,0.333333333333333315],"xyz":[0.45831742503191869,0.447789714962510244,0.148238867813204195],"hpluv":[54.780917696258733,122.3124851735341,72.7461171317656579],"hsluv":[54.780917696258733,77.0893717991816345,72.7461171317656579]},"#ddaa66":{"lch":[72.9460991959627307,63.2340905833455835,51.7145858463931702],"luv":[72.9460991959627307,39.17852917707404,49.6345954292357661],"rgb":[0.866666666666666696,0.66666666666666663,0.4],"xyz":[0.465902420805426876,0.450823713271913562,0.188186512220348157],"hpluv":[51.7145858463931702,109.998947735143361,72.9460991959627307],"hsluv":[51.7145858463931702,67.2337497701281421,72.9460991959627307]},"#ddaa77":{"lch":[73.1904440644495651,55.4382228560327377,47.150998877343909],"luv":[73.1904440644495651,37.7017926183457632,40.6444508733775294],"rgb":[0.866666666666666696,0.66666666666666663,0.466666666666666674],"xyz":[0.475216433825628781,0.454549318479994358,0.237240314126746066],"hpluv":[47.150998877343909,96.1156803308001173,73.1904440644495651],"hsluv":[47.150998877343909,55.7140089565642214,73.1904440644495651]},"#ddaa88":{"lch":[73.4809558021361511,47.1613293807763228,40.1850915920125189],"luv":[73.4809558021361511,36.0295555463961819,30.4312687229965526],"rgb":[0.866666666666666696,0.66666666666666663,0.533333333333333326],"xyz":[0.486356850927572582,0.459005485320771955,0.295913177530318261],"hpluv":[40.1850915920125189,81.4424009312931645,73.4809558021361511],"hsluv":[40.1850915920125189,45.325944585658668,73.4809558021361511]},"#ddaa99":{"lch":[73.8190624606049539,39.1833139250455389,29.2463480703396321],"luv":[73.8190624606049539,34.1885051927702435,19.1436204212419021],"rgb":[0.866666666666666696,0.66666666666666663,0.6],"xyz":[0.499413815036645281,0.464228270964401113,0.36467985517143614],"hpluv":[29.2463480703396321,67.3553294964948,73.8190624606049539],"hsluv":[29.2463480703396321,46.1073405736803323,73.8190624606049539]},"#ddaaaa":{"lch":[74.2058435914849923,32.9500913661112946,12.1770506300625296],"luv":[74.2058435914849923,32.2087294789219527,6.95027095793437244],"rgb":[0.866666666666666696,0.66666666666666663,0.66666666666666663],"xyz":[0.514471508001897893,0.470251348150502235,0.443983704788434741],"hpluv":[12.1770506300625296,56.3453191386000114,74.2058435914849923],"hsluv":[12.1770506300625296,46.9171896008106,74.2058435914849923]},"#ddaabb":{"lch":[74.6420527030620633,30.7078714289026884,348.787813428378513],"luv":[74.6420527030620633,30.1217754775259223,-5.97093039446416807],"rgb":[0.866666666666666696,0.66666666666666663,0.733333333333333282],"xyz":[0.531609100109234456,0.477106384993437,0.534241689887076543],"hpluv":[348.787813428378513,52.2042025244198,74.6420527030620633],"hsluv":[348.787813428378513,47.7320050944543937,74.6420527030620633]},"#ddaacc":{"lch":[75.1281375044867445,34.0548346014018435,325.184688201169763],"luv":[75.1281375044867445,27.9589055182432595,-19.4430286208394669],"rgb":[0.866666666666666696,0.66666666666666663,0.8],"xyz":[0.55090147555295621,0.484823335170925795,0.635848200557346699],"hpluv":[325.184688201169763,57.5195499622066393,75.1281375044867445],"hsluv":[325.184688201169763,48.5278754329488109,75.1281375044867445]},"#ddaadd":{"lch":[75.6642595524878772,42.092894356631966,307.715012949247466],"luv":[75.6642595524878772,25.749668941594777,-33.2981426616688125],"rgb":[0.866666666666666696,0.66666666666666663,0.866666666666666696],"xyz":[0.572419801103589809,0.493430665391179302,0.749178048457352697],"hpluv":[307.715012949247466,70.5922995729826255,75.6642595524878772],"hsluv":[307.715012949247466,49.2811497501269855,75.6642595524878772]},"#ddaaee":{"lch":[76.2503141773092636,52.9001531738191915,296.399494755977059],"luv":[76.2503141773092636,23.5208512504545659,-47.3834967290038875],"rgb":[0.866666666666666696,0.66666666666666663,0.933333333333333348],"xyz":[0.596231981369764519,0.502955537497649319,0.87458886452587592],"hpluv":[296.399494755977059,89.1958388421213,76.2503141773092636],"hsluv":[296.399494755977059,73.8038640729286,76.2503141773092636]},"#ddaaff":{"lch":[76.8859510948180542,65.1444004641461447,289.080822119258073],"luv":[76.8859510948180542,21.295808093697417,-61.565261872824486],"rgb":[0.866666666666666696,0.66666666666666663,1],"xyz":[0.62240302977959594,0.513423956861582,1.01242305281765765],"hpluv":[289.080822119258073,113.514774922986319,76.8859510948180542],"hsluv":[289.080822119258073,99.9999999999968736,76.8859510948180542]},"#663300":{"lch":[27.2772702365161024,46.6784293424923,33.1138040531735385],"luv":[27.2772702365161024,39.0972512948193938,25.5006020923387098],"rgb":[0.4,0.2,0],"xyz":[0.0666314194074114075,0.0519284799764346272,0.00651436879857064926],"hpluv":[33.1138040531735385,217.147410386557254,27.2772702365161024],"hsluv":[33.1138040531735385,100.000000000002288,27.2772702365161024]},"#663311":{"lch":[27.3893959478715772,43.971204952951652,30.1269617465812196],"luv":[27.3893959478715772,38.0313691656755353,22.0699303215615963],"rgb":[0.4,0.2,0.0666666666666666657],"xyz":[0.0676430849070485257,0.0523331461762894801,0.0118424737633262799],"hpluv":[30.1269617465812196,203.716046393577358,27.3893959478715772],"hsluv":[30.1269617465812196,87.8713966090680572,27.3893959478715772]},"#663322":{"lch":[27.5957277293980781,39.608651287835805,23.9834802389854467],"luv":[27.5957277293980781,36.1889469500517436,16.0998563809655693],"rgb":[0.4,0.2,0.133333333333333331],"xyz":[0.0695184430455255548,0.0530832894316803,0.0217193599593054759],"hpluv":[23.9834802389854467,182.132533879714401,27.5957277293980781],"hsluv":[23.9834802389854467,66.9779468056010501,27.5957277293980781]},"#663333":{"lch":[27.9312558147072,34.2527069144242517,12.1770506300619683],"luv":[27.9312558147072,33.482036777055967,7.2250359324586606],"rgb":[0.4,0.2,0.2],"xyz":[0.0726061937779832883,0.0543183897246634143,0.0379815138169166192],"hpluv":[12.1770506300619683,155.612242967619039,27.9312558147072],"hsluv":[12.1770506300619683,36.4647718300342518,27.9312558147072]},"#663344":{"lch":[28.4068233476218452,30.4023991370198274,352.642674566889241],"luv":[28.4068233476218452,30.1520905841737843,-3.89323858637544307],"rgb":[0.4,0.2,0.266666666666666663],"xyz":[0.0770641890222021619,0.0561015878223509873,0.0614602887698032577],"hpluv":[352.642674566889241,135.807736934047625,28.4068233476218452],"hsluv":[352.642674566889241,42.3197568133242044,28.4068233476218452]},"#663355":{"lch":[29.027378781744666,31.164203729876963,328.257954430910445],"luv":[29.027378781744666,26.5028264215118483,-16.3953586660521324],"rgb":[0.4,0.2,0.333333333333333315],"xyz":[0.0830266030615641609,0.0584865534380958202,0.0928623360437771661],"hpluv":[328.257954430910445,136.234637721643935,29.027378781744666],"hsluv":[328.257954430910445,48.648881209958347,29.027378781744666]},"#663366":{"lch":[29.7928910898429251,37.2833882928919067,307.715012949244567],"luv":[29.7928910898429251,22.8075289246907325,-29.4935190668720466],"rgb":[0.4,0.2,0.4],"xyz":[0.0906115988350723323,0.0615205517474991317,0.132809980450921128],"hpluv":[307.715012949244567,158.796911496206434,29.7928910898429251],"hsluv":[307.715012949244567,54.9388950129523792,29.7928910898429251]},"#663377":{"lch":[30.6992208566667273,46.7654342463890345,294.320996437271049],"luv":[30.6992208566667273,19.2602655771695837,-42.6151148086008646],"rgb":[0.4,0.2,0.466666666666666674],"xyz":[0.0999256118552742517,0.0652461569555799481,0.181863782357319037],"hpluv":[294.320996437271049,193.302265796468333,30.6992208566667273],"hsluv":[294.320996437271049,60.8304716126584424,30.6992208566667273]},"#663388":{"lch":[31.7390466224972485,57.6768981875091811,286.074834637191429],"luv":[31.7390466224972485,15.9703082974272554,-55.4217812544619122],"rgb":[0.4,0.2,0.533333333333333326],"xyz":[0.11106602895721808,0.0697023237963575459,0.240536645760891205],"hpluv":[286.074834637191429,230.593651019326217,31.7390466224972485],"hsluv":[286.074834637191429,66.1275975958513,31.7390466224972485]},"#663399":{"lch":[32.9028065942714818,68.9918273860838696,280.844497617061506],"luv":[32.9028065942714818,12.9804074562249703,-67.7597319087197292],"rgb":[0.4,0.2,0.6],"xyz":[0.124122993066290793,0.0749251094399867,0.309303323402009112],"hpluv":[280.844497617061506,266.074975063872387,32.9028065942714818],"hsluv":[280.844497617061506,70.7618769362906761,32.9028065942714818]},"#6633aa":{"lch":[34.1795810026756612,80.2563017922262,277.366876751775067],"luv":[34.1795810026756612,10.2906460265496023,-79.5938225097975],"rgb":[0.4,0.2,0.66666666666666663],"xyz":[0.139180686031543321,0.0809481866260878,0.388607173019007712],"hpluv":[277.366876751775067,297.955725741163178,34.1795810026756612],"hsluv":[277.366876751775067,74.7463951454814293,34.1795810026756612]},"#6633bb":{"lch":[35.5578512622049701,91.2933310256451875,274.950579703742051],"luv":[35.5578512622049701,7.87828999249439477,-90.9527615663878208],"rgb":[0.4,0.2,0.733333333333333282],"xyz":[0.15631827813888,0.0878032234690225566,0.478865158117649459],"hpluv":[274.950579703742051,325.793841875348,35.5578512622049701],"hsluv":[274.950579703742051,78.1373397599298158,35.5578512622049701]},"#6633cc":{"lch":[37.0261004663704369,102.052471518039624,273.208108112313198],"luv":[37.0261004663704369,5.71114175070883,-101.892540467119574],"rgb":[0.4,0.2,0.8],"xyz":[0.175610653582601722,0.0955201736465113582,0.58047166878791967],"hpluv":[273.208108112313198,349.747708937339723,37.0261004663704369],"hsluv":[273.208108112313198,81.008127051099,37.0261004663704369]},"#6633dd":{"lch":[38.5732487885037258,112.538160698021628,271.912259810227567],"luv":[38.5732487885037258,3.75528971541350476,-112.475488051606391],"rgb":[0.4,0.2,0.866666666666666696],"xyz":[0.197128979133235266,0.104127503866764892,0.693801516687925668],"hpluv":[271.912259810227567,370.214070757058153,38.5732487885037258],"hsluv":[271.912259810227567,83.8924044294761,38.5732487885037258]},"#6633ee":{"lch":[40.1889386764538372,122.775879994578517,270.923585069715159],"luv":[40.1889386764538372,1.97901241536538453,-122.759929204537158],"rgb":[0.4,0.2,0.933333333333333348],"xyz":[0.22094115939941,0.113652375973234937,0.819212332756448891],"hpluv":[270.923585069715159,387.655406037674595,40.1889386764538372],"hsluv":[270.923585069715159,91.8481370725274502,40.1889386764538372]},"#6633ff":{"lch":[41.8636962738951581,132.796565847050772,270.152898062524457],"luv":[41.8636962738951581,0.354377123439640451,-132.796093005873018],"rgb":[0.4,0.2,1],"xyz":[0.247112207809241397,0.124120795337167633,0.957046521048230736],"hpluv":[270.152898062524457,402.521052726566381,41.8636962738951581],"hsluv":[270.152898062524457,99.9999999999993747,41.8636962738951581]},"#ddbb00":{"lch":[76.6269242453545871,86.8164471599593,69.4373142874166263],"luv":[76.6269242453545871,30.4927107526369845,81.2852390562642],"rgb":[0.866666666666666696,0.733333333333333282,0],"xyz":[0.475876739286364758,0.509140637318047595,0.0732090665375303],"hpluv":[69.4373142874166263,149.25100710879434,76.6269242453545871],"hsluv":[69.4373142874166263,100.000000000002373,76.6269242453545871]},"#ddbb11":{"lch":[76.6514577805917412,85.7837129406502754,69.2755127455160391],"luv":[76.6514577805917412,30.3566774947925779,80.2328956062352461],"rgb":[0.866666666666666696,0.733333333333333282,0.0666666666666666657],"xyz":[0.476888404786001863,0.509545303517902504,0.0785371715022859379],"hpluv":[69.2755127455160391,147.663405788509436,76.6514577805917412],"hsluv":[69.2755127455160391,98.710789014839,76.6514577805917412]},"#ddbb22":{"lch":[76.6969020797125722,83.8847347199512257,68.9672438614109353],"luv":[76.6969020797125722,30.1063672837106679,78.2959473281657523],"rgb":[0.866666666666666696,0.733333333333333282,0.133333333333333331],"xyz":[0.478763762924478919,0.510295446773293304,0.0884140576982651305],"hpluv":[68.9672438614109353,144.735860207932831,76.6969020797125722],"hsluv":[68.9672438614109353,96.3396664069398554,76.6969020797125722]},"#ddbb33":{"lch":[76.7716285455552452,80.8014056767331823,68.4347482297151828],"luv":[76.7716285455552452,29.6994133556607949,75.1452726767666093],"rgb":[0.866666666666666696,0.733333333333333282,0.2],"xyz":[0.481851513656936625,0.511530547066276431,0.104676211555876281],"hpluv":[68.4347482297151828,139.9591753538609,76.7716285455552452],"hsluv":[68.4347482297151828,92.4878111801133542,76.7716285455552452]},"#ddbb44":{"lch":[76.8793043130786771,76.4437058057830683,67.6060651816737277],"luv":[76.8793043130786771,29.122950030038453,70.6788082728408398],"rgb":[0.866666666666666696,0.733333333333333282,0.266666666666666663],"xyz":[0.486309508901155541,0.513313745163964,0.128154986508762919],"hpluv":[67.6060651816737277,133.157612926581692,76.8793043130786771],"hsluv":[67.6060651816737277,87.0382611213693167,76.8793043130786771]},"#ddbb55":{"lch":[77.0229278214451654,70.786451757311653,66.3713649049339551],"luv":[77.0229278214451654,28.3717024864450664,64.851894732620238],"rgb":[0.866666666666666696,0.733333333333333282,0.333333333333333315],"xyz":[0.492271922940517526,0.515698710779708747,0.159557033782736835],"hpluv":[66.3713649049339551,124.235507886155276,77.0229278214451654],"hsluv":[66.3713649049339551,79.9485715087726,77.0229278214451654]},"#ddbb66":{"lch":[77.2049977781888259,63.8693414267369732,64.5489675558404912],"luv":[77.2049977781888259,27.4471820183984,57.6710063509733359],"rgb":[0.866666666666666696,0.733333333333333282,0.4],"xyz":[0.499856918714025711,0.518732709089112065,0.199504678189880769],"hpluv":[64.5489675558404912,113.177180957201557,77.2049977781888259],"hsluv":[64.5489675558404912,71.2432689272834665,77.2049977781888259]},"#ddbb77":{"lch":[77.4276024714994264,55.80459657383539,61.8158033937064815],"luv":[77.4276024714994264,26.3569386858829375,49.1880552764299495],"rgb":[0.866666666666666696,0.733333333333333282,0.466666666666666674],"xyz":[0.509170931734227561,0.522458314297192916,0.248558480096278678],"hpluv":[61.8158033937064815,100.062778032150931,77.4276024714994264],"hsluv":[61.8158033937064815,61.00659046349368,77.4276024714994264]},"#ddbb88":{"lch":[77.6924726660212883,46.8021917196541537,57.5480835848938881],"luv":[77.6924726660212883,25.1136643841879952,39.4936578574539112],"rgb":[0.866666666666666696,0.733333333333333282,0.533333333333333326],"xyz":[0.520311348836171472,0.526914481137970458,0.307231343499850873],"hpluv":[57.5480835848938881,85.1204314231653285,77.6924726660212883],"hsluv":[57.5480835848938881,49.3735690170151145,77.6924726660212883]},"#ddbb99":{"lch":[78.001015952892,37.2494741955694195,50.4191367157405352],"luv":[78.001015952892,23.7341209657771088,28.7091419207933036],"rgb":[0.866666666666666696,0.733333333333333282,0.6],"xyz":[0.533368312945244116,0.532137266781599672,0.375998021140968752],"hpluv":[50.4191367157405352,68.8881727109007471,78.001015952892],"hsluv":[50.4191367157405352,37.2278198354843894,78.001015952892]},"#ddbbaa":{"lch":[78.3543411988951135,27.9779961680489,37.3601297670291643],"luv":[78.3543411988951135,22.2379488027189254,16.9776883770144309],"rgb":[0.866666666666666696,0.733333333333333282,0.66666666666666663],"xyz":[0.548426005910496728,0.538160343967700738,0.455301870757967353],"hpluv":[37.3601297670291643,52.7537881236722086,78.3543411988951135],"hsluv":[37.3601297670291643,37.9002282962103152,78.3543411988951135]},"#ddbbbb":{"lch":[78.7532777240269724,21.1216737069600953,12.1770506300632171],"luv":[78.7532777240269724,20.6464457718990104,4.45526398447083238],"rgb":[0.866666666666666696,0.733333333333333282,0.733333333333333282],"xyz":[0.565563598017833291,0.545015380810635497,0.545559855856609155],"hpluv":[12.1770506300632171,40.7192307977840144,78.7532777240269724],"hsluv":[12.1770506300632171,38.5653299871361952,78.7532777240269724]},"#ddbbcc":{"lch":[79.1983918483363425,20.8793784390591419,335.381067074864461],"luv":[79.1983918483363425,18.9814116783666442,-8.69795692664743747],"rgb":[0.866666666666666696,0.733333333333333282,0.8],"xyz":[0.584855973461555,0.552732330988124354,0.647166366526879311],"hpluv":[335.381067074864461,41.2776027841095186,79.1983918483363425],"hsluv":[335.381067074864461,39.1976988204569,79.1983918483363425]},"#ddbbdd":{"lch":[79.6900023594157858,28.2216267397768341,307.715012949250536],"luv":[79.6900023594157858,17.264138203128045,-22.325092338948604],"rgb":[0.866666666666666696,0.733333333333333282,0.866666666666666696],"xyz":[0.606374299012188644,0.56133966120837786,0.760496214426885309],"hpluv":[307.715012949250536,57.3946451248898555,79.6900023594157858],"hsluv":[307.715012949250536,39.7709084435557401,79.6900023594157858]},"#ddbbee":{"lch":[80.2281958041266,39.4567857635703447,293.154060026294076],"luv":[80.2281958041266,15.5145982189510505,-36.2785774927409221],"rgb":[0.866666666666666696,0.733333333333333282,0.933333333333333348],"xyz":[0.630186479278363354,0.570864533314847877,0.885907030495408532],"hpluv":[293.154060026294076,82.8233888781043674,80.2281958041266],"hsluv":[293.154060026294076,68.7191774169969278,80.2281958041266]},"#ddbbff":{"lch":[80.8128420975971409,52.2658591287574765,285.253756774661895],"luv":[80.8128420975971409,13.7508586713070624,-50.4245368473411],"rgb":[0.866666666666666696,0.733333333333333282,1],"xyz":[0.656357527688194775,0.581332952678780601,1.02374121878719038],"hpluv":[285.253756774661895,113.64059963508393,80.8128420975971409],"hsluv":[285.253756774661895,99.9999999999962768,80.8128420975971409]},"#664400":{"lch":[31.7142168878436834,41.7146560735594463,49.9018869072924431],"luv":[31.7142168878436834,26.8683448374877969,31.9093180282686859],"rgb":[0.4,0.266666666666666663,0],"xyz":[0.0754639898903774337,0.0695936209423669294,0.00945855895955924342],"hpluv":[49.9018869072924431,166.906788900061372,31.7142168878436834],"hsluv":[49.9018869072924431,100.000000000002103,31.7142168878436834]},"#664411":{"lch":[31.8065195391856221,38.988494662362406,47.7128576067384387],"luv":[31.8065195391856221,26.2332728657793552,28.8429906699465946],"rgb":[0.4,0.266666666666666663,0.0666666666666666657],"xyz":[0.0764756553900145519,0.0699982871422217823,0.0147866639243148749],"hpluv":[47.7128576067384387,155.546285842055198,31.8065195391856221],"hsluv":[47.7128576067384387,90.7993319288460157,31.8065195391856221]},"#664422":{"lch":[31.9766874661881033,34.3475437583520318,43.0092135947734064],"luv":[31.9766874661881033,25.116436032279772,23.4290077311931029],"rgb":[0.4,0.266666666666666663,0.133333333333333331],"xyz":[0.078351013528491581,0.0707484303976126,0.0246635501202940727],"hpluv":[43.0092135947734064,136.301783870263904,31.9766874661881033],"hsluv":[43.0092135947734064,74.6688439558526227,31.9766874661881033]},"#664433":{"lch":[32.2542649002247757,27.9288783689085562,32.9719795273007179],"luv":[32.2542649002247757,23.4305644913898661,15.1997004759998031],"rgb":[0.4,0.266666666666666663,0.2],"xyz":[0.0814387642609493145,0.0719835306905957095,0.0409257039779052159],"hpluv":[32.9719795273007179,109.876716511985933,32.2542649002247757],"hsluv":[32.9719795273007179,50.4508902462759465,32.2542649002247757]},"#664444":{"lch":[32.6494757012261942,21.7704999617243,12.1770506300622419],"luv":[32.6494757012261942,21.2806737346177428,4.59212303669972144],"rgb":[0.4,0.266666666666666663,0.266666666666666663],"xyz":[0.0858967595051681881,0.0737667287882832895,0.0644044789307918475],"hpluv":[12.1770506300622419,84.6119136876739,32.6494757012261942],"hsluv":[12.1770506300622419,19.8271939783404392,32.6494757012261942]},"#664455":{"lch":[33.1682230288457163,20.3425996427482829,337.72581918360828],"luv":[33.1682230288457163,18.8246474429619,-7.71064257201243208],"rgb":[0.4,0.266666666666666663,0.333333333333333315],"xyz":[0.0918591735445301871,0.0761516944040281224,0.0958065262047657629],"hpluv":[337.72581918360828,77.8257963773028649,33.1682230288457163],"hsluv":[337.72581918360828,26.9902218950403885,33.1682230288457163]},"#664466":{"lch":[33.8127168447387447,26.5268160416637819,307.715012949245931],"luv":[33.8127168447387447,16.2273642995468066,-20.9843898457416387],"rgb":[0.4,0.266666666666666663,0.4],"xyz":[0.0994441693180383585,0.0791856927134314409,0.135754170611909725],"hpluv":[307.715012949245931,99.5507152142919125,33.8127168447387447],"hsluv":[307.715012949245931,34.4415155187259359,33.8127168447387447]},"#664477":{"lch":[34.5819879544663067,37.1994974310500766,291.489286484323088],"luv":[34.5819879544663067,13.6271894146704895,-34.6136146303646512],"rgb":[0.4,0.266666666666666663,0.466666666666666674],"xyz":[0.108758182338240278,0.0829112979215122503,0.184807972518307634],"hpluv":[291.489286484323088,136.49804898345451,34.5819879544663067],"hsluv":[291.489286484323088,41.7425383187140824,34.5819879544663067]},"#664488":{"lch":[35.4724176022540263,49.4256461635840623,283.003444619748336],"luv":[35.4724176022540263,11.1212465051830698,-48.1582015326441066],"rgb":[0.4,0.266666666666666663,0.533333333333333326],"xyz":[0.119898599440184106,0.0873674647622898481,0.243480835921879801],"hpluv":[283.003444619748336,176.807585609029246,35.4724176022540263],"hsluv":[283.003444619748336,48.5905204317402166,35.4724176022540263]},"#664499":{"lch":[36.4782980897457563,61.9753280698008169,278.131406705371774],"luv":[36.4782980897457563,8.76603164871553453,-61.3522450974139844],"rgb":[0.4,0.266666666666666663,0.6],"xyz":[0.132955563549256806,0.092590250405919,0.312247513562997736],"hpluv":[278.131406705371774,215.5875082467536,36.4782980897457563],"hsluv":[278.131406705371774,54.8155424382278511,36.4782980897457563]},"#6644aa":{"lch":[37.5923984663849922,74.3597011725147468,275.081334091822],"luv":[37.5923984663849922,6.58602388672208239,-74.0674655150911576],"rgb":[0.4,0.266666666666666663,0.66666666666666663],"xyz":[0.148013256514509361,0.0986133275920201,0.391551363179996281],"hpluv":[275.081334091822,251.001852587777108,37.5923984663849922],"hsluv":[275.081334091822,60.3520360208115179,37.5923984663849922]},"#6644bb":{"lch":[38.8064988843830392,86.3901107279874765,273.04172423936518],"luv":[38.8064988843830392,4.58413310153298603,-86.2684006766171905],"rgb":[0.4,0.266666666666666663,0.733333333333333282],"xyz":[0.165150848621846,0.105468364434954859,0.481809348278638083],"hpluv":[273.04172423936518,282.487278503057098,38.8064988843830392],"hsluv":[273.04172423936518,65.2044789549227346,38.8064988843830392]},"#6644cc":{"lch":[40.1118623747323184,98.0126069922284415,271.608181870646],"luv":[40.1118623747323184,2.75066337520804938,-97.9740015535209],"rgb":[0.4,0.266666666666666663,0.8],"xyz":[0.184443224065567735,0.11318531461244366,0.583415858948908239],"hpluv":[271.608181870646,310.061926380003911,40.1118623747323184],"hsluv":[271.608181870646,73.249037078124374,40.1118623747323184]},"#6644dd":{"lch":[41.4996246628331491,109.23540368219534,270.561113733160255],"luv":[41.4996246628331491,1.06975602599714947,-109.230165429047204],"rgb":[0.4,0.266666666666666663,0.866666666666666696],"xyz":[0.205961549616201278,0.121792644832697194,0.696745706848914237],"hpluv":[270.561113733160255,334.009312605211903,41.4996246628331491],"hsluv":[270.561113733160255,82.0982912580276434,41.4996246628331491]},"#6644ee":{"lch":[42.9610953823040305,120.093362966476874,269.772657810053431],"luv":[42.9610953823040305,-0.476513570908160711,-120.092417593346411],"rgb":[0.4,0.266666666666666663,0.933333333333333348],"xyz":[0.229773729882376043,0.131317516939167239,0.82215652291743746],"hpluv":[269.772657810053431,354.717803858999673,42.9610953823040305],"hsluv":[269.772657810053431,90.971694410809846,42.9610953823040305]},"#6644ff":{"lch":[44.4879743720372502,130.630057251556309,269.16406595263021],"luv":[44.4879743720372502,-1.90579898569535566,-130.61615439053088],"rgb":[0.4,0.266666666666666663,1],"xyz":[0.255944778292207409,0.141785936303099935,0.959990711209219305],"hpluv":[269.16406595263021,372.597392941492103,44.4879743720372502],"hsluv":[269.16406595263021,99.9999999999993463,44.4879743720372502]},"#ddcc00":{"lch":[81.0484811072975475,89.5621409057231119,78.2088923998372394],"luv":[81.0484811072975475,18.3014975440108643,87.6723004789036224],"rgb":[0.866666666666666696,0.8,0],"xyz":[0.514100482595981623,0.585588123937282434,0.0859503143074022424],"hpluv":[78.2088923998372394,197.564965691755532,81.0484811072975475],"hsluv":[78.2088923998372394,100.000000000002245,81.0484811072975475]},"#ddcc11":{"lch":[81.070830830397739,88.588371741804238,78.1407504993947413],"luv":[81.070830830397739,18.2056357525625714,86.6974880530521261],"rgb":[0.866666666666666696,0.8,0.0666666666666666657],"xyz":[0.515112148095618783,0.585992790137137343,0.0912784192721578791],"hpluv":[78.1407504993947413,195.686226016320433,81.070830830397739],"hsluv":[78.1407504993947413,98.8754134531589699,81.070830830397739]},"#ddcc22":{"lch":[81.1122340585289265,86.7947856050049751,78.0111959233441894],"luv":[81.1122340585289265,18.0290607078827385,84.9016358983162149],"rgb":[0.866666666666666696,0.8,0.133333333333333331],"xyz":[0.516987506234095728,0.586742933392528143,0.101155305468137072],"hpluv":[78.0111959233441894,192.214732219338657,81.1122340585289265],"hsluv":[78.0111959233441894,96.8049917221618443,81.1122340585289265]},"#ddcc33":{"lch":[81.1803270736657367,83.8738846457710139,77.7882255314295747],"luv":[81.1803270736657367,17.7414783140301893,81.9760237679585089],"rgb":[0.866666666666666696,0.8,0.2],"xyz":[0.520075256966553545,0.58797803368551127,0.117417459325748208],"hpluv":[77.7882255314295747,186.530107062901806,81.1803270736657367],"hsluv":[77.7882255314295747,93.4358723678778631,81.1803270736657367]},"#ddcc44":{"lch":[81.2784695635313312,79.7261575767135469,77.443216014682],"luv":[81.2784695635313312,17.3330313363216426,77.8191893214074213],"rgb":[0.866666666666666696,0.8,0.266666666666666663],"xyz":[0.524533252210772405,0.589761231783198836,0.140896234278634847],"hpluv":[77.443216014682,178.389435414851135,81.2784695635313312],"hsluv":[77.443216014682,88.6570950843060643,81.2784695635313312]},"#ddcc55":{"lch":[81.4094229919429893,74.303525235023784,76.9333685993953509],"luv":[81.4094229919429893,16.7988406729037365,72.37964364652683],"rgb":[0.866666666666666696,0.8,0.333333333333333315],"xyz":[0.530495666250134335,0.592146197398943586,0.172298281552608762],"hpluv":[76.9333685993953509,167.620308244181615,81.4094229919429893],"hsluv":[76.9333685993953509,82.4185745103993668,81.4094229919429893]},"#ddcc66":{"lch":[81.5755062452221154,67.6049359495878406,76.1891492108976252],"luv":[81.5755062452221154,16.1384724175358123,65.6504156329288548],"rgb":[0.866666666666666696,0.8,0.4],"xyz":[0.538080662023642575,0.595180195708346904,0.212245925959752724],"hpluv":[76.1891492108976252,154.10859642349061,81.5755062452221154],"hsluv":[76.1891492108976252,74.724981631947216,81.5755062452221154]},"#ddcc77":{"lch":[81.7786782860545571,59.6741108071854,75.0887439649445554],"luv":[81.7786782860545571,15.3554995822328237,57.6646176889111857],"rgb":[0.866666666666666696,0.8,0.466666666666666674],"xyz":[0.547394675043844425,0.598905800916427755,0.261299727866150633],"hpluv":[75.0887439649445554,137.792143148878608,81.7786782860545571],"hsluv":[75.0887439649445554,65.6305091544174104,81.7786782860545571]},"#ddcc88":{"lch":[82.020587165389415,50.599662209211,73.3985048227604722],"luv":[82.020587165389415,14.4570002873895778,48.4904213054152891],"rgb":[0.866666666666666696,0.8,0.533333333333333326],"xyz":[0.558535092145788337,0.603361967757205298,0.319972591269722773],"hpluv":[73.3985048227604722,118.661765286999071,82.020587165389415],"hsluv":[73.3985048227604722,55.2326761810852389,82.020587165389415]},"#ddcc99":{"lch":[82.3026016456871901,40.5232855707982438,70.6109505258247765],"luv":[82.3026016456871901,13.4529549720920478,38.2250529884698622],"rgb":[0.866666666666666696,0.8,0.6],"xyz":[0.571592056254861,0.608584753400834511,0.388739268910840707],"hpluv":[70.6109505258247765,96.7842051030752231,82.3026016456871901],"hsluv":[70.6109505258247765,43.6647666281718685,82.3026016456871901]},"#ddccaa":{"lch":[82.6258332993788542,29.6818113573176419,65.4008685536862231],"luv":[82.6258332993788542,12.3555588351715961,26.9879619705157374],"rgb":[0.866666666666666696,0.8,0.66666666666666663],"xyz":[0.586649749220113592,0.614607830586935577,0.468043118527839308],"hpluv":[65.4008685536862231,72.4135107626852,82.6258332993788542],"hsluv":[65.4008685536862231,31.0871436920773085,82.6258332993788542]},"#ddccbb":{"lch":[82.9911533066729419,18.6379527757414252,53.1465475992889],"luv":[82.9911533066729419,11.1784915779275345,14.9135713265793797],"rgb":[0.866666666666666696,0.8,0.733333333333333282],"xyz":[0.603787341327450156,0.621462867429870336,0.55830110362648111],"hpluv":[53.1465475992889,46.5946179098545272,82.9911533066729419],"hsluv":[53.1465475992889,24.678645774572626,82.9911533066729419]},"#ddcccc":{"lch":[83.3992063850657,10.164901186858037,12.1770506300648638],"luv":[83.3992063850657,9.93619558955776228,2.14411598208697862],"rgb":[0.866666666666666696,0.8,0.8],"xyz":[0.62307971677117191,0.629179817607359193,0.659907614296751266],"hpluv":[12.1770506300648638,26.1289592314662436,83.3992063850657],"hsluv":[12.1770506300648638,25.0002112827592455,83.3992063850657]},"#ddccdd":{"lch":[83.8504233095379163,14.1290270468723165,307.715012949259346],"luv":[83.8504233095379163,8.64321103323171513,-11.1769543403501022],"rgb":[0.866666666666666696,0.8,0.866666666666666696],"xyz":[0.644598042321805509,0.637787147827612699,0.773237462196757264],"hpluv":[307.715012949259346,37.4791950150616557,83.8504233095379163],"hsluv":[307.715012949259346,25.214872966603707,83.8504233095379163]},"#ddccee":{"lch":[84.3450329093034,25.9620569722210597,286.361909425528779],"luv":[84.3450329093034,7.31360586969829818,-24.9106316943502399],"rgb":[0.866666666666666696,0.8,0.933333333333333348],"xyz":[0.668410222587980218,0.647312019934082716,0.898648278265280487],"hpluv":[286.361909425528779,71.3464154396222199,84.3450329093034],"hsluv":[286.361909425528779,60.879598082714125,84.3450329093034]},"#ddccff":{"lch":[84.8830740665913623,39.380529428060008,278.705583312848262],"luv":[84.8830740665913623,5.96052452183370107,-38.926831947371717],"rgb":[0.866666666666666696,0.8,1],"xyz":[0.694581270997811639,0.65778043929801544,1.03648246655706222],"hpluv":[278.705583312848262,112.590543218900592,84.8830740665913623],"hsluv":[278.705583312848262,99.9999999999947704,84.8830740665913623]},"#665500":{"lch":[36.5970311204425656,41.5054710368830655,69.2006364019199651],"luv":[36.5970311204425656,14.7384507745119784,38.800543743107859],"rgb":[0.4,0.333333333333333315,0],"xyz":[0.0872772466047234,0.0932201343710592,0.0133963111976744542],"hpluv":[69.2006364019199651,143.912599562803223,36.5970311204425656],"hsluv":[69.2006364019199651,100.000000000002359,36.5970311204425656]},"#665511":{"lch":[36.673028710438345,38.8606023214232366,68.2658014049057869],"luv":[36.673028710438345,14.3901304021596417,36.0980686435250391],"rgb":[0.4,0.333333333333333315,0.0666666666666666657],"xyz":[0.0882889121043605174,0.0936248005709140463,0.0187244161624300839],"hpluv":[68.2658014049057869,134.462776824764262,36.673028710438345],"hsluv":[68.2658014049057869,93.0449405246809107,36.673028710438345]},"#665522":{"lch":[36.8133307706753357,34.1687527519613923,66.2355675996872719],"luv":[36.8133307706753357,13.769229594380441,31.2715842419585037],"rgb":[0.4,0.333333333333333315,0.133333333333333331],"xyz":[0.0901642702428375464,0.0943749438263048607,0.0286013023584092835],"hpluv":[66.2355675996872719,117.777773408929676,36.8133307706753357],"hsluv":[66.2355675996872719,80.6853283069105629,36.8133307706753357]},"#665533":{"lch":[37.0427251812615097,27.0303271109949854,61.7081001991288645],"luv":[37.0427251812615097,12.8113945713483854,23.8014023297917383],"rgb":[0.4,0.333333333333333315,0.2],"xyz":[0.09325202097529528,0.0956100441192879735,0.0448634562160204267],"hpluv":[61.7081001991288645,92.5950345984193177,37.0427251812615097],"hsluv":[61.7081001991288645,61.7209513910547045,37.0427251812615097]},"#665544":{"lch":[37.3704580906404473,18.1024774089589755,50.3425610862832542],"luv":[37.3704580906404473,11.5529306171195891,13.9366237840407656],"rgb":[0.4,0.333333333333333315,0.266666666666666663],"xyz":[0.0977100162195141536,0.0973932422169755535,0.0683422311689070583],"hpluv":[50.3425610862832542,61.4679768710498351,37.3704580906404473],"hsluv":[50.3425610862832542,37.0117339514184067,37.3704580906404473]},"#665555":{"lch":[37.8025949068387348,10.2943047784276782,12.1770506300631105],"luv":[37.8025949068387348,10.0626876598879917,2.1714115065313786],"rgb":[0.4,0.333333333333333315,0.333333333333333315],"xyz":[0.103672430258876153,0.0997782078327203864,0.0997442784428809737],"hpluv":[12.1770506300631105,34.5553054430909654,37.8025949068387348],"hsluv":[12.1770506300631105,8.09737912949257321,37.8025949068387348]},"#665566":{"lch":[38.3424918197480693,13.7697499972876347,307.715012949250308],"luv":[38.3424918197480693,8.42342892447929,-10.8927434626015351],"rgb":[0.4,0.333333333333333315,0.4],"xyz":[0.111257426032384324,0.102812206142123705,0.139691922850024935],"hpluv":[307.715012949250308,45.570631638882567,38.3424918197480693],"hsluv":[307.715012949250308,15.7660506346962208,38.3424918197480693]},"#665577":{"lch":[38.9911218270375812,25.5692820710091411,285.225395910208761],"luv":[38.9911218270375812,6.71492531026355,-24.671805035392353],"rgb":[0.4,0.333333333333333315,0.466666666666666674],"xyz":[0.120571439052586243,0.106537811350204514,0.188745724756422845],"hpluv":[285.225395910208761,83.2131821356252885,38.9911218270375812],"hsluv":[285.225395910208761,23.5948697041559434,38.9911218270375812]},"#665588":{"lch":[39.7473800461840554,39.003702064123587,277.369365694294345],"luv":[39.7473800461840554,5.00282395952989312,-38.6815269493963],"rgb":[0.4,0.333333333333333315,0.533333333333333326],"xyz":[0.131711856154530071,0.110993978190982112,0.247418588159995],"hpluv":[277.369365694294345,124.519293959659265,39.7473800461840554],"hsluv":[277.369365694294345,31.2388068533835614,39.7473800461840554]},"#665599":{"lch":[40.6084045881889466,52.6763518020623636,273.629018089310307],"luv":[40.6084045881889466,3.33420095564239061,-52.5707251534733189],"rgb":[0.4,0.333333333333333315,0.6],"xyz":[0.144768820263602771,0.11621676383461127,0.316185265801112947],"hpluv":[273.629018089310307,164.603508765513965,40.6084045881889466],"hsluv":[273.629018089310307,39.2894117268144569,40.6084045881889466]},"#6655aa":{"lch":[41.5699140891343575,66.1399121177165,271.505962745252077],"luv":[41.5699140891343575,1.73822184255944534,-66.1170670838121168],"rgb":[0.4,0.333333333333333315,0.66666666666666663],"xyz":[0.159826513228855327,0.122239841020712364,0.395489115418111492],"hpluv":[271.505962745252077,201.894186201954597,41.5699140891343575],"hsluv":[271.505962745252077,49.6682832978127067,41.5699140891343575]},"#6655bb":{"lch":[42.6265484117568647,79.2031960637105499,270.166039680829499],"luv":[42.6265484117568647,0.229525718995523903,-79.2028634876978],"rgb":[0.4,0.333333333333333315,0.733333333333333282],"xyz":[0.176964105336191974,0.129094877863647123,0.485747100516753294],"hpluv":[270.166039680829499,235.777232293519603,42.6265484117568647],"hsluv":[270.166039680829499,59.8653820834470309,42.6265484117568647]},"#6655cc":{"lch":[43.7721949853351333,91.7929775852419,269.258674658723919],"luv":[43.7721949853351333,-1.18763654850412936,-91.7852943199147688],"rgb":[0.4,0.333333333333333315,0.8],"xyz":[0.1962564807799137,0.136811828041135924,0.58735361118702345],"hpluv":[269.258674658723919,266.103421792879146,43.7721949853351333],"hsluv":[269.258674658723919,69.9112236392489734,43.7721949853351333]},"#6655dd":{"lch":[45.0002850881211458,103.899953671233533,268.61259940679895],"luv":[45.0002850881211458,-2.51566121975990953,-103.869494181457682],"rgb":[0.4,0.333333333333333315,0.866666666666666696],"xyz":[0.217774806330547244,0.145419158261389458,0.700683459087029448],"hpluv":[268.61259940679895,292.98097185143456,45.0002850881211458],"hsluv":[268.61259940679895,79.8793625185682714,45.0002850881211458]},"#6655ee":{"lch":[46.3040490971424106,115.549020689755764,268.134901078425969],"luv":[46.3040490971424106,-3.7607010001107648,-115.487805894602445],"rgb":[0.4,0.333333333333333315,0.933333333333333348],"xyz":[0.241586986596722,0.154944030367859503,0.826094275155552671],"hpluv":[268.134901078425969,316.655201018988919,46.3040490971424106],"hsluv":[268.134901078425969,89.8701820385079344,46.3040490971424106]},"#6655ff":{"lch":[47.6767252326213651,126.781348408818275,267.771145841725911],"luv":[47.6767252326213651,-4.93065761335473951,-126.685432942615918],"rgb":[0.4,0.333333333333333315,1],"xyz":[0.267758035006553374,0.165412449731792199,0.963928463447334516],"hpluv":[267.771145841725911,337.433561350206048,47.6767252326213651],"hsluv":[267.771145841725911,99.9999999999992468,47.6767252326213651]},"#dddd00":{"lch":[85.547159878993142,94.3072427966830844,85.8743202181747449],"luv":[85.547159878993142,6.78488618903739749,94.0628585750738466],"rgb":[0.866666666666666696,0.866666666666666696,0],"xyz":[0.556734473143156827,0.670856105031634,0.100161644489793561],"hpluv":[85.8743202181747449,283.614606809988061,85.547159878993142],"hsluv":[85.8743202181747449,100.000000000002203,85.547159878993142]},"#dddd11":{"lch":[85.5675738163798627,93.4011806547303394,85.8743202181746881],"luv":[85.5675738163798627,6.71970001318247423,93.159144368282],"rgb":[0.866666666666666696,0.866666666666666696,0.0666666666666666657],"xyz":[0.557746138642794,0.671260771231488862,0.105489749454549198],"hpluv":[85.8743202181746881,281.335749103468061,85.5675738163798627],"hsluv":[85.8743202181746881,99.0156164862488,85.5675738163798627]},"#dddd22":{"lch":[85.6053941241358558,91.7307060091609401,85.8743202181746739],"luv":[85.6053941241358558,6.59951857201479086,91.4929985275198447],"rgb":[0.866666666666666696,0.866666666666666696,0.133333333333333331],"xyz":[0.559621496781270933,0.672010914486879662,0.11536663565052839],"hpluv":[85.8743202181746739,277.118842420723468,85.6053941241358558],"hsluv":[85.8743202181746739,97.2017654403352083,85.6053941241358558]},"#dddd33":{"lch":[85.667603455332241,89.0058006932873,85.8743202181745602],"luv":[85.667603455332241,6.4034766573555908,88.775154428206335],"rgb":[0.866666666666666696,0.866666666666666696,0.2],"xyz":[0.56270924751372875,0.673246014779862789,0.131628789508139526],"hpluv":[85.8743202181745602,270.196330508983522,85.667603455332241],"hsluv":[85.8743202181745602,94.2458512979473113,85.667603455332241]},"#dddd44":{"lch":[85.7572852094861418,85.1265937151141117,85.8743202181744607],"luv":[85.7572852094861418,6.12438910193468278,84.9059998802570419],"rgb":[0.866666666666666696,0.866666666666666696,0.266666666666666663],"xyz":[0.567167242757947609,0.675029212877550355,0.155107564461026165],"hpluv":[85.8743202181744607,260.24482525674506,85.7572852094861418],"hsluv":[85.8743202181744607,90.0440000232135844,85.7572852094861418]},"#dddd55":{"lch":[85.8769849033878074,80.0369945631262,85.874320218174276],"luv":[85.8769849033878074,5.75822050268421481,79.8295897229865545],"rgb":[0.866666666666666696,0.866666666666666696,0.333333333333333315],"xyz":[0.573129656797309539,0.677414178493295105,0.18650961173500008],"hpluv":[85.874320218174276,247.008869171162701,85.8769849033878074],"hsluv":[85.874320218174276,84.5423921226573327,85.8769849033878074]},"#dddd66":{"lch":[86.0288537292730098,73.7198014533942398,85.8743202181739775],"luv":[86.0288537292730098,5.30373328608645522,73.5287667485177252],"rgb":[0.866666666666666696,0.866666666666666696,0.4],"xyz":[0.58071465257081778,0.680448176802698423,0.226457256142144042],"hpluv":[85.8743202181739775,230.281095596483937,86.0288537292730098],"hsluv":[85.8743202181739775,77.7321300368988,86.0288537292730098]},"#dddd77":{"lch":[86.2147251389940834,66.1931358813644124,85.8743202181736365],"luv":[86.2147251389940834,4.76223119383214133,66.0216054929389315],"rgb":[0.866666666666666696,0.866666666666666696,0.466666666666666674],"xyz":[0.59002866559101963,0.684173782010779274,0.275511058048541924],"hpluv":[85.8743202181736365,209.886373280136951,86.2147251389940834],"hsluv":[85.8743202181736365,69.6453389130317362,86.2147251389940834]},"#dddd88":{"lch":[86.4361603707972,57.5066396271378224,85.8743202181730823],"luv":[86.4361603707972,4.13728567831694072,57.3576190965201391],"rgb":[0.866666666666666696,0.866666666666666696,0.533333333333333326],"xyz":[0.601169082692963541,0.688629948851556817,0.334183921452114119],"hpluv":[85.8743202181730823,185.665493576193455,86.4361603707972],"hsluv":[85.8743202181730823,60.3508056243124429,86.4361603707972]},"#dddd99":{"lch":[86.6944777431662,47.7369558995854888,85.8743202181722154],"luv":[86.6944777431662,3.43441079587341314,47.613252157820078],"rgb":[0.866666666666666696,0.866666666666666696,0.6],"xyz":[0.614226046802036185,0.693852734495186,0.402950599093232054],"hpluv":[85.8743202181722154,157.456397081560084,86.6944777431662],"hsluv":[85.8743202181722154,49.9486591868920939,86.6944777431662]},"#ddddaa":{"lch":[86.990772885999732,36.9824894935128,85.874320218170638],"luv":[86.990772885999732,2.66068622896724838,36.886654469181245],"rgb":[0.866666666666666696,0.866666666666666696,0.66666666666666663],"xyz":[0.629283739767288797,0.699875811681287097,0.482254448710230599],"hpluv":[85.874320218170638,125.071764704863014,86.990772885999732],"hsluv":[85.874320218170638,38.5641267001819443,86.990772885999732]},"#ddddbb":{"lch":[87.3259337660435477,25.3576808227713499,85.8743202181676821],"luv":[87.3259337660435477,1.82434533444747116,25.2919698878957568],"rgb":[0.866666666666666696,0.866666666666666696,0.733333333333333282],"xyz":[0.64642133187462536,0.706730848524221855,0.572512433808872401],"hpluv":[85.8743202181676821,88.2719508819342735,87.3259337660435477],"hsluv":[85.8743202181676821,26.340671416181145,87.3259337660435477]},"#ddddcc":{"lch":[87.7006527393466797,12.9871390430395461,85.8743202181585445],"luv":[87.7006527393466797,0.934353054076054512,12.9534846621895881],"rgb":[0.866666666666666696,0.866666666666666696,0.8],"xyz":[0.665713707318347114,0.714447798701710712,0.674118944479142557],"hpluv":[85.8743202181585445,46.7319159493201113,87.7006527393466797],"hsluv":[85.8743202181585445,13.4329442518860063,87.7006527393466797]},"#dddddd":{"lch":[88.1154369871094,4.67545248961294327e-12,0],"luv":[88.1154369871094,4.4193702762792188e-12,1.52611347670073729e-12],"rgb":[0.866666666666666696,0.866666666666666696,0.866666666666666696],"xyz":[0.687232032868980713,0.723055128921964219,0.787448792379148554],"hpluv":[0,1.74708563976297451e-11,88.1154369871094],"hsluv":[0,1.74437740136320375e-11,88.1154369871094]},"#ddddee":{"lch":[88.5706181797242209,13.4751686036456029,265.874320218195521],"luv":[88.5706181797242209,-0.969464090371862097,-13.4402495614536726],"rgb":[0.866666666666666696,0.866666666666666696,0.933333333333333348],"xyz":[0.711044213135155423,0.732580001028434236,0.912859608447671778],"hpluv":[265.874320218195521,52.5550848411252431,88.5706181797242209],"hsluv":[265.874320218195521,47.1269490590101725,88.5706181797242209]},"#ddddff":{"lch":[89.0663618949558753,27.3146757005029208,265.874320218186369],"luv":[89.0663618949558753,-1.9651403266809826,-27.2438934831293338],"rgb":[0.866666666666666696,0.866666666666666696,1],"xyz":[0.737215261544986844,0.743048420392367,1.05069379673945362],"hpluv":[265.874320218186369,111.815120511018762,89.0663618949558753],"hsluv":[265.874320218186369,99.9999999999922125,89.0663618949558753]},"#666600":{"lch":[41.7321583215394583,46.0055575524193685,85.8743202181747449],"luv":[41.7321583215394583,3.30984623025532709,45.8863404908370924],"rgb":[0.4,0.4,0],"xyz":[0.102305304310569861,0.123276249782752534,0.0184056637662898],"hpluv":[85.8743202181747449,139.887458074797365,41.7321583215394583],"hsluv":[85.8743202181747449,100.000000000002203,41.7321583215394583]},"#666611":{"lch":[41.7952597887023742,43.6298127640598423,85.8743202181746],"luv":[41.7952597887023742,3.13892449057558931,43.5167521176544625],"rgb":[0.4,0.4,0.0666666666666666657],"xyz":[0.103316969810206979,0.123680915982607387,0.0237337687310454348],"hpluv":[85.8743202181746,132.463323325332908,41.7952597887023742],"hsluv":[85.8743202181746,94.6927802880713756,41.7952597887023742]},"#666622":{"lch":[41.9118699845736913,39.3503176022612067,85.874320218174276],"luv":[41.9118699845736913,2.83103840719259514,39.248346677737],"rgb":[0.4,0.4,0.133333333333333331],"xyz":[0.105192327948684008,0.124431059237998201,0.0336106549270246274],"hpluv":[85.874320218174276,119.138061739500813,41.9118699845736913],"hsluv":[85.874320218174276,85.1670788640685288,41.9118699845736913]},"#666633":{"lch":[42.1028501842444953,32.6344620115447057,85.8743202181736507],"luv":[42.1028501842444953,2.34786962297492563,32.5498943011565842],"rgb":[0.4,0.4,0.2],"xyz":[0.108280078681141742,0.125666159530981314,0.0498728087846357776],"hpluv":[85.8743202181736507,98.3567766096709306,42.1028501842444953],"hsluv":[85.8743202181736507,70.3113616926845,42.1028501842444953]},"#666644":{"lch":[42.3763861696741557,23.5947988734222314,85.8743202181723575],"luv":[42.3763861696741557,1.69751569722617934,23.5336562041455402],"rgb":[0.4,0.4,0.266666666666666663],"xyz":[0.112738073925360616,0.127449357628668908,0.0733515837375224161],"hpluv":[85.8743202181723575,70.6531759312171346,42.3763861696741557],"hsluv":[85.8743202181723575,50.5071554688203506,42.3763861696741557]},"#666655":{"lch":[42.7382714661199543,12.562340839470254,85.87432021816781],"luv":[42.7382714661199543,0.903791165304248856,12.5297872646162745],"rgb":[0.4,0.4,0.333333333333333315],"xyz":[0.118700487964722615,0.129834323244413741,0.104753631011496318],"hpluv":[85.87432021816781,37.2986356199978459,42.7382714661199543],"hsluv":[85.87432021816781,26.6633164497530721,42.7382714661199543]},"#666666":{"lch":[43.1922895629847048,2.27708065554704512e-12,0],"luv":[43.1922895629847048,2.15069538500574498e-12,7.48067960001998255e-13],"rgb":[0.4,0.4,0.4],"xyz":[0.126285483738230786,0.132868321553817031,0.144701275418640279],"hpluv":[0,6.68977504875838914e-12,43.1922895629847048],"hsluv":[0,1.91542116883063395e-12,43.1922895629847048]},"#666677":{"lch":[43.7404449074606489,13.5883126365404472,265.874320218186085],"luv":[43.7404449074606489,-0.977604179760566572,-13.5531003971814314],"rgb":[0.4,0.4,0.466666666666666674],"xyz":[0.135599496758432692,0.136593926761897855,0.193755077325038189],"hpluv":[265.874320218186085,39.4204575510779804,43.7404449074606489],"hsluv":[265.874320218186085,10.3527957183817456,43.7404449074606489]},"#666688":{"lch":[44.3831523723879684,27.7327571842679852,265.874320218181708],"luv":[44.3831523723879684,-1.9952189844931838,-27.660891566352042],"rgb":[0.4,0.4,0.533333333333333326],"xyz":[0.146739913860376547,0.141050093602675453,0.252427940728610356],"hpluv":[265.874320218181708,79.2892354857961692,44.3831523723879684],"hsluv":[265.874320218181708,21.2254167484079588,44.3831523723879684]},"#666699":{"lch":[45.1194249231942308,42.0446421145154,265.87432021818023],"luv":[45.1194249231942308,-3.02488020162380478,-41.9356892193690598],"rgb":[0.4,0.4,0.6],"xyz":[0.159796877969449247,0.14627287924630461,0.321194618369728291],"hpluv":[265.87432021818023,118.245992523098394,45.1194249231942308],"hsluv":[265.87432021818023,32.3647541960069702,45.1194249231942308]},"#6666aa":{"lch":[45.9470714788517682,56.2348015337582652,265.874320218179548],"luv":[45.9470714788517682,-4.04578393932889835,-56.0890767962662125],"rgb":[0.4,0.4,0.66666666666666663],"xyz":[0.174854570934701803,0.152295956432405705,0.400498467986726892],"hpluv":[265.874320218179548,155.305436018888514,45.9470714788517682],"hsluv":[265.874320218179548,43.5990379455573205,45.9470714788517682]},"#6666bb":{"lch":[46.8629040956598786,70.1103551977131,265.874320218179093],"luv":[46.8629040956598786,-5.04405352741049562,-69.9286738753289541],"rgb":[0.4,0.4,0.733333333333333282],"xyz":[0.191992163042038422,0.159150993275340463,0.490756453085368638],"hpluv":[265.874320218179093,189.841997809706953,46.8629040956598786],"hsluv":[265.874320218179093,54.8353857399755285,46.8629040956598786]},"#6666cc":{"lch":[47.8629477245616854,83.5592716582008,265.874320218178866],"luv":[47.8629477245616854,-6.01162892081844,-83.3427393224351505],"rgb":[0.4,0.4,0.8],"xyz":[0.211284538485760176,0.166867943452829265,0.592362963755638794],"hpluv":[265.874320218178866,221.531011478982748,47.8629477245616854],"hsluv":[265.874320218178866,66.0482344892977693,47.8629477245616854]},"#6666dd":{"lch":[48.9426439028117102,96.5306872715973583,265.874320218178696],"luv":[48.9426439028117102,-6.94485076081307,-96.2805413000828736],"rgb":[0.4,0.4,0.866666666666666696],"xyz":[0.23280286403639372,0.175475273673082799,0.705692811655644792],"hpluv":[265.874320218178696,250.274901054084751,48.9426439028117102],"hsluv":[265.874320218178696,77.2646968282616911,48.9426439028117102]},"#6666ee":{"lch":[50.0970402589656203,109.016062738443594,265.874320218178525],"luv":[50.0970402589656203,-7.84310469187671711,-108.73356263723052],"rgb":[0.4,0.4,0.933333333333333348],"xyz":[0.256615044302568429,0.185000145779552844,0.831103627724168],"hpluv":[265.874320218178525,276.132643737939816,50.0970402589656203],"hsluv":[265.874320218178525,88.5507283896609181,50.0970402589656203]},"#6666ff":{"lch":[51.3209595583197142,121.033610519319112,265.874320218178411],"luv":[51.3209595583197142,-8.70770100014002502,-120.719968599376287],"rgb":[0.4,0.4,1],"xyz":[0.28278609271239985,0.19546856514348554,0.96893781601594986],"hpluv":[265.874320218178411,299.261292593223402,51.3209595583197142],"hsluv":[265.874320218178411,99.9999999999991616,51.3209595583197142]},"#ddee00":{"lch":[90.1008574130140261,100.518542770188731,92.3281002120423295],"luv":[90.1008574130140261,-4.08324753875312307,100.435574027231638],"rgb":[0.866666666666666696,0.933333333333333348,0],"xyz":[0.603913249483671644,0.765213657712664919,0.115887903269964759],"hpluv":[92.3281002120423295,458.324419080212692,90.1008574130140261],"hsluv":[92.3281002120423295,100.000000000002288,90.1008574130140261]},"#ddee11":{"lch":[90.1195571422023676,99.6821059706602739,92.3717344777628284],"luv":[90.1195571422023676,-4.12512016496088219,99.5967149778072667],"rgb":[0.866666666666666696,0.933333333333333348,0.0666666666666666657],"xyz":[0.604924914983308804,0.765618323912519827,0.121216008234720396],"hpluv":[92.3717344777628284,455.439701471196656,90.1195571422023676],"hsluv":[92.3717344777628284,99.1349582088955827,90.1195571422023676]},"#ddee22":{"lch":[90.1542040339558213,98.139145338163118,92.4541942657322409],"luv":[90.1542040339558213,-4.20238430415396635,98.0491295925940562],"rgb":[0.866666666666666696,0.933333333333333348,0.133333333333333331],"xyz":[0.606800273121785749,0.766368467167910628,0.131092894430699575],"hpluv":[92.4541942657322409,450.094002053356689,90.1542040339558213],"hsluv":[92.4541942657322409,97.539848527320828,90.1542040339558213]},"#ddee33":{"lch":[90.2112004280082402,95.6198982889531237,92.5945991605726562],"luv":[90.2112004280082402,-4.32860020636881337,95.5218727257959728],"rgb":[0.866666666666666696,0.933333333333333348,0.2],"xyz":[0.609888023854243566,0.767603567460893754,0.147355048288310725],"hpluv":[92.5945991605726562,441.296742170845221,90.2112004280082402],"hsluv":[92.5945991605726562,94.9371734060285348,90.2112004280082402]},"#ddee44":{"lch":[90.2933822328294582,92.028546743238266,92.808164678773025],"luv":[90.2933822328294582,-4.50867173729536486,91.9180357429253689],"rgb":[0.866666666666666696,0.933333333333333348,0.266666666666666663],"xyz":[0.614346019098462426,0.76938676555858132,0.170833823241197363],"hpluv":[92.808164678773025,428.602609406071736,90.2933822328294582],"hsluv":[92.808164678773025,91.2305485856041827,90.2933822328294582]},"#ddee55":{"lch":[90.4030992965535,87.3081168904988658,93.1158428735316477],"luv":[90.4030992965535,-4.74562541158387852,87.1790474507375137],"rgb":[0.866666666666666696,0.933333333333333348,0.333333333333333315],"xyz":[0.620308433137824355,0.77177173117432607,0.202235870515171279],"hpluv":[93.1158428735316477,411.63119840797242,90.4030992965535],"hsluv":[93.1158428735316477,86.365058197250562,90.4030992965535]},"#ddee66":{"lch":[90.5423480313319828,81.4363754503924,93.5488244177654451],"luv":[90.5423480313319828,-5.04083628618753,81.2802141731499717],"rgb":[0.866666666666666696,0.933333333333333348,0.4],"xyz":[0.627893428911332596,0.774805729483729388,0.242183514922315241],"hpluv":[93.5488244177654451,390.03815237863023,90.5423480313319828],"hsluv":[93.5488244177654451,80.3228278296054583,90.5423480313319828]},"#ddee77":{"lch":[90.7128424721769449,74.4235139877598613,94.1564113073248],"luv":[90.7128424721769449,-5.39417557361030209,74.2277731322134855],"rgb":[0.866666666666666696,0.933333333333333348,0.466666666666666674],"xyz":[0.637207441931534446,0.77853133469181024,0.291237316828713122],"hpluv":[94.1564113073248,363.492124647987794,90.7128424721769449],"hsluv":[94.1564113073248,73.1200108954656116,90.7128424721769449]},"#ddee88":{"lch":[90.9160566530372449,66.3104835404903099,95.0215233218939801],"luv":[90.9160566530372449,-5.80415396856009735,66.0559764448523197],"rgb":[0.866666666666666696,0.933333333333333348,0.533333333333333326],"xyz":[0.648347859033478358,0.782987501532587782,0.349910180232285317],"hpluv":[95.0215233218939801,331.65301907995223,90.9160566530372449],"hsluv":[95.0215233218939801,64.803658473982523,90.9160566530372449]},"#ddee99":{"lch":[91.1532518637430798,57.1683554138076389,96.2947128608995513],"luv":[91.1532518637430798,-6.26808654843775237,56.8236918172404799],"rgb":[0.866666666666666696,0.933333333333333348,0.6],"xyz":[0.661404823142551,0.788210287176217,0.418676857873403252],"hpluv":[96.2947128608995513,294.152965661212647,91.1532518637430798],"hsluv":[96.2947128608995513,55.4479539090275679,91.1532518637430798]},"#ddeeaa":{"lch":[91.4254953447680805,47.1012792006961263,98.2790075719046712],"luv":[91.4254953447680805,-6.78228473243696595,46.6104185365255219],"rgb":[0.866666666666666696,0.933333333333333348,0.66666666666666663],"xyz":[0.676462516107803613,0.794233364362318062,0.497980707490401797],"hpluv":[98.2790075719046712,250.593114601078071,91.4254953447680805],"hsluv":[98.2790075719046712,45.1497304611624699,91.4254953447680805]},"#ddeebb":{"lch":[91.7336739482950634,36.2629153409390739,101.681625346389353],"luv":[91.7336739482950634,-7.34227032126066,35.5118303605101318],"rgb":[0.866666666666666696,0.933333333333333348,0.733333333333333282],"xyz":[0.693600108215140176,0.80108840120525282,0.588238692589043599],"hpluv":[101.681625346389353,200.613962446551909,91.7336739482950634],"hsluv":[101.681625346389353,34.0234190840686495,91.7336739482950634]},"#ddeecc":{"lch":[92.0785048140775189,24.9340669502590622,108.575873850927678],"luv":[92.0785048140775189,-7.94300120518182506,23.6350677285782567],"rgb":[0.866666666666666696,0.933333333333333348,0.8],"xyz":[0.712892483658861931,0.808805351382741677,0.689845203259313755],"hpluv":[108.575873850927678,144.339382081965653,92.0785048140775189],"hsluv":[108.575873850927678,22.1956929245148693,92.0785048140775189]},"#ddeedd":{"lch":[92.4605443140240908,14.0242187757329084,127.71501294922345],"luv":[92.4605443140240908,-8.57909621466854766,11.0940443666446207],"rgb":[0.866666666666666696,0.933333333333333348,0.866666666666666696],"xyz":[0.73441080920949553,0.817412681602995184,0.803175051159319753],"hpluv":[127.71501294922345,85.5555802205660854,92.4605443140240908],"hsluv":[127.71501294922345,19.0167034911391681,92.4605443140240908]},"#ddeeee":{"lch":[92.8801960589335636,9.45784403502816851,192.177050630058346],"luv":[92.8801960589335636,-9.24504689815110403,-1.99497409554724747],"rgb":[0.866666666666666696,0.933333333333333348,0.933333333333333348],"xyz":[0.758222989475670239,0.826937553709465201,0.928585867227843],"hpluv":[192.177050630058346,61.3009405779386327,92.8801960589335636],"hsluv":[192.177050630058346,16.5065503962475049,92.8801960589335636]},"#ddeeff":{"lch":[93.3377184761608305,18.4254994321377019,237.36941304521946],"luv":[93.3377184761608305,-9.93540601395951306,-15.5173044263971267],"rgb":[0.866666666666666696,0.933333333333333348,1],"xyz":[0.78439403788550166,0.837405973073397925,1.06642005551962482],"hpluv":[237.36941304521946,128.083838047846456,93.3377184761608305],"hsluv":[237.36941304521946,99.9999999999860592,93.3377184761608305]},"#667700":{"lch":[46.9985837429297462,53.5023535392226,97.7743932102929705],"luv":[46.9985837429297462,-7.23741162388150272,53.0105810873873509],"rgb":[0.4,0.466666666666666674,0],"xyz":[0.12075904236398749,0.160183725889588319,0.0245569097840955056],"hpluv":[97.7743932102929705,144.453291553004675,46.9985837429297462],"hsluv":[97.7743932102929705,100.000000000002416,46.9985837429297462]},"#667711":{"lch":[47.0515894602548315,51.4525286527524344,98.1592061252685681],"luv":[47.0515894602548315,-7.3023584206057679,50.9317019768564],"rgb":[0.4,0.466666666666666674,0.0666666666666666657],"xyz":[0.121770707863624608,0.160588392089443172,0.0298850147488511353],"hpluv":[98.1592061252685681,138.762383385982389,47.0515894602548315],"hsluv":[98.1592061252685681,95.8888552433840573,47.0515894602548315]},"#667722":{"lch":[47.1496128779850068,47.7434140964333835,98.9413563019921],"luv":[47.1496128779850068,-7.4204465613794337,47.1632331632727],"rgb":[0.4,0.466666666666666674,0.133333333333333331],"xyz":[0.123646066002101637,0.161338535344834,0.0397619009448303348],"hpluv":[98.9413563019921,128.491579290861381,47.1496128779850068],"hsluv":[98.9413563019921,88.4562635009272071,47.1496128779850068]},"#667733":{"lch":[47.3103471969426579,41.884713336750373,100.466311561708949],"luv":[47.3103471969426579,-7.6086666810921777,41.1878307590699961],"rgb":[0.4,0.466666666666666674,0.2],"xyz":[0.126733816734559357,0.162573635637817099,0.0560240548024414781],"hpluv":[100.466311561708949,112.341117260385403,47.3103471969426579],"hsluv":[100.466311561708949,76.7252257071794,47.3103471969426579]},"#667744":{"lch":[47.5409803755201068,33.9506682862991624,103.399633201782777],"luv":[47.5409803755201068,-7.86778476785512915,33.0264415269496823],"rgb":[0.4,0.466666666666666674,0.266666666666666663],"xyz":[0.131191811978778244,0.164356833735504693,0.0795028297553281166],"hpluv":[103.399633201782777,90.6190532449782324,47.5409803755201068],"hsluv":[103.399633201782777,60.8161329795325543,47.5409803755201068]},"#667755":{"lch":[47.8468512336942808,24.3055974565694441,109.700167733355244],"luv":[47.8468512336942808,-8.19336864569332768,22.8829800934354815],"rgb":[0.4,0.466666666666666674,0.333333333333333315],"xyz":[0.137154226018140257,0.166741799351249526,0.110904877029302018],"hpluv":[109.700167733355244,64.4602914823941262,47.8468512336942808],"hsluv":[109.700167733355244,41.23982633361328,47.8468512336942808]},"#667766":{"lch":[48.2317738399223543,14.0211946941261125,127.715012949232488],"luv":[48.2317738399223543,-8.57724628010491408,11.0916521267580634],"rgb":[0.4,0.466666666666666674,0.4],"xyz":[0.144739221791648415,0.169775797660652816,0.15085252143644598],"hpluv":[127.715012949232488,36.8885098590324958,48.2317738399223543],"hsluv":[127.715012949232488,18.7828263722028552,48.2317738399223543]},"#667777":{"lch":[48.6982180758881356,9.21652694043341,192.177050630059739],"luv":[48.6982180758881356,-9.00915932709454736,-1.94407228846053126],"rgb":[0.4,0.466666666666666674,0.466666666666666674],"xyz":[0.154053234811850348,0.17350140286873364,0.199906323342843889],"hpluv":[192.177050630059739,24.0156061835451808,48.6982180758881356],"hsluv":[192.177050630059739,23.9216020554503501,48.6982180758881356]},"#667788":{"lch":[49.2474401880289605,18.4334880243097601,239.056580638027469],"luv":[49.2474401880289605,-9.47834019220879398,-15.8099509152663327],"rgb":[0.4,0.466666666666666674,0.533333333333333326],"xyz":[0.165193651913794148,0.177957569709511237,0.258579186746416056],"hpluv":[239.056580638027469,47.4966726259429564,49.2474401880289605],"hsluv":[239.056580638027469,29.274081353383373,49.2474401880289605]},"#667799":{"lch":[49.8796002039077422,31.7351192214463786,251.680675473596239],"luv":[49.8796002039077422,-9.97474964621831,-30.126768188683684],"rgb":[0.4,0.466666666666666674,0.6],"xyz":[0.178250616022866876,0.183180355353140395,0.327345864387534],"hpluv":[251.680675473596239,80.734004933806176,49.8796002039077422],"hsluv":[251.680675473596239,34.661761655835349,49.8796002039077422]},"#6677aa":{"lch":[50.5938810850088174,45.7960576637453798,256.758518919433186],"luv":[50.5938810850088174,-10.4898463625666416,-44.5784928057335676],"rgb":[0.4,0.466666666666666674,0.66666666666666663],"xyz":[0.193308308988119404,0.18920343253924149,0.406649714004532592],"hpluv":[256.758518919433186,114.860161977636537,50.5938810850088174],"hsluv":[256.758518919433186,39.9381656359214858,50.5938810850088174]},"#6677bb":{"lch":[51.388614147457119,59.9444468574027738,259.409682348511467],"luv":[51.388614147457119,-11.0169047239158306,-58.9233783768730106],"rgb":[0.4,0.466666666666666674,0.733333333333333282],"xyz":[0.210445901095456078,0.196058469382176248,0.496907699103174338],"hpluv":[259.409682348511467,148.020333314730891,51.388614147457119],"hsluv":[259.409682348511467,49.2101017344363356,51.388614147457119]},"#6677cc":{"lch":[52.2614099661724225,73.9004259234932306,261.00752312302825],"luv":[52.2614099661724225,-11.5509895931656974,-72.9921063615257566],"rgb":[0.4,0.466666666666666674,0.8],"xyz":[0.229738276539177805,0.20377541955966505,0.598514209773444494],"hpluv":[261.00752312302825,179.434168102703751,52.2614099661724225],"hsluv":[261.00752312302825,61.6581230008595327,52.2614099661724225]},"#6677dd":{"lch":[53.2092913421323,87.5170631601914266,262.060353074135],"luv":[53.2092913421323,-12.0887245225321198,-86.6781349799548],"rgb":[0.4,0.466666666666666674,0.866666666666666696],"xyz":[0.251256602089811376,0.212382749779918584,0.711844057673450492],"hpluv":[262.060353074135,208.710638687620559,53.2092913421323],"hsluv":[262.060353074135,74.2459971892304083,53.2092913421323]},"#6677ee":{"lch":[54.2288239257805884,100.719531231348427,262.797438231409785],"luv":[54.2288239257805884,-12.6279723106459851,-99.9247631309883531],"rgb":[0.4,0.466666666666666674,0.933333333333333348],"xyz":[0.275068782355986086,0.221907621886388629,0.837254873741973715],"hpluv":[262.797438231409785,235.68005803746027,54.2288239257805884],"hsluv":[262.797438231409785,87.0042080584200193,54.2288239257805884]},"#6677ff":{"lch":[55.3162401631211793,113.47857319487936,263.336661992011841],"luv":[55.3162401631211793,-13.1675101506557386,-112.712036849566218],"rgb":[0.4,0.466666666666666674,1],"xyz":[0.301239830765817507,0.232376041250321325,0.97508906203375556],"hpluv":[263.336661992011841,260.315806593762318,55.3162401631211793],"hsluv":[263.336661992011841,99.999999999999,55.3162401631211793]},"#ddff00":{"lch":[94.69236188875891,107.73563953931891,97.6513944636985],"luv":[94.69236188875891,-14.3445112693176284,106.77641604488548],"rgb":[0.866666666666666696,1,0],"xyz":[0.65576562191334542,0.868918402572014,0.13317202741318887],"hpluv":[97.6513944636985,949.977135711580445,94.69236188875891],"hsluv":[97.6513944636985,100.000000000002302,94.69236188875891]},"#ddff11":{"lch":[94.7095428290633237,106.965998536257018,97.7198690947758308],"luv":[94.7095428290633237,-14.3687245726656343,105.996531061225838],"rgb":[0.866666666666666696,1,0.0666666666666666657],"xyz":[0.65677728741298258,0.869323068771868934,0.138500132377944507],"hpluv":[97.7198690947758308,946.378692368412885,94.7095428290633237],"hsluv":[97.7198690947758308,99.9999999999867697,94.7095428290633237]},"#ddff22":{"lch":[94.7413776147606086,105.545731309599958,97.8489007917202827],"luv":[94.7413776147606086,-14.4134418215914106,104.556941866783148],"rgb":[0.866666666666666696,1,0.133333333333333331],"xyz":[0.658652645551459526,0.870073212027259735,0.148377018573923686],"hpluv":[97.8489007917202827,939.695870823628752,94.7413776147606086],"hsluv":[97.8489007917202827,99.9999999999872,94.7413776147606086]},"#ddff33":{"lch":[94.7937532988665197,103.225383790498825,98.0674915546983],"luv":[94.7937532988665197,-14.4865977424562669,102.203807876928138],"rgb":[0.866666666666666696,1,0.2],"xyz":[0.661740396283917343,0.871308312320242861,0.164639172431534836],"hpluv":[98.0674915546983,928.656435156239354,94.7937532988665197],"hsluv":[98.0674915546983,99.9999999999868834,94.7937532988665197]},"#ddff44":{"lch":[94.8692843830354491,99.9146373114600692,98.397314807396512],"luv":[94.8692843830354491,-14.5912004882884094,98.8434702820129729],"rgb":[0.866666666666666696,1,0.266666666666666663],"xyz":[0.666198391528136202,0.873091510417930428,0.188117947384421474],"hpluv":[98.397314807396512,912.633071017653265,94.8692843830354491],"hsluv":[98.397314807396512,99.9999999999866276,94.8692843830354491]},"#ddff55":{"lch":[94.9701440016210654,95.558111661139634,98.8668834316730738],"luv":[94.9701440016210654,-14.7292629682473848,94.4161083536863828],"rgb":[0.866666666666666696,1,0.333333333333333315],"xyz":[0.672160805567498132,0.875476476033675177,0.21951999465839539],"hpluv":[98.8668834316730738,891.031026100052486,94.9701440016210654],"hsluv":[98.8668834316730738,99.9999999999861586,94.9701440016210654]},"#ddff66":{"lch":[95.0981866754888,90.1320341607989235,99.5166683548804798],"luv":[95.0981866754888,-14.9019372161492765,88.8915960547979438],"rgb":[0.866666666666666696,1,0.4],"xyz":[0.679745801341006373,0.878510474343078496,0.259467639065539379],"hpluv":[99.5166683548804798,863.234823568518,95.0981866754888],"hsluv":[99.5166683548804798,99.9999999999856186,95.0981866754888]},"#ddff77":{"lch":[95.2550143462764396,83.6430269583913599,100.407261812829162],"luv":[95.2550143462764396,-15.1095945804084604,82.2669806810598487],"rgb":[0.866666666666666696,1,0.466666666666666674],"xyz":[0.689059814361208223,0.882236079551159347,0.308521440971937233],"hpluv":[100.407261812829162,828.556184265804632,95.2550143462764396],"hsluv":[100.407261812829162,99.9999999999855476,95.2550143462764396]},"#ddff88":{"lch":[95.4420158908659175,76.1281736437493,101.633961649281417],"luv":[95.4420158908659175,-15.3518949618923237,74.5641880758576434],"rgb":[0.866666666666666696,1,0.533333333333333326],"xyz":[0.700200231463152134,0.886692246391936889,0.367194304375509428],"hpluv":[101.633961649281417,786.17501332264635,95.4420158908659175],"hsluv":[101.633961649281417,99.9999999999848512,95.4420158908659175]},"#ddff99":{"lch":[95.6603925662724208,67.6570848719276086,103.355147801887099],"luv":[95.6603925662724208,-15.6278614338241617,65.8274341013866859],"rgb":[0.866666666666666696,1,0.6],"xyz":[0.713257195572224778,0.891915032035566102,0.435960982016627363],"hpluv":[103.355147801887099,735.074270676232231,95.6603925662724208],"hsluv":[103.355147801887099,99.9999999999844107,95.6603925662724208]},"#ddffaa":{"lch":[95.9111754000973775,58.338925144698,105.852499131344544],"luv":[95.9111754000973775,-15.935965587620279,56.1201852084333268],"rgb":[0.866666666666666696,1,0.66666666666666663],"xyz":[0.72831488853747739,0.897938109221667169,0.515264831633625908],"hpluv":[105.852499131344544,673.992295850936557,95.9111754000973775],"hsluv":[105.852499131344544,99.9999999999831886,95.9111754000973775]},"#ddffbb":{"lch":[96.1952377631310185,48.3433070572267596,109.672211431084662],"luv":[96.1952377631310185,-16.2742233848326485,45.5216980180866813],"rgb":[0.866666666666666696,1,0.733333333333333282],"xyz":[0.745452480644814,0.904793146064601927,0.60552281673226771],"hpluv":[109.672211431084662,601.502194015230771,96.1952377631310185],"hsluv":[109.672211431084662,99.9999999999821654,96.1952377631310185]},"#ddffcc":{"lch":[96.513305005727517,37.9644197829535202,115.996292551248089],"luv":[96.513305005727517,-16.6402982513575566,34.1232712904577653],"rgb":[0.866666666666666696,1,0.8],"xyz":[0.764744856088535707,0.912510096242090785,0.707129327402537866],"hpluv":[115.996292551248089,516.693096965009204,96.513305005727517],"hsluv":[115.996292551248089,99.9999999999804885,96.513305005727517]},"#ddffdd":{"lch":[96.8659623148576,27.841508205801528,127.715012949232161],"luv":[96.8659623148576,-17.0316066426751398,22.0243945284064],"rgb":[0.866666666666666696,1,0.866666666666666696],"xyz":[0.786263181639169306,0.921117426462344291,0.820459175302543864],"hpluv":[127.715012949232161,422.676993554754517,96.8659623148576],"hsluv":[127.715012949232161,99.9999999999786411,96.8659623148576]},"#ddffee":{"lch":[97.2536615310726802,19.7831433293950418,151.864226334417424],"luv":[97.2536615310726802,-17.4454209009420502,9.32898974060759478],"rgb":[0.866666666666666696,1,0.933333333333333348],"xyz":[0.810075361905344,0.930642298568814308,0.945869991371067087],"hpluv":[151.864226334417424,343.73229759561508,97.2536615310726802],"hsluv":[151.864226334417424,99.9999999999752,97.2536615310726802]},"#ddffff":{"lch":[97.6767274082888406,18.2904922799610645,192.177050630059568],"luv":[97.6767274082888406,-17.878964623675607,-3.85807359036494368],"rgb":[0.866666666666666696,1,1],"xyz":[0.836246410315175437,0.941110717932747,1.08370417966284882],"hpluv":[192.177050630059568,376.852754928906336,97.6767274082888406],"hsluv":[192.177050630059568,99.9999999999715072,97.6767274082888406]},"#668800":{"lch":[52.32310792684153,62.4331707825390509,105.73052795354684],"luv":[52.32310792684153,-16.9264656143939405,60.0948881001240167],"rgb":[0.4,0.533333333333333326,0],"xyz":[0.142831412088957943,0.204328465339529863,0.0319143663590854554],"hpluv":[105.73052795354684,151.412310196323318,52.32310792684153],"hsluv":[105.73052795354684,100.000000000002359,52.32310792684153]},"#668811":{"lch":[52.3681821172622222,60.6739112189649603,106.201766876928076],"luv":[52.3681821172622222,-16.9292783492562116,58.26425179456308],"rgb":[0.4,0.533333333333333326,0.0666666666666666657],"xyz":[0.143843077588595075,0.204733131539384716,0.0372424713238410851],"hpluv":[106.201766876928076,147.019120365759306,52.3681821172622222],"hsluv":[106.201766876928076,96.7617570127925859,52.3681821172622222]},"#668822":{"lch":[52.4515808002199,57.4815115963739842,107.134347730867304],"luv":[52.4515808002199,-16.9348150675510247,54.9302850350507796],"rgb":[0.4,0.533333333333333326,0.133333333333333331],"xyz":[0.145718435727072076,0.205483274794775544,0.0471193575198202846],"hpluv":[107.134347730867304,139.062145386582984,52.4515808002199],"hsluv":[107.134347730867304,90.8761910280814647,52.4515808002199]},"#668833":{"lch":[52.5884544541714121,52.4173031151438593,108.860637572968898],"luv":[52.5884544541714121,-16.9448041098426323,49.6028958786070291],"rgb":[0.4,0.533333333333333326,0.2],"xyz":[0.14880618645952981,0.206718375087758643,0.0633815113774314209],"hpluv":[108.860637572968898,126.480505252334424,52.5884544541714121],"hsluv":[108.860637572968898,81.504484256448066,52.5884544541714121]},"#668844":{"lch":[52.7851097594501937,45.5231929703366234,111.874794573011059],"luv":[52.7851097594501937,-16.9610118856818559,42.2455343678863215],"rgb":[0.4,0.533333333333333326,0.266666666666666663],"xyz":[0.153264181703748698,0.208501573185446237,0.0868602863303180595],"hpluv":[111.874794573011059,109.436101408621766,52.7851097594501937],"hsluv":[111.874794573011059,68.6312430201703734,52.7851097594501937]},"#668855":{"lch":[53.0463844713544859,37.0894540992544819,117.255878513522262],"luv":[53.0463844713544859,-16.9856764955971045,32.9714179156375593],"rgb":[0.4,0.533333333333333326,0.333333333333333315],"xyz":[0.15922659574311071,0.21088653880119107,0.118262333604291975],"hpluv":[117.255878513522262,88.7225425584692715,53.0463844713544859],"hsluv":[117.255878513522262,52.5261258187504225,53.0463844713544859]},"#668866":{"lch":[53.3759296841588906,27.8248149657310222,127.715012949236794],"luv":[53.3759296841588906,-17.0213948144824521,22.0111891193247189],"rgb":[0.4,0.533333333333333326,0.4],"xyz":[0.166811591516618868,0.213920537110594361,0.158209978011435937],"hpluv":[127.715012949236794,66.1494380276081415,53.3759296841588906],"hsluv":[127.715012949236794,33.681854155652033,53.3759296841588906]},"#668877":{"lch":[53.7763606180623839,19.6211535767711887,150.461713858693599],"luv":[53.7763606180623839,-17.0709226847205855,9.67332757511772101],"rgb":[0.4,0.533333333333333326,0.466666666666666674],"xyz":[0.176125604536820801,0.217646142318675184,0.207263779917833846],"hpluv":[150.461713858693599,46.2990901048939207,53.7763606180623839],"hsluv":[150.461713858693599,37.1484166060608132,53.7763606180623839]},"#668888":{"lch":[54.2493559855519436,17.5313913512660982,192.17705063006045],"luv":[54.2493559855519436,-17.1369431164247104,-3.69795393909545],"rgb":[0.4,0.533333333333333326,0.533333333333333326],"xyz":[0.187266021638764601,0.222102309159452782,0.265936643321406],"hpluv":[192.17705063006045,41.0072951616226788,54.2493559855519436],"hsluv":[192.17705063006045,40.8467805779917228,54.2493559855519436]},"#668899":{"lch":[54.7957384612029728,24.7393499057112685,225.882505108050964],"luv":[54.7957384612029728,-17.2218541013304964,-17.7607200042594577],"rgb":[0.4,0.533333333333333326,0.6],"xyz":[0.200322985747837329,0.22732509480308194,0.33470332096252392],"hpluv":[225.882505108050964,57.2902642666713859,54.7957384612029728],"hsluv":[225.882505108050964,44.6631352998217963,54.7957384612029728]},"#6688aa":{"lch":[55.4155508256813363,36.5699037808867828,241.717344836465486],"luv":[55.4155508256813363,-17.3276119763631087,-32.2042190673817643],"rgb":[0.4,0.533333333333333326,0.66666666666666663],"xyz":[0.215380678713089857,0.233348171989183034,0.414007170579522521],"hpluv":[241.717344836465486,83.7397171719788389,55.4155508256813363],"hsluv":[241.717344836465486,48.4952118884804193,55.4155508256813363]},"#6688bb":{"lch":[56.1081340603271457,49.918102431374308,249.531909378681803],"luv":[56.1081340603271457,-17.4556451944419777,-46.7666270025424495],"rgb":[0.4,0.533333333333333326,0.733333333333333282],"xyz":[0.232518270820426531,0.240203208832117793,0.504265155678164323],"hpluv":[249.531909378681803,112.8941838879785,56.1081340603271457],"hsluv":[249.531909378681803,52.2580147864780216,56.1081340603271457]},"#6688cc":{"lch":[56.8722093096567107,63.7230017864969795,253.960340799970709],"luv":[56.8722093096567107,-17.6068348542363715,-61.2423082770199372],"rgb":[0.4,0.533333333333333326,0.8],"xyz":[0.251810646264148286,0.247920159009606594,0.605871666348434479],"hpluv":[253.960340799970709,142.178999158492672,56.8722093096567107],"hsluv":[253.960340799970709,56.6402695601832349,56.8722093096567107]},"#6688dd":{"lch":[57.7059632125805564,77.5471512008463719,256.744147904563079],"luv":[57.7059632125805564,-17.7815469636593271,-75.4809727477468755],"rgb":[0.4,0.533333333333333326,0.866666666666666696],"xyz":[0.273328971814781774,0.256527489229860128,0.719201514248440477],"hpluv":[256.744147904563079,170.523595036459966,57.7059632125805564],"hsluv":[256.744147904563079,70.7529337108087475,57.7059632125805564]},"#6688ee":{"lch":[58.6071348177704721,91.1720868217648501,258.626369492504523],"luv":[58.6071348177704721,-17.979697586292076,-89.3816529839368599],"rgb":[0.4,0.533333333333333326,0.933333333333333348],"xyz":[0.297141152080956539,0.266052361336330145,0.8446123303169637],"hpluv":[258.626369492504523,197.40162879311913,58.6071348177704721],"hsluv":[258.626369492504523,85.1920367601911295,58.6071348177704721]},"#6688ff":{"lch":[59.57310174908622,104.481663139573541,259.967822360236937],"luv":[59.57310174908622,-18.2008336002305597,-102.884146439906075],"rgb":[0.4,0.533333333333333326,1],"xyz":[0.323312200490787904,0.276520780700262869,0.982446518608745434],"hpluv":[259.967822360236937,222.550815911907222,59.57310174908622],"hsluv":[259.967822360236937,99.9999999999987352,59.57310174908622]},"#669900":{"lch":[57.6618978033021961,71.9113437902946373,111.072092359847389],"luv":[57.6618978033021961,-25.8551729794803826,67.1025438856612624],"rgb":[0.4,0.6,0],"xyz":[0.168701012541425444,0.25606766624446553,0.0405375665099077104],"hpluv":[111.072092359847389,158.251486754186431,57.6618978033021961],"hsluv":[111.072092359847389,100.000000000002444,57.6618978033021961]},"#669911":{"lch":[57.7006802499588929,70.3894808316696867,111.521292839157113],"luv":[57.7006802499588929,-25.8221679479897865,65.4820177928093727],"rgb":[0.4,0.6,0.0666666666666666657],"xyz":[0.169712678041062576,0.256472332444320383,0.0458656714746633401],"hpluv":[111.521292839157113,154.798288730060023,57.7006802499588929],"hsluv":[111.521292839157113,97.4070268725327821,57.7006802499588929]},"#669922":{"lch":[57.7724648019637499,67.6202459496272326,112.394641072548438],"luv":[57.7724648019637499,-25.7622250908158499,62.5204400229094404],"rgb":[0.4,0.6,0.133333333333333331],"xyz":[0.171588036179539577,0.257222475699711184,0.0557425576706425396],"hpluv":[112.394641072548438,148.523500329687067,57.7724648019637499],"hsluv":[112.394641072548438,92.6757293451634183,57.7724648019637499]},"#669933":{"lch":[57.8903535973237524,63.206621217633213,113.958803391015238],"luv":[57.8903535973237524,-25.6669247559924365,57.7605915769530824],"rgb":[0.4,0.6,0.2],"xyz":[0.174675786911997311,0.258457575992694311,0.0720047115282536898],"hpluv":[113.958803391015238,138.546544821103367,57.8903535973237524],"hsluv":[113.958803391015238,85.092275495173979,57.8903535973237524]},"#669944":{"lch":[58.0598969225296457,57.1535921702901888,116.538768682419729],"luv":[58.0598969225296457,-25.5364113217858204,51.131446241744662],"rgb":[0.4,0.6,0.266666666666666663],"xyz":[0.179133782156216198,0.260240774090381877,0.0954834864811403283],"hpluv":[116.538768682419729,124.912700512594284,58.0598969225296457],"hsluv":[116.538768682419729,74.5746503624431796,58.0598969225296457]},"#669955":{"lch":[58.2854489010818355,49.6561447471622515,120.7300937454592],"luv":[58.2854489010818355,-25.3740154630121886,42.6836274282534163],"rgb":[0.4,0.6,0.333333333333333315],"xyz":[0.185096196195578211,0.262625739706126737,0.126885533755114244],"hpluv":[120.7300937454592,108.106592630407334,58.2854489010818355],"hsluv":[120.7300937454592,61.2495338993745833,58.2854489010818355]},"#669966":{"lch":[58.5704165792398754,41.1710358166226,127.715012949238272],"luv":[58.5704165792398754,-25.1857364161826034,32.5688942303571949],"rgb":[0.4,0.6,0.4],"xyz":[0.192681191969086368,0.265659738015530056,0.166833178162258178],"hpluv":[127.715012949238272,89.1975256314243552,58.5704165792398754],"hsluv":[127.715012949238272,45.4174387408809324,58.5704165792398754]},"#669977":{"lch":[58.9173908027988489,32.643461159974926,139.926834832055846],"luv":[58.9173908027988489,-24.9795271581232114,21.0147276798767138],"rgb":[0.4,0.6,0.466666666666666674],"xyz":[0.201995204989288302,0.269385343223610851,0.215886980068656087],"hpluv":[139.926834832055846,70.3059403526018514,58.9173908027988489],"hsluv":[139.926834832055846,47.7876005322921813,58.9173908027988489]},"#669988":{"lch":[59.328227692638464,26.116847909850911,161.480821243886396],"luv":[59.328227692638464,-24.7644493579715288,8.29528738156475498],"rgb":[0.4,0.6,0.533333333333333326],"xyz":[0.213135622091232102,0.273841510064388449,0.274559843472228282],"hpluv":[161.480821243886396,55.8597144892801083,59.328227692638464],"hsluv":[161.480821243886396,50.3655359274122105,59.328227692638464]},"#669999":{"lch":[59.8041090330486043,25.1148951486962346,192.17705063006062],"luv":[59.8041090330486043,-24.5498215694726056,-5.29756729424584893],"rgb":[0.4,0.6,0.6],"xyz":[0.226192586200304829,0.279064295708017607,0.343326521113346161],"hpluv":[192.17705063006062,53.2892577697712042,59.8041090330486043],"hsluv":[192.17705063006062,53.0806679813151447,59.8041090330486043]},"#6699aa":{"lch":[60.3455948386344119,31.1785657150768039,218.6653689057203],"luv":[60.3455948386344119,-24.3444790905776323,-19.4794583563761137],"rgb":[0.4,0.6,0.66666666666666663],"xyz":[0.241250279165557358,0.285087372894118729,0.422630370730344762],"hpluv":[218.6653689057203,65.5616517705923911,60.3455948386344119],"hsluv":[218.6653689057203,55.8649153078387357,60.3455948386344119]},"#6699bb":{"lch":[60.9526745558420231,41.7013653705125407,234.60099737489486],"luv":[60.9526745558420231,-24.1562241025528444,-33.9923625373734168],"rgb":[0.4,0.6,0.733333333333333282],"xyz":[0.258387871272894032,0.291942409737053488,0.512888355828986509],"hpluv":[234.60099737489486,86.8154127469588,60.9526745558420231],"hsluv":[234.60099737489486,58.6571249967150123,60.9526745558420231]},"#6699cc":{"lch":[61.6248198105828493,54.2138016672169485,243.734276496040906],"luv":[61.6248198105828493,-23.9914938552849968,-48.6162988492970101],"rgb":[0.4,0.6,0.8],"xyz":[0.277680246716615731,0.299659359914542289,0.614494866499256664],"hpluv":[243.734276496040906,111.633239234030881,61.6248198105828493],"hsluv":[243.734276496040906,61.4057918386087067,61.6248198105828493]},"#6699dd":{"lch":[62.361039595623,67.5283063616342361,249.312993820438976],"luv":[62.361039595623,-23.8552311607989473,-63.1743627299522288],"rgb":[0.4,0.6,0.866666666666666696],"xyz":[0.29919857226724933,0.308266690134795796,0.727824714399262662],"hpluv":[249.312993820438976,137.407942777337979,62.361039595623],"hsluv":[249.312993820438976,66.62550454031512,62.361039595623]},"#6699ee":{"lch":[63.1599376048740453,81.0888167917790526,252.968345076420633],"luv":[63.1599376048740453,-23.7509145884581336,-77.5325110189427278],"rgb":[0.4,0.6,0.933333333333333348],"xyz":[0.323010752533424039,0.317791562241265813,0.853235530467785885],"hpluv":[252.968345076420633,162.914071535813093,63.1599376048740453],"hsluv":[252.968345076420633,83.0301883133999183,63.1599376048740453]},"#6699ff":{"lch":[64.0197707514621186,94.6074384193794771,255.504450424431923],"luv":[64.0197707514621186,-23.6806962224400728,-91.5958079318982499],"rgb":[0.4,0.6,1],"xyz":[0.34918180094325546,0.328259981605198536,0.99106971875956773],"hpluv":[255.504450424431923,187.521252715437782,64.0197707514621186],"hsluv":[255.504450424431923,99.9999999999985079,64.0197707514621186]},"#550000":{"lch":[15.1243819173422267,50.8637728648741643,12.1770506300617765],"luv":[15.1243819173422267,49.7193613905117289,10.7288626130266547],"rgb":[0.333333333333333315,0,0],"xyz":[0.0374622858816120868,0.019316491157706641,0.00175604465070052949],"hpluv":[12.1770506300617765,426.746789183125202,15.1243819173422267],"hsluv":[12.1770506300617765,100.000000000002203,15.1243819173422267]},"#550011":{"lch":[15.3402258633588957,47.2707050856887108,7.4875089370669734],"luv":[15.3402258633588957,46.8676416739534929,6.15984766208174239],"rgb":[0.333333333333333315,0,0.0666666666666666657],"xyz":[0.0384739513812492051,0.0197211573575614939,0.00708414961545616138],"hpluv":[7.4875089370669734,391.020613457768548,15.3402258633588957],"hsluv":[7.4875089370669734,99.9999999999966889,15.3402258633588957]},"#550022":{"lch":[15.7326592199860933,42.4312907985821823,358.411234527054887],"luv":[15.7326592199860933,42.4149789665186745,-1.17643448760390168],"rgb":[0.333333333333333315,0,0.133333333333333331],"xyz":[0.0403493095197262272,0.0204713006129523117,0.0169610358114353557],"hpluv":[358.411234527054887,342.234221563623748,15.7326592199860933],"hsluv":[358.411234527054887,99.9999999999971578,15.7326592199860933]},"#550033":{"lch":[16.358416636328208,38.360101220613565,343.406058671947278],"luv":[16.358416636328208,36.7625096026365128,-10.9551473459637485],"rgb":[0.333333333333333315,0,0.2],"xyz":[0.0434370602521839677,0.0217064009059354281,0.0332231896690465],"hpluv":[343.406058671947278,297.562230749163234,16.358416636328208],"hsluv":[343.406058671947278,99.9999999999977547,16.358416636328208]},"#550044":{"lch":[17.2212923868602061,37.8614359764106112,324.728975934647224],"luv":[17.2212923868602061,30.9112016871952413,-21.8628896637516235],"rgb":[0.333333333333333315,0,0.266666666666666663],"xyz":[0.0478950554964028483,0.0234895990036230046,0.0567019646219331375],"hpluv":[324.728975934647224,278.978456842737614,17.2212923868602061],"hsluv":[324.728975934647224,99.9999999999983089,17.2212923868602061]},"#550055":{"lch":[18.3096014215038,41.7063030886972754,307.715012949243544],"luv":[18.3096014215038,25.5131777875110508,-32.9923245090298636],"rgb":[0.333333333333333315,0,0.333333333333333315],"xyz":[0.0538574695357648403,0.025874564619367834,0.0881040118959070528],"hpluv":[307.715012949243544,289.042783730483393,18.3096014215038],"hsluv":[307.715012949243544,99.9999999999988,18.3096014215038]},"#550066":{"lch":[19.6013792550641099,48.6148100748190828,295.355623011865077],"luv":[19.6013792550641099,20.818580180871372,-43.9316113733990079],"rgb":[0.333333333333333315,0,0.4],"xyz":[0.0614424653092730116,0.028908562928771149,0.128051656303051015],"hpluv":[295.355623011865077,314.717786655224245,19.6013792550641099],"hsluv":[295.355623011865077,99.9999999999992468,19.6013792550641099]},"#550077":{"lch":[21.069395574911745,57.1127554515679421,287.139622223683091],"luv":[21.069395574911745,16.83119884103942,-54.5763463493480572],"rgb":[0.333333333333333315,0,0.466666666666666674],"xyz":[0.0707564783294749311,0.0326341681368519654,0.177105458209448924],"hpluv":[287.139622223683091,343.969838941793114,21.069395574911745],"hsluv":[287.139622223683091,99.9999999999995737,21.069395574911745]},"#550088":{"lch":[22.6852054601189934,66.3294491167530822,281.703433904835379],"luv":[22.6852054601189934,13.454662288017035,-64.9505033302079084],"rgb":[0.333333333333333315,0,0.533333333333333326],"xyz":[0.0818968954314187592,0.0370903349776295563,0.235778321613021091],"hpluv":[281.703433904835379,371.024851449370942,22.6852054601189934],"hsluv":[281.703433904835379,99.9999999999998721,22.6852054601189934]},"#550099":{"lch":[24.4218644362266417,75.8503102235033424,278.01254475278904],"luv":[24.4218644362266417,10.5727682252252198,-75.1098271403773339],"rgb":[0.333333333333333315,0,0.6],"xyz":[0.0949538595404914726,0.0423131206212587208,0.304544999254138971],"hpluv":[278.01254475278904,394.110378481836165,24.4218644362266417],"hsluv":[278.01254475278904,100.000000000000071,24.4218644362266417]},"#5500aa":{"lch":[26.2553935553790794,85.4876195151354,275.424483319872081],"luv":[26.2553935553790794,8.0814629277942,-85.1047768771603614],"rgb":[0.333333333333333315,0,0.66666666666666663],"xyz":[0.110011552505744015,0.0483361978073598153,0.383848848871137571],"hpluv":[275.424483319872081,413.165469396605374,26.2553935553790794],"hsluv":[275.424483319872081,100.00000000000027,26.2553935553790794]},"#5500bb":{"lch":[28.1653177219846,95.1546470205467756,273.553022331801344],"luv":[28.1653177219846,5.89694295360029841,-94.9717479748942708],"rgb":[0.333333333333333315,0,0.733333333333333282],"xyz":[0.127149144613080661,0.0551912346502945739,0.474106833969779318],"hpluv":[273.553022331801344,428.701175528050442,28.1653177219846],"hsluv":[273.553022331801344,100.000000000000355,28.1653177219846]},"#5500cc":{"lch":[30.1346298593711452,104.80902699908826,272.162345307959299],"luv":[30.1346298593711452,3.95455850560158062,-104.734395532324456],"rgb":[0.333333333333333315,0,0.8],"xyz":[0.146441520056802388,0.0629081848277833755,0.575713344640049529],"hpluv":[272.162345307959299,441.338845171454864,30.1346298593711452],"hsluv":[272.162345307959299,100.000000000000441,30.1346298593711452]},"#5500dd":{"lch":[32.1494591091083208,114.428501102308275,271.104225820707256],"luv":[32.1494591091083208,2.20517261265448461,-114.407250986418532],"rgb":[0.333333333333333315,0,0.866666666666666696],"xyz":[0.167959845607435931,0.0715155150480369095,0.689043192540055527],"hpluv":[271.104225820707256,451.647764573950099,32.1494591091083208],"hsluv":[271.104225820707256,100.000000000000483,32.1494591091083208]},"#5500ee":{"lch":[34.1986254005705774,124.000502171291956,270.282536199645165],"luv":[34.1986254005705774,0.611467178704377612,-123.998994538754019],"rgb":[0.333333333333333315,0,0.933333333333333348],"xyz":[0.191772025873610696,0.0810403871545069404,0.81445400860857875],"hpluv":[270.282536199645165,460.101999214721616,34.1986254005705774],"hsluv":[270.282536199645165,100.000000000000597,34.1986254005705774]},"#5500ff":{"lch":[36.2731838611955055,133.517545782829444,269.6330586770423],"luv":[36.2731838611955055,-0.855085145745556,-133.514807647929],"rgb":[0.333333333333333315,0,1],"xyz":[0.217943074283442062,0.0915088065184396504,0.952288196900360595],"hpluv":[269.6330586770423,467.080772865482345,36.2731838611955055],"hsluv":[269.6330586770423,100.000000000000668,36.2731838611955055]},"#551100":{"lch":[17.1436512350983392,46.6418802884309827,16.9386517648024579],"luv":[17.1436512350983392,44.618427652544149,13.5889996193616174],"rgb":[0.333333333333333315,0.0666666666666666657,0],"xyz":[0.0394666861425404941,0.0233252916795635146,0.00242417807100998037],"hpluv":[16.9386517648024579,345.232802292268,17.1436512350983392],"hsluv":[16.9386517648024579,100.000000000002245,17.1436512350983392]},"#551111":{"lch":[17.3342210988239742,43.3325537190722372,12.1770506300618173],"luv":[17.3342210988239742,42.3575912084996133,9.14027783111198566],"rgb":[0.333333333333333315,0.0666666666666666657,0.0666666666666666657],"xyz":[0.0404783516421776124,0.0237299578794183674,0.0077522830357656114],"hpluv":[12.1770506300618173,317.211759513802576,17.3342210988239742],"hsluv":[12.1770506300618173,74.3325474389658751,17.3342210988239742]},"#551122":{"lch":[17.681833534927847,38.7809423842287515,2.75476418742331486],"luv":[17.681833534927847,38.7361268795629599,1.86385798259144919],"rgb":[0.333333333333333315,0.0666666666666666657,0.133333333333333331],"xyz":[0.0423537097806546345,0.0244801011348091888,0.0176291692317448075],"hpluv":[2.75476418742331486,278.311009894887945,17.681833534927847],"hsluv":[2.75476418742331486,76.7057995287142234,17.681833534927847]},"#551133":{"lch":[18.2390179286851222,34.9181665436168771,346.660743506282301],"luv":[18.2390179286851222,33.9761101882180157,-8.05619582966011727],"rgb":[0.333333333333333315,0.0666666666666666657,0.2],"xyz":[0.045441460513112375,0.0257152014277923,0.0338913230893559542],"hpluv":[346.660743506282301,242.9345634355779,18.2390179286851222],"hsluv":[346.660743506282301,79.7834922439867285,18.2390179286851222]},"#551144":{"lch":[19.0128230091186055,34.7408929356053093,326.164658676814156],"luv":[19.0128230091186055,28.8572161490225767,-19.3440098762325228],"rgb":[0.333333333333333315,0.0666666666666666657,0.266666666666666663],"xyz":[0.0498994557573312555,0.0274983995254798746,0.0573700980422425927],"hpluv":[326.164658676814156,231.864199750183133,19.0128230091186055],"hsluv":[326.164658676814156,83.0221027238197706,19.0128230091186055]},"#551155":{"lch":[19.9971255718025702,39.1813209297373,307.715012949243771],"luv":[19.9971255718025702,23.9685594933690105,-30.9949038651824331],"rgb":[0.333333333333333315,0.0666666666666666657,0.333333333333333315],"xyz":[0.0558618697966932476,0.0298833651412247076,0.0887721453162165],"hpluv":[307.715012949243771,248.628452083429778,19.9971255718025702],"hsluv":[307.715012949243771,86.0178721207098391,19.9971255718025702]},"#551166":{"lch":[21.1763147828962417,46.7756191769153702,294.771362117319313],"luv":[21.1763147828962417,19.5989049109657927,-42.4716549674572263],"rgb":[0.333333333333333315,0.0666666666666666657,0.4],"xyz":[0.0634468655702014189,0.0329173634506280191,0.128719789723360456],"hpluv":[294.771362117319313,280.29057047770084,21.1763147828962417],"hsluv":[294.771362117319313,88.5810746573468464,21.1763147828962417]},"#551177":{"lch":[22.529041607596703,55.8726050260016436,286.442196236272423],"luv":[22.529041607596703,15.8146223861076685,-53.5877384405836494],"rgb":[0.333333333333333315,0.0666666666666666657,0.466666666666666674],"xyz":[0.0727608785904033384,0.0366429686587088355,0.177773591629758365],"hpluv":[286.442196236272423,314.699121073082495,22.529041607596703],"hsluv":[286.442196236272423,90.6792509168865166,22.529041607596703]},"#551188":{"lch":[24.0315326783493077,65.5523157673088548,281.05474383939486],"luv":[24.0315326783493077,12.5694476912001676,-64.3359548557037613],"rgb":[0.333333333333333315,0.0666666666666666657,0.533333333333333326],"xyz":[0.0839012956923471664,0.0410991354994864333,0.236446455033330533],"hpluv":[281.05474383939486,346.135302225987516,24.0315326783493077],"hsluv":[281.05474383939486,92.3586421581981654,24.0315326783493077]},"#551199":{"lch":[25.6600874124784752,75.409923320082811,277.450872837297311],"luv":[25.6600874124784752,9.77886091464338847,-74.7731931533810439],"rgb":[0.333333333333333315,0.0666666666666666657,0.6],"xyz":[0.0969582598014198799,0.0463219211431155908,0.30521313267444844],"hpluv":[277.450872837297311,372.914863977489176,25.6600874124784752],"hsluv":[277.450872837297311,93.6909530677945099,25.6600874124784752]},"#5511aa":{"lch":[27.3926712394503795,85.2829889480110097,274.948569823839534],"luv":[27.3926712394503795,7.3566383451248436,-84.9650991652784882],"rgb":[0.333333333333333315,0.0666666666666666657,0.66666666666666663],"xyz":[0.112015952766672422,0.0523449983292166923,0.38451698229144704],"hpluv":[274.948569823839534,395.063906765864772,27.3926712394503795],"hsluv":[274.948569823839534,94.7471527755802185,27.3926712394503795]},"#5511bb":{"lch":[29.2097366740877575,95.1102004757886732,273.151254165932869],"luv":[29.2097366740877575,5.22840137893499524,-94.9663838079847125],"rgb":[0.333333333333333315,0.0666666666666666657,0.733333333333333282],"xyz":[0.129153544874009069,0.0592000351721514509,0.474774967390088787],"hpluv":[273.151254165932869,413.179515249173164,29.2097366740877575],"hsluv":[273.151254165932869,95.5878244802283,29.2097366740877575]},"#5511cc":{"lch":[31.0944914716528729,104.870266468627406,271.822015936655589],"luv":[31.0944914716528729,3.33433100744475697,-104.81724584215],"rgb":[0.333333333333333315,0.0666666666666666657,0.8],"xyz":[0.148445920317730795,0.0669169853496402456,0.576381478060359],"hpluv":[271.822015936655589,427.964986778194486,31.0944914716528729],"hsluv":[271.822015936655589,96.2613872132177733,31.0944914716528729]},"#5511dd":{"lch":[33.0328257175950526,114.557035031638449,270.814150293263936],"luv":[33.0328257175950526,1.62775523553093748,-114.545469959022128],"rgb":[0.333333333333333315,0.0666666666666666657,0.866666666666666696],"xyz":[0.169964245868364339,0.0755243155698937796,0.689711325960365],"hpluv":[270.814150293263936,440.063516862193467,33.0328257175950526],"hsluv":[270.814150293263936,96.8053522828386832,33.0328257175950526]},"#5511ee":{"lch":[35.0130604571318926,124.169729525043778,270.033521846843314],"luv":[35.0130604571318926,0.0726475571782520396,-124.169708273213573],"rgb":[0.333333333333333315,0.0666666666666666657,0.933333333333333348],"xyz":[0.193776426134539104,0.0850491876763638244,0.815122142028888219],"hpluv":[270.033521846843314,450.012925469310176,35.0130604571318926],"hsluv":[270.033521846843314,97.2483877085506663,35.0130604571318926]},"#5511ff":{"lch":[37.0256255288684244,133.709282746677673,269.417732433602225],"luv":[37.0256255288684244,-1.35879534673770408,-133.702378317802101],"rgb":[0.333333333333333315,0.0666666666666666657,1],"xyz":[0.219947474544370469,0.0955176070402965205,0.952956330320670064],"hpluv":[269.417732433602225,458.245787382607887,37.0256255288684244],"hsluv":[269.417732433602225,99.999999999999531,37.0256255288684244]},"#552200":{"lch":[20.34436993371488,40.5799496107340403,26.5709502396200712],"luv":[20.34436993371488,36.2939416756913289,18.1516420207988389],"rgb":[0.333333333333333315,0.133333333333333331,0],"xyz":[0.0431823098773084293,0.0307565391490994891,0.0036627193159325909],"hpluv":[26.5709502396200712,253.10841584108,20.34436993371488],"hsluv":[26.5709502396200712,100.000000000002359,20.34436993371488]},"#552211":{"lch":[20.5030711832139332,37.4561676233306144,21.8926823519782197],"luv":[20.5030711832139332,34.7549742653004543,13.9662542166947503],"rgb":[0.333333333333333315,0.133333333333333331,0.0666666666666666657],"xyz":[0.0441939753769455546,0.031161205348954342,0.00899082428068822236],"hpluv":[21.8926823519782197,231.816181029165051,20.5030711832139332],"hsluv":[21.8926823519782197,79.998991439989,20.5030711832139332]},"#552222":{"lch":[20.7936643332181177,32.9512801850020054,12.1770506300619488],"luv":[20.7936643332181177,32.2098915499349658,6.95052171940595098],"rgb":[0.333333333333333315,0.133333333333333331,0.133333333333333331],"xyz":[0.0460693335154225697,0.0319113486043451633,0.0188677104766674167],"hpluv":[12.1770506300619488,201.08542320769223,20.7936643332181177],"hsluv":[12.1770506300619488,47.1205474310924046,20.7936643332181177]},"#552233":{"lch":[21.2623572347893699,28.8586800011052311,354.1745907436],"luv":[21.2623572347893699,28.7096478626609084,-2.92908364650122532],"rgb":[0.333333333333333315,0.133333333333333331,0.2],"xyz":[0.0491570842478803102,0.0331464488973282762,0.0351298643342785599],"hpluv":[354.1745907436,172.228245917758017,21.2623572347893699],"hsluv":[354.1745907436,52.8325366869496236,21.2623572347893699]},"#552244":{"lch":[21.9189283311679688,28.7014290952845421,329.54904741067952],"luv":[21.9189283311679688,24.7424491748557642,-14.5459011732283336],"rgb":[0.333333333333333315,0.133333333333333331,0.266666666666666663],"xyz":[0.0536150794920991908,0.0349296469950158492,0.0586086392871652],"hpluv":[329.54904741067952,166.158870546468904,21.9189283311679688],"hsluv":[329.54904741067952,59.1960886419386,21.9189283311679688]},"#552255":{"lch":[22.7630226511172538,33.9275210993755394,307.715012949244226],"luv":[22.7630226511172538,20.7546297224435,-26.8388157904337739],"rgb":[0.333333333333333315,0.133333333333333331,0.333333333333333315],"xyz":[0.0595774935314611828,0.0373146126107606821,0.0900106865611391138],"hpluv":[307.715012949244226,189.13048019699076,22.7630226511172538],"hsluv":[307.715012949244226,65.4333859354686211,22.7630226511172538]},"#552266":{"lch":[23.7863579144178132,42.6539605518829816,293.531429927677038],"luv":[23.7863579144178132,17.0296819355444384,-39.1069083914310625],"rgb":[0.333333333333333315,0.133333333333333331,0.4],"xyz":[0.0671624893049693611,0.0403486109201639936,0.129958330968283076],"hpluv":[293.531429927677038,227.546804006344104,23.7863579144178132],"hsluv":[293.531429927677038,71.0608597854246,23.7863579144178132]},"#552277":{"lch":[24.975052770659552,52.81712200152176,285.022920758889427],"luv":[24.975052770659552,13.6904851349353347,-51.0119495147337858],"rgb":[0.333333333333333315,0.133333333333333331,0.466666666666666674],"xyz":[0.0764765023251712805,0.04407421612824481,0.179012132874680985],"hpluv":[285.022920758889427,268.353735360872861,24.975052770659552],"hsluv":[285.022920758889427,75.8822745115455604,24.975052770659552]},"#552288":{"lch":[26.3119033569515395,63.3751525334233818,279.769698022236867],"luv":[26.3119033569515395,10.754023379801918,-62.4560720809542573],"rgb":[0.333333333333333315,0.133333333333333331,0.533333333333333326],"xyz":[0.0876169194271151086,0.0485303829690224,0.237684996278253152],"hpluv":[279.769698022236867,305.637106002952862,26.3119033569515395],"hsluv":[279.769698022236867,79.8897505498065357,26.3119033569515395]},"#552299":{"lch":[27.7783456471686065,73.9162973481211,276.357347681517297],"luv":[27.7783456471686065,8.18468635974612368,-73.4617582341209783],"rgb":[0.333333333333333315,0.133333333333333331,0.6],"xyz":[0.100673883536187808,0.0537531686126515654,0.306451673919371059],"hpluv":[276.357347681517297,337.654974874305083,27.7783456471686065],"hsluv":[276.357347681517297,83.1678045973750102,27.7783456471686065]},"#5522aa":{"lch":[29.3559430420228864,84.3037876124251824,274.032676149589577],"luv":[29.3559430420228864,5.92869585954675404,-84.0950603258353482],"rgb":[0.333333333333333315,0.133333333333333331,0.66666666666666663],"xyz":[0.115731576501440364,0.0597762457987526669,0.38575552353636966],"hpluv":[274.032676149589577,364.410076381253305,29.3559430420228864],"hsluv":[274.032676149589577,85.8312635149374898,29.3559430420228864]},"#5522bb":{"lch":[31.0273723986379082,94.5090555446981568,272.384235640696716],"luv":[31.0273723986379082,3.93164792491766635,-94.4272403734501324],"rgb":[0.333333333333333315,0.133333333333333331,0.733333333333333282],"xyz":[0.132869168608777,0.0666312826416874254,0.476013508635011406],"hpluv":[272.384235640696716,386.516244750379769,31.0273723986379082],"hsluv":[272.384235640696716,87.9935415010939437,31.0273723986379082]},"#5522cc":{"lch":[32.7769760620793207,104.54175742802569,271.176024316906762],"luv":[32.7769760620793207,2.1456208028374788,-104.519736688869415],"rgb":[0.333333333333333315,0.133333333333333331,0.8],"xyz":[0.152161544052498737,0.0743482328191762271,0.577620019305281507],"hpluv":[271.176024316906762,404.725193356887132,32.7769760620793207],"hsluv":[271.176024316906762,89.7538092894248507,32.7769760620793207]},"#5522dd":{"lch":[34.5909880118612847,114.421842397276407,270.265889656874094],"luv":[34.5909880118612847,0.530989812409553341,-114.420610326139567],"rgb":[0.333333333333333315,0.133333333333333331,0.866666666666666696],"xyz":[0.173679869603132281,0.0829555630394297611,0.690949867205287505],"hpluv":[270.265889656874094,419.744772471420788,34.5909880118612847],"hsluv":[270.265889656874094,91.1938440016712519,34.5909880118612847]},"#5522ee":{"lch":[36.4575428526747132,124.16924767107497,269.564389707514863],"luv":[36.4575428526747132,-0.94402906580191559,-124.165659005715739],"rgb":[0.333333333333333315,0.133333333333333331,0.933333333333333348],"xyz":[0.197492049869307018,0.092480435145899792,0.816360683273810728],"hpluv":[269.564389707514863,432.181309790662738,36.4575428526747132],"hsluv":[269.564389707514863,92.960018101107309,36.4575428526747132]},"#5522ff":{"lch":[38.3665568136218695,133.800754994484379,269.013084090219763],"luv":[38.3665568136218695,-2.30459494965050871,-133.780906258001124],"rgb":[0.333333333333333315,0.133333333333333331,1],"xyz":[0.223663098279138411,0.102948854509832488,0.954194871565592573],"hpluv":[269.013084090219763,442.532391911887146,38.3665568136218695],"hsluv":[269.013084090219763,99.9999999999994458,38.3665568136218695]},"#ccaa00":{"lch":[70.5858735612972623,80.4904122142546186,67.9906634155396],"luv":[70.5858735612972623,30.1643998932495876,74.6244962294604335],"rgb":[0.8,0.66666666666666663,0],"xyz":[0.392753797737474875,0.415879162748823417,0.059586129772359088],"hpluv":[67.9906634155396,144.699051457387782,70.5858735612972623],"hsluv":[67.9906634155396,100.000000000002373,70.5858735612972623]},"#ccaa11":{"lch":[70.6139482370970342,79.3332745728624786,67.7767588069511078],"luv":[70.6139482370970342,30.0051392857341135,73.4401802210267078],"rgb":[0.8,0.66666666666666663,0.0666666666666666657],"xyz":[0.393765463237112,0.416283828948678269,0.0649142347371147177],"hpluv":[67.7767588069511078,142.56214209062793,70.6139482370970342],"hsluv":[67.7767588069511078,98.4234445622979308,70.6139482370970342]},"#ccaa22":{"lch":[70.6659431154106,77.2098224605726529,67.3668792611096166],"luv":[70.6659431154106,29.7125737342128318,71.263733037795],"rgb":[0.8,0.66666666666666663,0.133333333333333331],"xyz":[0.395640821375589036,0.41703397220406907,0.0747911209330939103],"hpluv":[67.3668792611096166,138.644204697820271,70.6659431154106],"hsluv":[67.3668792611096166,95.5289103121581746,70.6659431154106]},"#ccaa33":{"lch":[70.7514162745237911,73.7740913884545,66.6515854645136159],"luv":[70.7514162745237911,29.2382542862800783,67.7328653349528622],"rgb":[0.8,0.66666666666666663,0.2],"xyz":[0.398728572108046742,0.418269072497052197,0.0910532747907050605],"hpluv":[66.6515854645136159,132.314688307412609,70.7514162745237911],"hsluv":[66.6515854645136159,90.8407422295077822,70.7514162745237911]},"#ccaa44":{"lch":[70.8745233475107597,68.9449101039795096,65.5199261400916271],"luv":[70.8745233475107597,28.5691680681362534,62.74713750555],"rgb":[0.8,0.66666666666666663,0.266666666666666663],"xyz":[0.403186567352265657,0.420052270594739763,0.114532049743591699],"hpluv":[65.5199261400916271,123.438713002021714,70.8745233475107597],"hsluv":[65.5199261400916271,84.237349466135143,70.8745233475107597]},"#ccaa55":{"lch":[71.0386313772099,62.7256766939065713,63.7915144306433959],"luv":[71.0386313772099,27.7020883768036121,56.2770363138665672],"rgb":[0.8,0.66666666666666663,0.333333333333333315],"xyz":[0.409148981391627642,0.422437236210484623,0.1459340970175656],"hpluv":[63.7915144306433959,112.044384698186093,71.0386313772099],"hsluv":[63.7915144306433959,75.6976413431368229,71.0386313772099]},"#ccaa66":{"lch":[71.2465086991263661,55.2096541299921952,61.1466680322388356],"luv":[71.2465086991263661,26.6424757380098143,48.3558103613508123],"rgb":[0.8,0.66666666666666663,0.4],"xyz":[0.416733977165135827,0.425471234519887942,0.185881741424709562],"hpluv":[61.1466680322388356,98.331070119416168,71.2465086991263661],"hsluv":[61.1466680322388356,65.2901205751262,71.2465086991263661]},"#ccaa77":{"lch":[71.5004247203994794,46.6032511345785068,56.9687004258729388],"luv":[71.5004247203994794,25.4032971934547263,39.0709035986321638],"rgb":[0.8,0.66666666666666663,0.466666666666666674],"xyz":[0.426047990185337733,0.429196839727968737,0.234935543331107471],"hpluv":[56.9687004258729388,82.707885898124573,71.5004247203994794],"hsluv":[56.9687004258729388,53.160756563752912,71.5004247203994794]},"#ccaa88":{"lch":[71.8022091544958556,37.3024926838847648,49.9478623796008847],"luv":[71.8022091544958556,24.003572993357885,28.5535364531929083],"rgb":[0.8,0.66666666666666663,0.533333333333333326],"xyz":[0.437188407287281533,0.433653006568746335,0.293608406734679639],"hpluv":[49.9478623796008847,65.9233659814751149,71.8022091544958556],"hsluv":[49.9478623796008847,39.5178130280575743,71.8022091544958556]},"#ccaa99":{"lch":[72.1532912119235874,28.1535194843350283,37.0598425499876214],"luv":[72.1532912119235874,22.4666918036374241,16.9666855559712388],"rgb":[0.8,0.66666666666666663,0.6],"xyz":[0.450245371396354233,0.438875792212375493,0.362375084375797574],"hpluv":[37.0598425499876214,49.5126161932360702,72.1532912119235874],"hsluv":[37.0598425499876214,26.6696495224772221,72.1532912119235874]},"#ccaaaa":{"lch":[72.5547286434336,21.297823518763618,12.177050630063027],"luv":[72.5547286434336,20.8186322940273918,4.49241984263274841],"rgb":[0.8,0.66666666666666663,0.66666666666666663],"xyz":[0.465303064361606789,0.444898869398476615,0.441678933992796174],"hpluv":[12.177050630063027,37.2485034287350203,72.5547286434336],"hsluv":[12.177050630063027,27.9047031904792959,72.5547286434336]},"#ccaabb":{"lch":[73.0072318845295,20.9674028584132515,335.544386587188285],"luv":[73.0072318845295,19.0862548050106788,-8.68025691700441193],"rgb":[0.8,0.66666666666666663,0.733333333333333282],"xyz":[0.482440656468943463,0.451753906241411374,0.531936919091437921],"hpluv":[335.544386587188285,36.4433325399841053,73.0072318845295],"hsluv":[335.544386587188285,29.1493731958161852,73.0072318845295]},"#ccaacc":{"lch":[73.5111862218870442,28.2733952257813925,307.715012949249683],"luv":[73.5111862218870442,17.2958067637387,-22.366044486780595],"rgb":[0.8,0.66666666666666663,0.8],"xyz":[0.501733031912665162,0.459470856418900175,0.633543429761708077],"hpluv":[307.715012949249683,48.8049486057506,73.5111862218870442],"hsluv":[307.715012949249683,30.3693282248248444,73.5111862218870442]},"#ccaadd":{"lch":[74.0666736076556,39.5441054640130645,293.032470315564865],"luv":[74.0666736076556,15.4717391639018693,-36.3917787995197202],"rgb":[0.8,0.66666666666666663,0.866666666666666696],"xyz":[0.523251357463298761,0.468078186639153682,0.746873277661714075],"hpluv":[293.032470315564865,67.7482749884916871,74.0666736076556],"hsluv":[293.032470315564865,52.1368854824616719,74.0666736076556]},"#ccaaee":{"lch":[74.6734949675833093,52.4074038625381462,285.081329657377239],"luv":[74.6734949675833093,13.6358764846886817,-50.6023601436286],"rgb":[0.8,0.66666666666666663,0.933333333333333348],"xyz":[0.54706353772947347,0.477603058745623699,0.872284093730237298],"hpluv":[285.081329657377239,89.0564736794959799,74.6734949675833093],"hsluv":[285.081329657377239,75.3315532053798194,74.6734949675833093]},"#ccaaff":{"lch":[75.3311933526529316,65.9300530396585458,280.316334998223624],"luv":[75.3311933526529316,11.8069327652914797,-64.8642292214135239],"rgb":[0.8,0.66666666666666663,1],"xyz":[0.573234586139304891,0.488071478109556423,1.01011828202201914],"hpluv":[280.316334998223624,111.057502918871393,75.3311933526529316],"hsluv":[280.316334998223624,99.9999999999973426,75.3311933526529316]},"#553300":{"lch":[24.6368918170402651,35.1311640480653367,43.6144672720514848],"luv":[24.6368918170402651,25.4348822629288698,24.2335604409056025],"rgb":[0.333333333333333315,0.2,0],"xyz":[0.049300031966319241,0.0429919833271212859,0.00570196001226947087],"hpluv":[43.6144672720514848,180.944734702515461,24.6368918170402651],"hsluv":[43.6144672720514848,100.000000000002245,24.6368918170402651]},"#553311":{"lch":[24.7639934196671305,31.9442274162558917,39.8156129865950632],"luv":[24.7639934196671305,24.536650698978292,20.4544967598277161],"rgb":[0.333333333333333315,0.2,0.0666666666666666657],"xyz":[0.0503116974659563593,0.0433966495269761388,0.0110300649770251023],"hpluv":[39.8156129865950632,163.685811409294416,24.7639934196671305],"hsluv":[39.8156129865950632,85.3309596574143256,24.7639934196671305]},"#553322":{"lch":[24.9975315322943885,26.9096454002331456,31.2519949010175395],"luv":[24.9975315322943885,23.0048892205904032,13.9608054035092266],"rgb":[0.333333333333333315,0.2,0.133333333333333331],"xyz":[0.0521870556044333814,0.0441467927823669601,0.0209069511730043],"hpluv":[31.2519949010175395,136.59983556614165,24.9975315322943885],"hsluv":[31.2519949010175395,60.4417762068684823,24.9975315322943885]},"#553333":{"lch":[25.3763514371309924,21.2787516643900716,12.1770506300621495],"luv":[25.3763514371309924,20.7999895475976082,4.48839695377019332],"rgb":[0.333333333333333315,0.2,0.2],"xyz":[0.0552748063368911219,0.0453818930753500729,0.0371691050306154416],"hpluv":[12.1770506300621495,106.403592780468983,25.3763514371309924],"hsluv":[12.1770506300621495,24.9336598370546909,25.3763514371309924]},"#553344":{"lch":[25.9113402150992655,19.4972565515274532,338.627269772390264],"luv":[25.9113402150992655,18.1564179844864455,-7.10545558065754257],"rgb":[0.333333333333333315,0.2,0.266666666666666663],"xyz":[0.05973280158111,0.047165091173037646,0.0606478799835020801],"hpluv":[338.627269772390264,95.4823185470749536,25.9113402150992655],"hsluv":[338.627269772390264,32.9723178491547841,25.9113402150992655]},"#553355":{"lch":[26.6061908173450519,25.0719265662328183,307.715012949245363],"luv":[26.6061908173450519,15.3373584467403763,-19.8334802195371829],"rgb":[0.333333333333333315,0.2,0.333333333333333315],"xyz":[0.065695215620472,0.0495500567887824789,0.0920499272574759886],"hpluv":[307.715012949245363,119.576085528419512,26.6061908173450519],"hsluv":[307.715012949245363,41.369683748934996,26.6061908173450519]},"#553366":{"lch":[27.4586282592714284,35.2024776289392847,290.893042573756475],"luv":[27.4586282592714284,12.5540679631371699,-32.8878367910220533],"rgb":[0.333333333333333315,0.2,0.4],"xyz":[0.0732802113939801658,0.0525840550981857904,0.13199757166461995],"hpluv":[290.893042573756475,162.679833835368925,27.4586282592714284],"hsluv":[290.893042573756475,49.429407074258,27.4586282592714284]},"#553377":{"lch":[28.461655060413058,46.8206771520520633,282.253113271302652],"luv":[28.461655060413058,9.93678843358592445,-45.7540822725452898],"rgb":[0.333333333333333315,0.2,0.466666666666666674],"xyz":[0.0825942244141820853,0.0563096603062666068,0.18105137357101786],"hpluv":[282.253113271302652,208.74537696470955,28.461655060413058],"hsluv":[282.253113271302652,56.732994513665389,28.461655060413058]},"#553388":{"lch":[29.6048600369324433,58.6666973974172876,277.388246485053742],"luv":[29.6048600369324433,7.54407762538358551,-58.1796207988872567],"rgb":[0.333333333333333315,0.2,0.533333333333333326],"xyz":[0.0937346415161259133,0.0607658271470442046,0.239724236974590027],"hpluv":[277.388246485053742,251.459446283522851,29.6048600369324433],"hsluv":[277.388246485053742,63.1061783000114715,29.6048600369324433]},"#553399":{"lch":[30.8756880539778678,70.2946203588512759,274.394660626066695],"luv":[30.8756880539778678,5.38640350826703,-70.0879469569565714],"rgb":[0.333333333333333315,0.2,0.6],"xyz":[0.106791605625198627,0.0659886127906733622,0.308490914615707934],"hpluv":[274.394660626066695,288.898157334443908,30.8756880539778678],"hsluv":[274.394660626066695,68.537799314251,30.8756880539778678]},"#5533aa":{"lch":[32.2605562861205,81.571224268378316,272.422737250332261],"luv":[32.2605562861205,3.44819039224039026,-81.498310483475251],"rgb":[0.333333333333333315,0.2,0.66666666666666663],"xyz":[0.121849298590451169,0.0720116899767744567,0.387794764232706535],"hpluv":[272.422737250332261,320.851781583216223,32.2605562861205],"hsluv":[272.422737250332261,73.1042224024611897,32.2605562861205]},"#5533bb":{"lch":[33.7457437232739395,92.4864953275551755,271.055064965734516],"luv":[33.7457437232739395,1.70298313903478205,-92.4708152143261231],"rgb":[0.333333333333333315,0.2,0.733333333333333282],"xyz":[0.138986890697787802,0.0788667268197092153,0.478052749331348281],"hpluv":[271.055064965734516,347.775228922495899,33.7457437232739395],"hsluv":[271.055064965734516,76.9172199670655772,33.7457437232739395]},"#5533cc":{"lch":[35.3180325241442,103.075547069605378,270.067872161558512],"luv":[35.3180325241442,0.12210251098248695,-103.075474748725966],"rgb":[0.333333333333333315,0.2,0.8],"xyz":[0.158279266141509556,0.0865836769971980169,0.579659260001618493],"hpluv":[270.067872161558512,370.338167129355497,35.3180325241442],"hsluv":[270.067872161558512,80.0940957669769205,35.3180325241442]},"#5533dd":{"lch":[36.9651203282397915,113.385246995104879,269.332372034398134],"luv":[36.9651203282397915,-1.32116971635525937,-113.377549570986602],"rgb":[0.333333333333333315,0.2,0.866666666666666696],"xyz":[0.179797591692143099,0.0951910072174515509,0.69298910790162449],"hpluv":[269.332372034398134,389.227711455139399,36.9651203282397915],"hsluv":[269.332372034398134,84.8119298710034855,36.9651203282397915]},"#5533ee":{"lch":[38.6758450270606247,123.460606758128,268.77009087446072],"luv":[38.6758450270606247,-2.64999738284680575,-123.432163292052948],"rgb":[0.333333333333333315,0.2,0.933333333333333348],"xyz":[0.203609771958317837,0.104715879323921596,0.818399923970147714],"hpluv":[268.77009087446072,405.067987408818738,38.6758450270606247],"hsluv":[268.77009087446072,92.2936685874649356,38.6758450270606247]},"#5533ff":{"lch":[40.4402700894382363,133.340096114557781,268.33094335317071],"luv":[40.4402700894382363,-3.88371885476632706,-133.283524712158766],"rgb":[0.333333333333333315,0.2,1],"xyz":[0.22978082036814923,0.115184298687854292,0.956234112261929559],"hpluv":[268.33094335317071,418.394573227645935,40.4402700894382363],"hsluv":[268.33094335317071,99.99999999999946,40.4402700894382363]},"#ccbb00":{"lch":[75.0632334950121418,83.0331806403360275,77.5616137481136292],"luv":[75.0632334950121418,17.8844849446013434,81.0842419062853423],"rgb":[0.8,0.733333333333333282,0],"xyz":[0.426708295646073654,0.483788158566022,0.0709042957418917],"hpluv":[77.5616137481136292,140.366584388758554,75.0632334950121418],"hsluv":[77.5616137481136292,100.000000000002373,75.0632334950121418]},"#ccbb11":{"lch":[75.0886164663743898,81.9438461169387438,77.472162284636525],"luv":[75.0886164663743898,17.7747618107910519,79.9928231718707394],"rgb":[0.8,0.733333333333333282,0.0666666666666666657],"xyz":[0.427719961145710759,0.484192824765876828,0.0762324007066473436],"hpluv":[77.472162284636525,138.478250548668058,75.0886164663743898],"hsluv":[77.472162284636525,98.6397508878022222,75.0886164663743898]},"#ccbb22":{"lch":[75.1356323460541802,79.9401497843360289,77.301186242421764],"luv":[75.1356323460541802,17.5729239259544805,77.9847414064744839],"rgb":[0.8,0.733333333333333282,0.133333333333333331],"xyz":[0.429595319284187815,0.484942968021267629,0.0861092869026265362],"hpluv":[77.301186242421764,135.007637737713509,75.1356323460541802],"hsluv":[77.301186242421764,96.1390577710114087,75.1356323460541802]},"#ccbb33":{"lch":[75.2129378077961235,76.6847204783522471,77.0041162235267223],"luv":[75.2129378077961235,17.2449407213965777,74.720535158405653],"rgb":[0.8,0.733333333333333282,0.2],"xyz":[0.432683070016645521,0.486178068314250755,0.102371440760237686],"hpluv":[77.0041162235267223,129.376563997369885,75.2129378077961235],"hsluv":[77.0041162235267223,92.0797058264172392,75.2129378077961235]},"#ccbb44":{"lch":[75.3243183189310628,72.0782997366288,76.5373230188340585],"luv":[75.3243183189310628,16.7806861485978907,70.0977165484408431],"rgb":[0.8,0.733333333333333282,0.266666666666666663],"xyz":[0.437141065260864436,0.487961266411938321,0.125850215713124325],"hpluv":[76.5373230188340585,121.425150369898518,75.3243183189310628],"hsluv":[76.5373230188340585,86.34290383100182,75.3243183189310628]},"#ccbb55":{"lch":[75.4728625341146397,66.0852327898053,75.831238609121371],"luv":[75.4728625341146397,16.1762634357197506,64.0748507149330351],"rgb":[0.8,0.733333333333333282,0.333333333333333315],"xyz":[0.443103479300226422,0.490346232027683182,0.157252262987098212],"hpluv":[75.831238609121371,111.10994393806304,75.4728625341146397],"hsluv":[75.831238609121371,78.8905565478608395,75.4728625341146397]},"#ccbb66":{"lch":[75.6611363515091284,58.7289677793131,74.7643785098968863],"luv":[75.6611363515091284,15.4333320312120961,56.6648384700597134],"rgb":[0.8,0.733333333333333282,0.4],"xyz":[0.450688475073734607,0.493380230337086501,0.197199907394242202],"hpluv":[74.7643785098968863,98.4960546107130739,75.6611363515091284],"hsluv":[74.7643785098968863,69.7569980114599701,75.6611363515091284]},"#ccbb77":{"lch":[75.8912747684230737,50.090867045562554,73.1036630558194389],"luv":[75.8912747684230737,14.5584607724557671,47.9285528814827799],"rgb":[0.8,0.733333333333333282,0.466666666666666674],"xyz":[0.460002488093936512,0.497105835545167296,0.246253709300640111],"hpluv":[73.1036630558194389,83.7540906733876795,75.8912747684230737],"hsluv":[73.1036630558194389,59.0406908273499624,75.8912747684230737]},"#ccbb88":{"lch":[76.1650362860674335,40.3168412407358332,70.3426656865815119],"luv":[76.1650362860674335,13.5623472284534756,37.9672283066009157],"rgb":[0.8,0.733333333333333282,0.533333333333333326],"xyz":[0.471142905195880313,0.501562002385944838,0.304926572704212251],"hpluv":[70.3426656865815119,67.6831847004182379,76.1650362860674335],"hsluv":[70.3426656865815119,46.8939441374685586,76.1650362860674335]},"#ccbb99":{"lch":[76.4838383644648871,29.6573629081618826,65.1594516064859732],"luv":[76.4838383644648871,12.4588924968264081,26.9134756658990248],"rgb":[0.8,0.733333333333333282,0.6],"xyz":[0.484199869304953068,0.506784788029574,0.373693250345330186],"hpluv":[65.1594516064859732,50.6096239917615662,76.4838383644648871],"hsluv":[65.1594516064859732,33.5105935092195324,76.4838383644648871]},"#ccbbaa":{"lch":[76.8487828748923,18.695758935396551,52.9508743401004551],"luv":[76.8487828748923,11.26418644921627,14.9214444946778713],"rgb":[0.8,0.733333333333333282,0.66666666666666663],"xyz":[0.499257562270205568,0.512807865215675118,0.452997099962328786],"hpluv":[52.9508743401004551,32.5142912020767696,76.8487828748923],"hsluv":[52.9508743401004551,19.1124274046376854,76.8487828748923]},"#ccbbbb":{"lch":[77.2606763328388126,10.2255548171674207,12.1770506300639045],"luv":[77.2606763328388126,9.99548454110707,2.15690985147396086],"rgb":[0.8,0.733333333333333282,0.733333333333333282],"xyz":[0.516395154377542243,0.519662902058609877,0.543255085060970533],"hpluv":[12.1770506300639045,18.1733155366010308,77.2606763328388126],"hsluv":[12.1770506300639045,17.1437484893634,77.2606763328388126]},"#ccbbcc":{"lch":[77.7200476270310361,14.1732404034447406,307.715012949257925],"luv":[77.7200476270310361,8.67025786172679247,-11.2119299027867267],"rgb":[0.8,0.733333333333333282,0.8],"xyz":[0.535687529821264,0.527379852236098734,0.644861595731240689],"hpluv":[307.715012949257925,25.815587331502627,77.7200476270310361],"hsluv":[307.715012949257925,18.1614974693692588,77.7200476270310361]},"#ccbbdd":{"lch":[78.2271648233418375,26.0669286991650679,286.275412631614586],"luv":[78.2271648233418375,7.3053819239814537,-25.022313377306272],"rgb":[0.8,0.733333333333333282,0.866666666666666696],"xyz":[0.557205855371897485,0.53598718245635224,0.758191443631246687],"hpluv":[286.275412631614586,48.8074477639820898,78.2271648233418375],"hsluv":[286.275412631614586,43.4510455050629929,78.2271648233418375]},"#ccbbee":{"lch":[78.7820519440635,39.5678846485468299,278.599571826643512],"luv":[78.7820519440635,5.9165048525659989,-39.1230426461218741],"rgb":[0.8,0.733333333333333282,0.933333333333333348],"xyz":[0.581018035638072305,0.545512054562822257,0.88360225969976991],"hpluv":[278.599571826643512,76.4037468789834,78.7820519440635],"hsluv":[278.599571826643512,70.6968150087455314,78.7820519440635]},"#ccbbff":{"lch":[79.3845061922316546,53.5695670840829834,274.837592460092935],"luv":[79.3845061922316546,4.51760925339512553,-53.3787385033564235],"rgb":[0.8,0.733333333333333282,1],"xyz":[0.607189084047903616,0.555980473926755,1.02143644799155164],"hpluv":[274.837592460092935,107.038572744282547,79.3845061922316546],"hsluv":[274.837592460092935,99.9999999999963762,79.3845061922316546]},"#554400":{"lch":[29.5776499109456879,34.0768703371065413,65.9474553070004674],"luv":[29.5776499109456879,13.8888553561515469,31.1180460322924546],"rgb":[0.333333333333333315,0.266666666666666663,0],"xyz":[0.0581326024492852811,0.0606571242930536,0.0086461501732580659],"hpluv":[65.9474553070004674,146.195957524823825,29.5776499109456879],"hsluv":[65.9474553070004674,100.000000000002217,29.5776499109456879]},"#554411":{"lch":[29.6787804923011507,30.8713815411758574,64.2244588846852906],"luv":[29.6787804923011507,13.4243191404277429,27.7998175151708296],"rgb":[0.333333333333333315,0.266666666666666663,0.0666666666666666657],"xyz":[0.0591442679489224,0.0610617904929084548,0.0139742551380136974],"hpluv":[64.2244588846852906,131.992525946838612,29.6787804923011507],"hsluv":[64.2244588846852906,89.4077694450363509,29.6787804923011507]},"#554422":{"lch":[29.8650740872788916,25.3442505658492152,60.1547603291711539],"luv":[29.8650740872788916,12.6127938179319639,21.9829131111162219],"rgb":[0.333333333333333315,0.266666666666666663,0.133333333333333331],"xyz":[0.0610196260873994215,0.0618119337482992762,0.0238511413339928952],"hpluv":[60.1547603291711539,107.684992873038837,29.8650740872788916],"hsluv":[60.1547603291711539,70.9921927199271892,29.8650740872788916]},"#554433":{"lch":[30.1685472793317686,17.4710669916127905,49.2680266756281497],"luv":[30.1685472793317686,11.400244593092479,13.2390560480378525],"rgb":[0.333333333333333315,0.266666666666666663,0.2],"xyz":[0.064107376819857162,0.0630470340412823821,0.0401132951916040384],"hpluv":[49.2680266756281497,73.4859575586117302,30.1685472793317686],"hsluv":[49.2680266756281497,43.7071568358896,30.1685472793317686]},"#554444":{"lch":[30.5997780424982437,10.1013456632853149,12.1770506300629258],"luv":[30.5997780424982437,9.87407003600776356,2.13071000682558],"rgb":[0.333333333333333315,0.266666666666666663,0.266666666666666663],"xyz":[0.0685653720640760356,0.0648302321389699621,0.06359207014449067],"hpluv":[12.1770506300629258,41.8890279889816597,30.5997780424982437],"hsluv":[12.1770506300629258,9.81589763549682282,30.5997780424982437]},"#554455":{"lch":[31.1643459369041338,13.3310860490153988,307.715012949249],"luv":[31.1643459369041338,8.15508312366709198,-10.5457325251654854],"rgb":[0.333333333333333315,0.266666666666666663,0.333333333333333315],"xyz":[0.0745277861034380346,0.0672151977547148,0.0949941174184645853],"hpluv":[307.715012949249,54.2808752323906702,31.1643459369041338],"hsluv":[307.715012949249,18.7795296363480162,31.1643459369041338]},"#554466":{"lch":[31.8635722620044533,24.8340912161126894,284.841165372516684],"luv":[31.8635722620044533,6.36101223964894835,-24.005616214070443],"rgb":[0.333333333333333315,0.266666666666666663,0.4],"xyz":[0.0821127818769462,0.0702491960641181135,0.134941761825608547],"hpluv":[284.841165372516684,98.8992811700442331,31.8635722620044533],"hsluv":[284.841165372516684,27.8963704264996828,31.8635722620044533]},"#554477":{"lch":[32.6951743277909443,37.9095930577936784,276.944338121378166],"luv":[32.6951743277909443,4.58346102749711282,-37.6314912117090259],"rgb":[0.333333333333333315,0.266666666666666663,0.466666666666666674],"xyz":[0.0914267948971481254,0.0739748012721989229,0.183995563732006456],"hpluv":[276.944338121378166,147.131204947893167,32.6951743277909443],"hsluv":[276.944338121378166,36.6308714978363952,32.6951743277909443]},"#554488":{"lch":[33.6539551717380903,51.1018638808679526,273.231940865766],"luv":[33.6539551717380903,2.88102600900669881,-51.0205858574182116],"rgb":[0.333333333333333315,0.266666666666666663,0.533333333333333326],"xyz":[0.102567211999091953,0.0784309681129765207,0.242668427135578624],"hpluv":[273.231940865766,192.681471981123309,33.6539551717380903],"hsluv":[273.231940865766,44.6505812495932801,33.6539551717380903]},"#554499":{"lch":[34.7325237210335871,63.9719124096453271,271.149517924849135],"luv":[34.7325237210335871,1.28337422751110575,-63.9590378909774913],"rgb":[0.333333333333333315,0.266666666666666663,0.6],"xyz":[0.115624176108164667,0.0836537537566056782,0.311435104776696559],"hpluv":[271.149517924849135,233.718085138698228,34.7325237210335871],"hsluv":[271.149517924849135,51.7999710200133876,34.7325237210335871]},"#5544aa":{"lch":[35.9219992682327671,76.3678985235758461,269.849629436139082],"luv":[35.9219992682327671,-0.200424374653859844,-76.367635520403681],"rgb":[0.333333333333333315,0.266666666666666663,0.66666666666666663],"xyz":[0.130681869073417223,0.0896768309427067867,0.390738954393695104],"hpluv":[269.849629436139082,269.767524553786757,35.9219992682327671],"hsluv":[269.849629436139082,58.0490239963672465,35.9219992682327671]},"#5544bb":{"lch":[37.2126506061998725,88.2627815084196925,268.978337620063314],"luv":[37.2126506061998725,-1.57376312233016602,-88.2487499584998574],"rgb":[0.333333333333333315,0.266666666666666663,0.733333333333333282],"xyz":[0.147819461180753842,0.0965318677856415452,0.480996939492336906],"hpluv":[268.978337620063314,300.972163983169935,37.2126506061998725],"hsluv":[268.978337620063314,66.0075029321504729,37.2126506061998725]},"#5544cc":{"lch":[38.5944341452357733,99.6871153018899605,268.363808876145868],"luv":[38.5944341452357733,-2.84637030136680202,-99.6464707519528758],"rgb":[0.333333333333333315,0.266666666666666663,0.8],"xyz":[0.167111836624475596,0.104248817963130347,0.582603450162607062],"hpluv":[268.363808876145868,327.758284181939189,38.5944341452357733],"hsluv":[268.363808876145868,74.5283681063652352,38.5944341452357733]},"#5544dd":{"lch":[40.0574145710935738,110.694467066426,267.913412719582],"luv":[40.0574145710935738,-4.03035995406870118,-110.621070496360275],"rgb":[0.333333333333333315,0.266666666666666663,0.866666666666666696],"xyz":[0.18863016217510914,0.112856148183383881,0.695933298062613059],"hpluv":[267.913412719582,350.65684831918054,40.0574145710935738],"hsluv":[267.913412719582,82.9425769408534,40.0574145710935738]},"#5544ee":{"lch":[41.5920687629554777,121.343449115737442,267.573227144435918],"luv":[41.5920687629554777,-5.13798666158471651,-121.23462268002875],"rgb":[0.333333333333333315,0.266666666666666663,0.933333333333333348],"xyz":[0.212442342441283877,0.122381020289853898,0.821344114131136283],"hpluv":[267.573227144435918,370.207437425804358,41.5920687629554777],"hsluv":[267.573227144435918,91.3878688389195872,41.5920687629554777]},"#5544ff":{"lch":[43.1894854939413833,131.689092168021887,267.309962581974105],"luv":[43.1894854939413833,-6.18053297470727,-131.543977468321657],"rgb":[0.333333333333333315,0.266666666666666663,1],"xyz":[0.23861339085111527,0.132849439653786594,0.959178302422918128],"hpluv":[267.309962581974105,386.911020330846497,43.1894854939413833],"hsluv":[267.309962581974105,99.9999999999994174,43.1894854939413833]},"#cccc00":{"lch":[79.627228346343,87.7811065558180132,85.8743202181747449],"luv":[79.627228346343,6.31536666608958797,87.5536339167982192],"rgb":[0.8,0.8,0],"xyz":[0.464932038955690574,0.560235645185256814,0.0836455435117636481],"hpluv":[85.8743202181747449,177.871840357077815,79.627228346343],"hsluv":[85.8743202181747449,100.000000000002245,79.627228346343]},"#cccc11":{"lch":[79.6502471087807891,86.7718911178833707,85.8743202181747],"luv":[79.6502471087807891,6.24275917928854351,86.5470337215737],"rgb":[0.8,0.8,0.0666666666666666657],"xyz":[0.465943704455327679,0.560640311385111723,0.0889736484765192848],"hpluv":[85.8743202181747,176.061859354342118,79.6502471087807891],"hsluv":[85.8743202181747,98.8217369524532927,79.6502471087807891]},"#cccc22":{"lch":[79.6928884771461838,84.9132131482774497,85.8743202181746597],"luv":[79.6928884771461838,6.10903754655005482,84.6931722597497298],"rgb":[0.8,0.8,0.133333333333333331],"xyz":[0.467819062593804735,0.561390454640502523,0.0988505346724984774],"hpluv":[85.8743202181746597,172.717957044242922,79.6928884771461838],"hsluv":[85.8743202181746597,96.653203912443459,79.6928884771461838]},"#cccc33":{"lch":[79.7630142061039891,81.8867831673476445,85.8743202181745602],"luv":[79.7630142061039891,5.89130259459140682,81.6745848549912665],"rgb":[0.8,0.8,0.2],"xyz":[0.470906813326262441,0.56262555493348565,0.115112688530109614],"hpluv":[85.8743202181745602,167.243641009868185,79.7630142061039891],"hsluv":[85.8743202181745602,93.1263971058523623,79.7630142061039891]},"#cccc44":{"lch":[79.8640786601047523,77.5899505798540901,85.8743202181744],"luv":[79.8640786601047523,5.58216917901353593,77.3888869169280156],"rgb":[0.8,0.8,0.266666666666666663],"xyz":[0.475364808570481356,0.564408753031173216,0.138591463482996252],"hpluv":[85.8743202181744,159.406599578518,79.8640786601047523],"hsluv":[85.8743202181744,88.1281264379617113,79.8640786601047523]},"#cccc55":{"lch":[79.9989166638852396,71.9729259129294832,85.8743202181741481],"luv":[79.9989166638852396,5.17805522174052,71.7864179952492236],"rgb":[0.8,0.8,0.333333333333333315],"xyz":[0.481327222609843342,0.566793718646918,0.169993510756970168],"hpluv":[85.8743202181741481,149.042041148428552,79.9989166638852396],"hsluv":[85.8743202181741481,81.6104176612222147,79.9989166638852396]},"#cccc66":{"lch":[80.1699032642976448,65.0330295388014,85.8743202181738],"luv":[80.1699032642976448,4.67876793832737103,64.8645054060685453],"rgb":[0.8,0.8,0.4],"xyz":[0.488912218383351527,0.569827716956321284,0.209941155164114129],"hpluv":[85.8743202181738,136.038559250079544,80.1699032642976448],"hsluv":[85.8743202181738,73.5839630734023,80.1699032642976448]},"#cccc77":{"lch":[80.3790384438565724,56.8098315426934803,85.8743202181733096],"luv":[80.3790384438565724,4.0871541782499472,56.6626166941875837],"rgb":[0.8,0.8,0.466666666666666674],"xyz":[0.498226231403553432,0.573553322164402135,0.258994957070512],"hpluv":[85.8743202181733096,120.326663009793734,80.3790384438565724],"hsluv":[85.8743202181733096,64.1122831116318252,80.3790384438565724]},"#cccc88":{"lch":[80.6279973255091704,47.3795499902223085,85.8743202181724854],"luv":[80.6279973255091704,3.40869741112766222,47.2567724166107865],"rgb":[0.8,0.8,0.533333333333333326],"xyz":[0.509366648505497288,0.578009489005179677,0.317667820474084206],"hpluv":[85.8743202181724854,101.866799769447482,80.6279973255091704],"hsluv":[85.8743202181724854,53.3047126681541172,80.6279973255091704]},"#cccc99":{"lch":[80.9181626169042119,36.8483625211582861,85.8743202181711496],"luv":[80.9181626169042119,2.65103653276840934,36.7528750683892724],"rgb":[0.8,0.8,0.6],"xyz":[0.522423612614569932,0.58323227464880889,0.386434498115202141],"hpluv":[85.8743202181711496,80.635831276566,80.9181626169042119],"hsluv":[85.8743202181711496,41.30786304104587,80.9181626169042119]},"#ccccaa":{"lch":[81.2506473976222452,25.3448572993520607,85.8743202181683216],"luv":[81.2506473976222452,1.82342275263520492,25.27917959487],"rgb":[0.8,0.8,0.66666666666666663],"xyz":[0.537481305579822544,0.58925535183491,0.465738347732200686],"hpluv":[85.8743202181683216,56.6117825452175509,81.2506473976222452],"hsluv":[85.8743202181683216,28.2959036617823898,81.2506473976222452]},"#ccccbb":{"lch":[81.6263125989092657,13.0121158497344798,85.8743202181599],"luv":[81.6263125989092657,0.936149997616518514,12.9783967449324749],"rgb":[0.8,0.8,0.733333333333333282],"xyz":[0.554618897687159107,0.596110388677844716,0.555996332830842488],"hpluv":[85.8743202181599,29.7570160502500514,81.6263125989092657],"hsluv":[85.8743202181599,14.4603328966824272,81.6263125989092657]},"#cccccc":{"lch":[82.0457816743453,4.34523248843710382e-12,0],"luv":[82.0457816743453,4.08534684758697557e-12,1.48019813318368677e-12],"rgb":[0.8,0.8,0.8],"xyz":[0.573911273130880861,0.603827338855333573,0.657602843501112644],"hpluv":[0,1.02065966511349575e-11,82.0457816743453],"hsluv":[0,1.01642596056880755e-11,82.0457816743453]},"#ccccdd":{"lch":[82.5094539517328087,13.5418343873660199,265.874320218194214],"luv":[82.5094539517328087,-0.974260325972223118,-13.5067425899839115],"rgb":[0.8,0.8,0.866666666666666696],"xyz":[0.59542959868151446,0.612434669075587079,0.770932691401118642],"hpluv":[265.874320218194214,32.7843842039110882,82.5094539517328087],"hsluv":[265.874320218194214,30.4637656032122131,82.5094539517328087]},"#ccccee":{"lch":[83.0175175610870895,27.4698052042972165,265.874320218185687],"luv":[83.0175175610870895,-1.97630103922669687,-27.3986209901955817],"rgb":[0.8,0.8,0.933333333333333348],"xyz":[0.61924177894768917,0.621959541182057096,0.896343507469641865],"hpluv":[265.874320218185687,68.7964750954906776,83.0175175610870895],"hsluv":[265.874320218185687,63.7216981471091941,83.0175175610870895]},"#ccccff":{"lch":[83.5699624582004219,41.6509292947620153,265.874320218182845],"luv":[83.5699624582004219,-2.99655473483939438,-41.5429966521238825],"rgb":[0.8,0.8,1],"xyz":[0.645412827357520591,0.63242796054598982,1.03417769576142371],"hpluv":[265.874320218182845,108.336501116640306,83.5699624582004219],"hsluv":[265.874320218182845,99.9999999999952536,83.5699624582004219]},"#555500":{"lch":[34.8595382729148753,38.4291768930055397,85.8743202181747307],"luv":[34.8595382729148753,2.76476741155027961,38.3295929776711901],"rgb":[0.333333333333333315,0.333333333333333315,0],"xyz":[0.0699458591636312466,0.084283637721745866,0.0125839024113732767],"hpluv":[85.8743202181747307,139.887458074797564,34.8595382729148753],"hsluv":[85.8743202181747307,100.000000000002331,34.8595382729148753]},"#555511":{"lch":[34.9408046802893,35.5443725161734108,85.8743202181745318],"luv":[34.9408046802893,2.55722164100294558,35.4522641737772517],"rgb":[0.333333333333333315,0.333333333333333315,0.0666666666666666657],"xyz":[0.0709575246632683648,0.0846883039216007188,0.0179120073761289064],"hpluv":[85.8743202181745318,129.085444875460666,34.9408046802893],"hsluv":[85.8743202181745318,92.2780688504912,34.9408046802893]},"#555522":{"lch":[35.0907688239250604,30.4130442263608813,85.8743202181740202],"luv":[35.0907688239250604,2.18805086034508589,30.3342330139914047],"rgb":[0.333333333333333315,0.333333333333333315,0.133333333333333331],"xyz":[0.0728328828017454,0.0854384471769915332,0.027788893572108106],"hpluv":[85.8743202181740202,109.978131404858061,35.0907688239250604],"hsluv":[85.8743202181740202,78.6190076783406653,35.0907688239250604]},"#555533":{"lch":[35.3357817552570097,22.5221214621125654,85.8743202181728549],"luv":[35.3357817552570097,1.62034247131604014,22.4637584885032275],"rgb":[0.333333333333333315,0.333333333333333315,0.2],"xyz":[0.0759206335342031274,0.0866735474699746461,0.0440510474297192492],"hpluv":[85.8743202181728549,80.8786547215116656,35.3357817552570097],"hsluv":[85.8743202181728549,57.8169450175211566,35.3357817552570097]},"#555544":{"lch":[35.6854507669058592,12.1926559388895619,85.8743202181691743],"luv":[35.6854507669058592,0.877194374836262392,12.1610603515028455],"rgb":[0.333333333333333315,0.333333333333333315,0.266666666666666663],"xyz":[0.080378628778422,0.0884567455676622261,0.0675298223826058808],"hpluv":[85.8743202181691743,43.355725530805,35.6854507669058592],"hsluv":[85.8743202181691743,30.9932899828832262,35.6854507669058592]},"#555555":{"lch":[36.1458508397197278,1.89718584003012571e-12,0],"luv":[36.1458508397197278,1.79982851973451413e-12,5.9994283991150471e-13],"rgb":[0.333333333333333315,0.333333333333333315,0.333333333333333315],"xyz":[0.086341042817784,0.090841711183407059,0.0989318696565798],"hpluv":[0,6.66025333978279224e-12,36.1458508397197278],"hsluv":[0,1.90696849203660445e-12,36.1458508397197278]},"#555566":{"lch":[36.7200402720523087,13.391014832031539,265.874320218184835],"luv":[36.7200402720523087,-0.963409690459316,-13.3563138627398903],"rgb":[0.333333333333333315,0.333333333333333315,0.4],"xyz":[0.0939260385912921714,0.0938757094928103775,0.138879514063723758],"hpluv":[265.874320218184835,46.2753453717946712,36.7200402720523087],"hsluv":[265.874320218184835,10.0205788523093844,36.7200402720523087]},"#555577":{"lch":[37.4084382237490445,27.3651172837118537,265.874320218181],"luv":[37.4084382237490445,-1.96876932050326592,-27.294204353927416],"rgb":[0.333333333333333315,0.333333333333333315,0.466666666666666674],"xyz":[0.103240051611494091,0.0976013147008911869,0.187933315970121667],"hpluv":[265.874320218181,92.8254499938530131,37.4084382237490445],"hsluv":[265.874320218181,20.457601163446,37.4084382237490445]},"#555588":{"lch":[38.2091925227490421,41.4380747403329508,265.874320218179832],"luv":[38.2091925227490421,-2.98124102314999906,-41.330693680935326],"rgb":[0.333333333333333315,0.333333333333333315,0.533333333333333326],"xyz":[0.114380468713437919,0.102057481541668785,0.246606179373693835],"hpluv":[265.874320218179832,137.616667264503377,38.2091925227490421],"hsluv":[265.874320218179832,30.9677616121988244,38.2091925227490421]},"#555599":{"lch":[39.1185695394092079,55.2798607696674651,265.874320218179207],"luv":[39.1185695394092079,-3.97708121608675258,-55.1366106295487626],"rgb":[0.333333333333333315,0.333333333333333315,0.6],"xyz":[0.127437432822510632,0.107280267185297942,0.315372857014811769],"hpluv":[265.874320218179207,179.317758559659353,39.1185695394092079],"hsluv":[265.874320218179207,41.3377460212352688,39.1185695394092079]},"#5555aa":{"lch":[40.1313601009005083,68.6985541131433166,265.874320218178866],"luv":[40.1313601009005083,-4.94248222285034178,-68.5205312786852829],"rgb":[0.333333333333333315,0.333333333333333315,0.66666666666666663],"xyz":[0.142495125787763188,0.113303344371399051,0.394676706631810315],"hpluv":[265.874320218178866,217.221618066114,40.1313601009005083],"hsluv":[265.874320218178866,51.4705865731736907,40.1313601009005083]},"#5555bb":{"lch":[41.2412811653463791,81.6070675548115787,265.874320218178639],"luv":[41.2412811653463791,-5.8711785983783864,-81.3955940869131],"rgb":[0.333333333333333315,0.333333333333333315,0.733333333333333282],"xyz":[0.159632717895099807,0.120158381214333809,0.484934691730452117],"hpluv":[265.874320218178639,251.093199488524249,41.2412811653463791],"hsluv":[265.874320218178639,61.3584924374872642,41.2412811653463791]},"#5555cc":{"lch":[42.4413509436270431,93.9883543596933,265.874320218178468],"luv":[42.4413509436270431,-6.76194392407029365,-93.7447964935174838],"rgb":[0.333333333333333315,0.333333333333333315,0.8],"xyz":[0.178925093338821561,0.127875331391822611,0.586541202400722272],"hpluv":[265.874320218178468,281.011551484187919,42.4413509436270431],"hsluv":[265.874320218178468,71.0546332315999791,42.4413509436270431]},"#5555dd":{"lch":[43.7242196004532389,105.866759380085014,265.874320218178411],"luv":[43.7242196004532389,-7.61652967783202328,-105.592420264465588],"rgb":[0.333333333333333315,0.333333333333333315,0.866666666666666696],"xyz":[0.200443418889455105,0.136482661612076145,0.69987105030072827],"hpluv":[265.874320218178411,307.239379297131052,43.7242196004532389],"hsluv":[265.874320218178411,80.6500300064864462,43.7242196004532389]},"#5555ee":{"lch":[45.0824447652298588,117.287521338877212,265.874320218178354],"luv":[45.0824447652298588,-8.43819053636753402,-116.983586892732674],"rgb":[0.333333333333333315,0.333333333333333315,0.933333333333333348],"xyz":[0.224255599155629842,0.146007533718546162,0.825281866369251493],"hpluv":[265.874320218178354,330.128999417958312,45.0824447652298588],"hsluv":[265.874320218178354,90.2572110855712708,45.0824447652298588]},"#5555ff":{"lch":[46.508708270344421,128.30356479361032,265.874320218178241],"luv":[46.508708270344421,-9.23073412981071,-127.971083789162734],"rgb":[0.333333333333333315,0.333333333333333315,1],"xyz":[0.250426647565461236,0.156475953082478858,0.963116054661033338],"hpluv":[265.874320218178241,350.061034522531031,46.508708270344421],"hsluv":[265.874320218178241,99.9999999999992468,46.508708270344421]},"#ccdd00":{"lch":[84.2515012159558552,94.1174138813685772,92.7819892835375555],"luv":[84.2515012159558552,-4.56806363508048818,94.0064912138661128],"rgb":[0.8,0.866666666666666696,0],"xyz":[0.507566029502865779,0.645503626279608334,0.0978568736941549666],"hpluv":[92.7819892835375555,256.902059824464118,84.2515012159558552],"hsluv":[92.7819892835375555,100.000000000002373,84.2515012159558552]},"#ccdd11":{"lch":[84.2724460606142287,93.1910749716768692,92.8373396690251695],"luv":[84.2724460606142287,-4.61302172096193619,93.0768310858219508],"rgb":[0.8,0.866666666666666696,0.0666666666666666657],"xyz":[0.508577695002502939,0.645908292479463242,0.103184978658910603],"hpluv":[92.8373396690251695,254.758074317949962,84.2724460606142287],"hsluv":[92.8373396690251695,98.9747327605244465,84.2724460606142287]},"#ccdd22":{"lch":[84.3112490917695396,91.4838404394451175,92.9423140418060711],"luv":[84.3112490917695396,-4.69591125178302349,91.3632392106652],"rgb":[0.8,0.866666666666666696,0.133333333333333331],"xyz":[0.510453053140979884,0.646658435734854,0.113061864854889796],"hpluv":[92.9423140418060711,250.792999873820406,84.3112490917695396],"hsluv":[92.9423140418060711,97.0860193213801637,84.3112490917695396]},"#ccdd33":{"lch":[84.3750724084435291,88.7007441607730271,93.1221866378423329],"luv":[84.3750724084435291,-4.83112791130122865,88.5690816130525],"rgb":[0.8,0.866666666666666696,0.2],"xyz":[0.513540803873437701,0.647893536027837169,0.129324018712500932],"hpluv":[93.1221866378423329,244.290353733928498,84.3750724084435291],"hsluv":[93.1221866378423329,94.0094146319777,84.3750724084435291]},"#ccdd44":{"lch":[84.4670755276021197,84.7426243382763857,93.3985511967960491],"luv":[84.4670755276021197,-5.02363867224446459,84.5935897939611152],"rgb":[0.8,0.866666666666666696,0.266666666666666663],"xyz":[0.517998799117656561,0.649676734125524735,0.152802793665387571],"hpluv":[93.3985511967960491,234.956854948695792,84.4670755276021197],"hsluv":[93.3985511967960491,89.638788485123,84.4670755276021197]},"#ccdd55":{"lch":[84.5898637292301601,79.5568981087007359,93.8026723407881633],"luv":[84.5898637292301601,-5.27624840258561711,79.3817437416967095],"rgb":[0.8,0.866666666666666696,0.333333333333333315],"xyz":[0.523961213157018491,0.652061699741269485,0.184204840939361486],"hpluv":[93.8026723407881633,222.570337020009788,84.5898637292301601],"hsluv":[93.8026723407881633,83.9211409492819485,84.5898637292301601]},"#ccdd66":{"lch":[84.7456349568684857,73.1331501088793772,94.3836122863904],"luv":[84.7456349568684857,-5.58984810871231,72.9192103836116],"rgb":[0.8,0.866666666666666696,0.4],"xyz":[0.531546208930526731,0.655095698050672803,0.224152485346505448],"hpluv":[94.3836122863904,206.963810787645969,84.7456349568684857],"hsluv":[94.3836122863904,76.851201462777,84.7456349568684857]},"#ccdd77":{"lch":[84.9362580835765186,65.5005774458529828,95.2238145131341156],"luv":[84.9362580835765186,-5.96359854749608687,65.2285300930849274],"rgb":[0.8,0.866666666666666696,0.466666666666666674],"xyz":[0.540860221950728581,0.658821303258753654,0.273206287252903357],"hpluv":[95.2238145131341156,188.015270942662227,84.9362580835765186],"hsluv":[95.2238145131341156,68.4671748287691,84.9362580835765186]},"#ccdd88":{"lch":[85.1633194008604733,56.7265968622164536,96.4730545580279],"luv":[85.1633194008604733,-6.39512608731957588,56.3649638862273221],"rgb":[0.8,0.866666666666666696,0.533333333333333326],"xyz":[0.552000639052672493,0.663277470099531197,0.331879150656475552],"hpluv":[96.4730545580279,165.642146962004915,85.1633194008604733],"hsluv":[96.4730545580279,58.8458897999489707,85.1633194008604733]},"#ccdd99":{"lch":[85.4281525463895548,46.9188240443766134,98.432972024211054],"luv":[85.4281525463895548,-6.88075351903593724,46.4115425375783843],"rgb":[0.8,0.866666666666666696,0.6],"xyz":[0.565057603161745137,0.66850025574316041,0.400645828297593432],"hpluv":[98.432972024211054,139.807612964747022,85.4281525463895548],"hsluv":[98.432972024211054,48.0968721297954644,85.4281525463895548]},"#ccddaa":{"lch":[85.7318592309590457,36.2402041704229134,101.807730551991185],"luv":[85.7318592309590457,-7.41576493035038453,35.4733537857886176],"rgb":[0.8,0.866666666666666696,0.66666666666666663],"xyz":[0.580115296126997748,0.674523332929261477,0.479949677914592032],"hpluv":[101.807730551991185,110.570541660882469,85.7318592309590457],"hsluv":[101.807730551991185,36.355428538792907,85.7318592309590457]},"#ccddbb":{"lch":[86.0753247228475828,24.9849555175277693,108.661729708420211],"luv":[86.0753247228475828,-7.99469198849898,23.671351930590518],"rgb":[0.8,0.866666666666666696,0.733333333333333282],"xyz":[0.597252888234334312,0.681378369772196235,0.570207663013233779],"hpluv":[108.661729708420211,78.3375416693066313,86.0753247228475828],"hsluv":[108.661729708420211,23.7751141135998658,86.0753247228475828]},"#ccddcc":{"lch":[86.4592303781436158,14.0773589090278701,127.715012949224516],"luv":[86.4592303781436158,-8.61160385902942771,11.1360815742673065],"rgb":[0.8,0.866666666666666696,0.8],"xyz":[0.616545263678056066,0.689095319949685092,0.671814173683503935],"hpluv":[127.715012949224516,45.5363150686036633,86.4592303781436158],"hsluv":[127.715012949224516,10.5200784033656536,86.4592303781436158]},"#ccdddd":{"lch":[86.8840646031333677,9.47353258269296106,192.177050630057835],"luv":[86.8840646031333677,-9.26038246071566817,-1.99828333241680145],"rgb":[0.8,0.866666666666666696,0.866666666666666696],"xyz":[0.638063589228689665,0.697702650169938599,0.785144021583509932],"hpluv":[192.177050630057835,31.7497104564534354,86.8840646031333677],"hsluv":[192.177050630057835,13.7818607651735867,86.8840646031333677]},"#ccddee":{"lch":[87.3501331068194276,18.4943223550678582,237.507437159903361],"luv":[87.3501331068194276,-9.9349674143158051,-15.5992429896340141],"rgb":[0.8,0.866666666666666696,0.933333333333333348],"xyz":[0.661875769494864374,0.707227522276408616,0.910554837652033155],"hpluv":[237.507437159903361,64.5162574350921432,87.3501331068194276],"hsluv":[237.507437159903361,51.9237885878372083,87.3501331068194276]},"#ccddff":{"lch":[87.8575689716950876,31.3946063828198874,250.2096672964189],"luv":[87.8575689716950876,-10.6295595905023852,-29.5403752996496962],"rgb":[0.8,0.866666666666666696,1],"xyz":[0.688046817904695795,0.717695941640341339,1.04838902594381489],"hpluv":[250.2096672964189,114.576774718516177,87.8575689716950876],"hsluv":[250.2096672964189,99.999999999992923,87.8575689716950876]},"#556600":{"lch":[40.3019892206732919,46.2375853800199934,99.381148915360626],"luv":[40.3019892206732919,-7.53678920078613679,45.6191967302971264],"rgb":[0.333333333333333315,0.4,0],"xyz":[0.0849739168694777086,0.114339753133439206,0.0175932549799886241],"hpluv":[99.381148915360626,145.582103533726,40.3019892206732919],"hsluv":[99.381148915360626,100.000000000002302,40.3019892206732919]},"#556611":{"lch":[40.3683315206726334,43.7939991819964618,99.9948312384981364],"luv":[40.3683315206726334,-7.60085740022420797,43.1293557931736729],"rgb":[0.333333333333333315,0.4,0.0666666666666666657],"xyz":[0.0859855823691148269,0.114744419333294059,0.0229213599447442573],"hpluv":[99.9948312384981364,137.661701347396985,40.3683315206726334],"hsluv":[99.9948312384981364,94.2576138599214204,40.3683315206726334]},"#556622":{"lch":[40.4909010608148421,39.4175015547736436,101.28961011017671],"luv":[40.4909010608148421,-7.7166980000465113,38.6547797923705758],"rgb":[0.333333333333333315,0.4,0.133333333333333331],"xyz":[0.0878609405075918559,0.115494562588684874,0.0327982461407234499],"hpluv":[101.28961011017671,123.529583899053776,40.4909010608148421],"hsluv":[101.28961011017671,83.977954812826539,40.4909010608148421]},"#556633":{"lch":[40.6915589391927455,32.6300466430477343,104.01044750968255],"luv":[40.6915589391927455,-7.89969574444685207,31.6593548745491518],"rgb":[0.333333333333333315,0.4,0.2],"xyz":[0.0909486912400495895,0.116729662881667987,0.0490603999983346],"hpluv":[104.01044750968255,101.754281640855311,40.6915589391927455],"hsluv":[104.01044750968255,68.015525760737134,40.6915589391927455]},"#556644":{"lch":[40.9787805135115306,23.7356999706126039,110.078417815454017],"luv":[40.9787805135115306,-8.1486066005911173,22.2931304119395044],"rgb":[0.333333333333333315,0.4,0.266666666666666663],"xyz":[0.0954066864842684631,0.118512860979355567,0.0725391749512212386],"hpluv":[110.078417815454017,73.4991539757345436,40.9787805135115306],"hsluv":[110.078417815454017,46.8659194429644117,40.9787805135115306]},"#556655":{"lch":[41.3584605937638372,13.8246485480389332,127.71501294923371],"luv":[41.3584605937638372,-8.45701225317865202,10.9361716896901875],"rgb":[0.333333333333333315,0.4,0.333333333333333315],"xyz":[0.101369100523630462,0.120897826595100399,0.10394122222519514],"hpluv":[127.71501294923371,42.4159365242361659,41.3584605937638372],"hsluv":[127.71501294923371,21.5972717302380097,41.3584605937638372]},"#556666":{"lch":[41.8343160733152146,9.01834401177998402,192.177050630060307],"luv":[41.8343160733152146,-8.8154354231024481,-1.90226891261946607],"rgb":[0.333333333333333315,0.4,0.4],"xyz":[0.108954096297138633,0.123931824904503718,0.143888866632339102],"hpluv":[192.177050630060307,27.3547941496945484,41.8343160733152146],"hsluv":[192.177050630060307,27.2477194602778816,41.8343160733152146]},"#556677":{"lch":[42.4081371223492525,18.1914318380534858,239.570903430569189],"luv":[42.4081371223492525,-9.21344558994119289,-15.6856817728697795],"rgb":[0.333333333333333315,0.4,0.466666666666666674],"xyz":[0.118268109317340553,0.127657430112584541,0.192942668538737],"hpluv":[239.570903430569189,54.4323412384199443,42.4081371223492525],"hsluv":[239.570903430569189,33.1626844996427934,42.4081371223492525]},"#556688":{"lch":[43.0800011190655425,31.444407039181371,252.144687081813345],"luv":[43.0800011190655425,-9.64130614192028546,-29.9298504828121246],"rgb":[0.333333333333333315,0.4,0.533333333333333326],"xyz":[0.129408526419284381,0.132113596953362111,0.251615531942309179],"hpluv":[252.144687081813345,92.6204805766441694,43.0800011190655425],"hsluv":[252.144687081813345,39.0862788716996903,43.0800011190655425]},"#556699":{"lch":[43.8484890486876964,45.3842681536749,257.153237313451427],"luv":[43.8484890486876964,-10.090933534038701,-44.2482186789059639],"rgb":[0.333333333333333315,0.4,0.6],"xyz":[0.142465490528357108,0.137336382596991269,0.320382209583427113],"hpluv":[257.153237313451427,131.337888607863903,43.8484890486876964],"hsluv":[257.153237313451427,44.8182326355090055,43.8484890486876964]},"#5566aa":{"lch":[44.7109144588579,59.3119903927914223,259.748012643434],"luv":[44.7109144588579,-10.5562103110165033,-58.3650462882037928],"rgb":[0.333333333333333315,0.4,0.66666666666666663],"xyz":[0.157523183493609636,0.143359459783092391,0.399686059200425714],"hpluv":[259.748012643434,168.332615885742257,44.7109144588579],"hsluv":[259.748012643434,50.2202557252039341,44.7109144588579]},"#5566bb":{"lch":[45.6635615252987463,72.9454914642558805,261.300749278862554],"luv":[45.6635615252987463,-11.0328519112314041,-72.1063166696695532],"rgb":[0.333333333333333315,0.4,0.733333333333333282],"xyz":[0.174660775600946283,0.15021449662602715,0.48994404429906746],"hpluv":[261.300749278862554,202.706651650989187,45.6635615252987463],"hsluv":[261.300749278862554,56.1551480082100767,45.6635615252987463]},"#5566cc":{"lch":[46.7019230239281953,86.153038102066219,262.316955218783903],"luv":[46.7019230239281953,-11.5180515282988498,-85.3796255742992],"rgb":[0.333333333333333315,0.4,0.8],"xyz":[0.193953151044668037,0.157931446803515951,0.591550554969337616],"hpluv":[262.316955218783903,234.085848684940913,46.7019230239281953],"hsluv":[262.316955218783903,67.0801136297732086,46.7019230239281953]},"#5566dd":{"lch":[47.8209277182799539,98.8836589551542,263.023825475898036],"luv":[47.8209277182799539,-12.010072956506761,-98.1515978267222664],"rgb":[0.333333333333333315,0.4,0.866666666666666696],"xyz":[0.215471476595301581,0.166538777023769485,0.704880402869343614],"hpluv":[263.023825475898036,262.38914084011509,47.8209277182799539],"hsluv":[263.023825475898036,77.9738615315733909,47.8209277182799539]},"#5566ee":{"lch":[49.0151480019121095,111.133834597019145,263.537783903780621],"luv":[49.0151480019121095,-12.5078880087352609,-110.427722650603215],"rgb":[0.333333333333333315,0.4,0.933333333333333348],"xyz":[0.23928365686147629,0.176063649130239502,0.830291218937866837],"hpluv":[263.537783903780621,287.710232398192659,49.0151480019121095],"hsluv":[263.537783903780621,88.9133133505171145,49.0151480019121095]},"#5566ff":{"lch":[50.2789812841098751,122.927042369796439,263.924295565134457],"luv":[50.2789812841098751,-13.0108962765956715,-122.236550687040406],"rgb":[0.333333333333333315,0.4,1],"xyz":[0.265454705271307712,0.186532068494172198,0.968125407229648682],"hpluv":[263.924295565134457,310.2417842032321,50.2789812841098751],"hsluv":[263.924295565134457,99.99999999999919,50.2789812841098751]},"#ccee00":{"lch":[88.9159222564839382,101.512339113439552,98.3897184755654],"luv":[88.9159222564839382,-14.8112090817394879,100.426007975120399],"rgb":[0.8,0.933333333333333348,0],"xyz":[0.554744805843380595,0.739861178960639299,0.113583132474326151],"hpluv":[98.3897184755654,409.405376777149172,88.9159222564839382],"hsluv":[98.3897184755654,100.000000000002402,88.9159222564839382]},"#ccee11":{"lch":[88.9350466502285855,100.665090554083037,98.4749110233884863],"luv":[88.9350466502285855,-14.8356507509631186,99.5658773027044],"rgb":[0.8,0.933333333333333348,0.0666666666666666657],"xyz":[0.555756471343017755,0.740265845160494207,0.118911237439081788],"hpluv":[98.4749110233884863,406.753799510206477,88.9350466502285855],"hsluv":[98.4749110233884863,99.103544824997428,88.9350466502285855]},"#ccee22":{"lch":[88.9704797513205108,99.1029038393990191,98.635890718104875],"luv":[88.9704797513205108,-14.8807650249594605,97.9793262973016823],"rgb":[0.8,0.933333333333333348,0.133333333333333331],"xyz":[0.557631829481494701,0.741015988415885,0.12878812363506098],"hpluv":[98.635890718104875,401.844579090604725,88.9704797513205108],"hsluv":[98.635890718104875,97.4508266239822376,88.9704797513205108]},"#ccee33":{"lch":[89.0287677898111696,96.5543294248683281,98.9099371535565837],"luv":[89.0287677898111696,-14.95450175665089,95.3892101230339335],"rgb":[0.8,0.933333333333333348,0.2],"xyz":[0.560719580213952518,0.742251088708868134,0.145050277492672131],"hpluv":[98.9099371535565837,393.778440936160052,89.0287677898111696],"hsluv":[98.9099371535565837,94.7550356083218333,89.0287677898111696]},"#ccee44":{"lch":[89.1128082270408157,92.9258219449750698,99.3266297509707101],"luv":[89.1128082270408157,-15.0597883526499068,91.6973890518296],"rgb":[0.8,0.933333333333333348,0.266666666666666663],"xyz":[0.565177575458171377,0.7440342868065557,0.168529052445558769],"hpluv":[99.3266297509707101,382.168331694223468,89.1128082270408157],"hsluv":[99.3266297509707101,90.9176847425828782,89.1128082270408157]},"#ccee55":{"lch":[89.224999764075946,88.1655281542066263,99.9265688821158591],"luv":[89.224999764075946,-15.1984931464969293,86.8456456063635187],"rgb":[0.8,0.933333333333333348,0.333333333333333315],"xyz":[0.571139989497533307,0.74641925242230045,0.199931099719532657],"hpluv":[99.9265688821158591,366.702481299920066,89.224999764075946],"hsluv":[99.9265688821158591,85.8839575374920372,89.224999764075946]},"#ccee66":{"lch":[89.3673776950467555,82.2600687786622444,100.76990980050725],"luv":[89.3673776950467555,-15.3715621348797811,80.8111006793235873],"rgb":[0.8,0.933333333333333348,0.4],"xyz":[0.578724985271041548,0.749453250731703768,0.239878744126676646],"hpluv":[100.76990980050725,347.124780760482849,89.3673776950467555],"hsluv":[100.76990980050725,79.6381055931254451,89.3673776950467555]},"#ccee77":{"lch":[89.5416863487684651,75.2338064272131817,101.95104715507324],"luv":[89.5416863487684651,-15.5791079616514043,73.6031047215169707],"rgb":[0.8,0.933333333333333348,0.466666666666666674],"xyz":[0.588038998291243398,0.753178855939784619,0.288932546033074555],"hpluv":[101.95104715507324,323.225079834159544,89.5416863487684651],"hsluv":[101.95104715507324,72.2002225208687349,89.5416863487684651]},"#ccee88":{"lch":[89.7494222523926481,67.150335761217363,103.626883623375818],"luv":[89.7494222523926481,-15.8204941270879562,65.2600916212887654],"rgb":[0.8,0.933333333333333348,0.533333333333333326],"xyz":[0.599179415393187309,0.757635022780562162,0.347605409436646695],"hpluv":[103.626883623375818,294.840431689210504,89.7494222523926481],"hsluv":[103.626883623375818,63.6228180815060256,89.7494222523926481]},"#ccee99":{"lch":[89.9918618926625697,58.1187887690418705,106.076645299715267],"luv":[89.9918618926625697,-16.094429395756972,55.8458857070554586],"rgb":[0.8,0.933333333333333348,0.6],"xyz":[0.61223637950226,0.762857808424191375,0.41637208707776463],"hpluv":[106.076645299715267,261.881276027636488,89.9918618926625697],"hsluv":[106.076645299715267,53.9866751643902418,89.9918618926625697]},"#cceeaa":{"lch":[90.2700807835134071,48.3136880988356481,109.842100564752428],"luv":[90.2700807835134071,-16.3990756203548145,45.4453823452884791],"rgb":[0.8,0.933333333333333348,0.66666666666666663],"xyz":[0.627294072467512565,0.768880885610292442,0.495675936694763231],"hpluv":[109.842100564752428,224.429228200920562,90.2700807835134071],"hsluv":[109.842100564752428,43.3959332818477037,90.2700807835134071]},"#cceebb":{"lch":[90.5849674500281736,38.0375276056681,116.096591597387416],"luv":[90.5849674500281736,-16.7321662581560417,34.1597441246474745],"rgb":[0.8,0.933333333333333348,0.733333333333333282],"xyz":[0.644431664574849128,0.7757359224532272,0.585933921793405],"hpluv":[116.096591597387416,183.067580850930824,90.5849674500281736],"hsluv":[116.096591597387416,31.9725829176952736,90.5849674500281736]},"#cceecc":{"lch":[90.9372344233822,27.9388105970907,127.715012949233042],"luv":[90.9372344233822,-17.0911298567764973,22.1013668762570106],"rgb":[0.8,0.933333333333333348,0.8],"xyz":[0.663724040018570882,0.783452872630716057,0.687540432463675133],"hpluv":[127.715012949233042,140.086760618050221,90.9372344233822],"hsluv":[127.715012949233042,30.3633811556705,90.9372344233822]},"#cceedd":{"lch":[91.327427526889025,19.8359452431300802,151.749458426713772],"luv":[91.327427526889025,-17.4732117028180483,9.38890816213244861],"rgb":[0.8,0.933333333333333348,0.866666666666666696],"xyz":[0.685242365569204481,0.792060202850969564,0.800870280363681131],"hpluv":[151.749458426713772,104.258293798779974,91.327427526889025],"hsluv":[151.749458426713772,29.0871711351253381,91.327427526889025]},"#cceeee":{"lch":[91.7559342603931,18.2870370266976643,192.177050630059739],"luv":[91.7559342603931,-17.87558711202,-3.8573447624494035],"rgb":[0.8,0.933333333333333348,0.933333333333333348],"xyz":[0.709054545835379191,0.801585074957439581,0.926281096432204354],"hpluv":[192.177050630059739,101.458793010104,91.7559342603931],"hsluv":[192.177050630059739,27.4217374065650326,91.7559342603931]},"#cceeff":{"lch":[92.2229917973594553,25.3309747642836847,223.758903531404655],"luv":[92.2229917973594553,-18.2954610486514362,-17.5195430170439934],"rgb":[0.8,0.933333333333333348,1],"xyz":[0.735225594245210612,0.812053494321372304,1.06411528472398609],"hpluv":[223.758903531404655,149.53216426558339,92.2229917973594553],"hsluv":[223.758903531404655,99.9999999999890861,92.2229917973594553]},"#557700":{"lch":[45.8045523271613533,55.5294361467329836,107.801769483020877],"luv":[45.8045523271613533,-16.9767207468495087,52.8706840456749276],"rgb":[0.333333333333333315,0.466666666666666674,0],"xyz":[0.103427654922895337,0.151247229240274977,0.023744500997794328],"hpluv":[107.801769483020877,153.83457187868342,45.8045523271613533],"hsluv":[107.801769483020877,100.000000000002288,45.8045523271613533]},"#557711":{"lch":[45.859623178970125,53.470483995502839,108.496139146384877],"luv":[45.859623178970125,-16.9630166203079504,50.7084679896019068],"rgb":[0.333333333333333315,0.466666666666666674,0.0666666666666666657],"xyz":[0.104439320422532456,0.15165189544012983,0.0290726059625499578],"hpluv":[108.496139146384877,147.952722071756682,45.859623178970125],"hsluv":[108.496139146384877,95.6324690191426,45.859623178970125]},"#557722":{"lch":[45.9614512879267494,49.76586948312967,109.899607245517743],"luv":[45.9614512879267494,-16.93896350220896,46.7943723206405409],"rgb":[0.333333333333333315,0.466666666666666674,0.133333333333333331],"xyz":[0.106314678561009485,0.152402038695520659,0.0389494921585291573],"hpluv":[109.899607245517743,137.396980684000368,45.9614512879267494],"hsluv":[109.899607245517743,87.7486210093461239,45.9614512879267494]},"#557733":{"lch":[46.1283843073061,43.9801463057798472,112.602269297118809],"luv":[46.1283843073061,-16.9029726498973396,40.6022509803905223],"rgb":[0.333333333333333315,0.466666666666666674,0.2],"xyz":[0.109402429293467218,0.153637138988503757,0.0552116460161403],"hpluv":[112.602269297118809,120.983948144693443,46.1283843073061],"hsluv":[112.602269297118809,75.3373974156097432,46.1283843073061]},"#557744":{"lch":[46.3678258482665413,36.3216896494577526,117.654446368962965],"luv":[46.3678258482665413,-16.8582748313623227,32.1724060135666861],"rgb":[0.333333333333333315,0.466666666666666674,0.266666666666666663],"xyz":[0.113860424537686092,0.155420337086191351,0.0786904209690269391],"hpluv":[117.654446368962965,99.4005156049610861,46.3678258482665413],"hsluv":[117.654446368962965,58.5682493514162346,46.3678258482665413]},"#557755":{"lch":[46.6852246722490349,27.4798560002662136,127.715012949237362],"luv":[46.6852246722490349,-16.8103715694690621,21.7383047520213317],"rgb":[0.333333333333333315,0.466666666666666674,0.333333333333333315],"xyz":[0.119822838577048091,0.157805302701936184,0.110092468243000841],"hpluv":[127.715012949237362,74.6920408293198506,46.6852246722490349],"hsluv":[127.715012949237362,38.0315615795731219,46.6852246722490349]},"#557766":{"lch":[47.0844103757355299,19.3533005907945039,150.034269154893224],"luv":[47.0844103757355299,-16.7662346577491,9.66662397939114371],"rgb":[0.333333333333333315,0.466666666666666674,0.4],"xyz":[0.127407834350556276,0.160839301011339475,0.150040112650144802],"hpluv":[150.034269154893224,52.1575559127659147,47.0844103757355299],"hsluv":[150.034269154893224,41.6155983808333403,47.0844103757355299]},"#557777":{"lch":[47.5677829408255519,17.1184872206298522,192.177050630060563],"luv":[47.5677829408255519,-16.733329138647683,-3.61085871511915846],"rgb":[0.333333333333333315,0.466666666666666674,0.466666666666666674],"xyz":[0.136721847370758182,0.164564906219420298,0.199093914556542712],"hpluv":[192.177050630060563,45.665876663612373,47.5677829408255519],"hsluv":[192.177050630060563,45.4871270252879683,47.5677829408255519]},"#557788":{"lch":[48.1364533988364371,24.3189053895014062,226.569261606948],"luv":[48.1364533988364371,-16.7186932071720697,-17.6605338760746164],"rgb":[0.333333333333333315,0.466666666666666674,0.533333333333333326],"xyz":[0.147862264472702,0.169021073060197896,0.257766777960114879],"hpluv":[226.569261606948,64.1075619232690173,48.1364533988364371],"hsluv":[226.569261606948,49.4930397679002567,48.1364533988364371]},"#557799":{"lch":[48.7903733600049776,36.1922931768580227,242.470518495943224],"luv":[48.7903733600049776,-16.7282575252316086,-32.0943528610435749],"rgb":[0.333333333333333315,0.466666666666666674,0.6],"xyz":[0.160919228581774709,0.174243858703827054,0.326533455601232814],"hpluv":[242.470518495943224,94.128532149155447,48.7903733600049776],"hsluv":[242.470518495943224,53.4981409183259657,48.7903733600049776]},"#5577aa":{"lch":[49.5284680294880957,49.5215284063763121,250.210257263218182],"luv":[49.5284680294880957,-16.7664778987851584,-46.5968560588918308],"rgb":[0.333333333333333315,0.466666666666666674,0.66666666666666663],"xyz":[0.175976921547027265,0.180266935889928148,0.405837305218231414],"hpluv":[250.210257263218182,126.875705911364861,49.5284680294880957],"hsluv":[250.210257263218182,57.3943781585142503,49.5284680294880957]},"#5577bb":{"lch":[50.3487764471929324,63.2168000831305,254.554261837862072],"luv":[50.3487764471929324,-16.8362555209572413,-60.9336057753316069],"rgb":[0.333333333333333315,0.466666666666666674,0.733333333333333282],"xyz":[0.193114513654363912,0.187121972732862907,0.496095290316873161],"hpluv":[254.554261837862072,159.324628464713726,50.3487764471929324],"hsluv":[254.554261837862072,61.1035457400689737,50.3487764471929324]},"#5577cc":{"lch":[51.2485971738404942,76.8367273058076279,257.264224247337211],"luv":[51.2485971738404942,-16.9390629845235594,-74.9463195111900546],"rgb":[0.333333333333333315,0.466666666666666674,0.8],"xyz":[0.212406889098085638,0.194838922910351708,0.597701800987143317],"hpluv":[257.264224247337211,190.250673687597981,51.2485971738404942],"hsluv":[257.264224247337211,64.5753193228694329,51.2485971738404942]},"#5577dd":{"lch":[52.2246350466270428,90.1721178795433502,259.084439545341468],"luv":[52.2246350466270428,-17.075183181685393,-88.5406627612090347],"rgb":[0.333333333333333315,0.466666666666666674,0.866666666666666696],"xyz":[0.233925214648719182,0.203446253130605242,0.711031648887149315],"hpluv":[259.084439545341468,219.096874823476185,52.2246350466270428],"hsluv":[259.084439545341468,74.9139940771913757,52.2246350466270428]},"#5577ee":{"lch":[53.2731438322457791,103.123503170291656,260.373961187264626],"luv":[53.2731438322457791,-17.2439851141504441,-101.671539200978515],"rgb":[0.333333333333333315,0.466666666666666674,0.933333333333333348],"xyz":[0.257737394914893947,0.212971125237075287,0.836442464955672538],"hpluv":[260.373961187264626,245.63410016831412,53.2731438322457791],"hsluv":[260.373961187264626,87.3510385353649,53.2731438322457791]},"#5577ff":{"lch":[54.3900599484937572,115.652149768064447,261.324783585170792],"luv":[54.3900599484937572,-17.4441870719707097,-114.32899931064253],"rgb":[0.333333333333333315,0.466666666666666674,1],"xyz":[0.283908443324725313,0.223439544601007983,0.974276653247454383],"hpluv":[261.324783585170792,269.819603010977914,54.3900599484937572],"hsluv":[261.324783585170792,99.9999999999989768,54.3900599484937572]},"#ccff00":{"lch":[93.605159534834371,109.568762044642341,102.903766821995461],"luv":[93.605159534834371,-24.4682604068618268,106.801768939739262],"rgb":[0.8,1,0],"xyz":[0.606597178273054372,0.843565923819988406,0.130867256617550276],"hpluv":[102.903766821995461,795.170643052662513,93.605159534834371],"hsluv":[102.903766821995461,100.000000000002359,93.605159534834371]},"#ccff11":{"lch":[93.6226829283917681,108.793716578542018,103.00230683973929],"luv":[93.6226829283917681,-24.4775292120886689,106.004355243751533],"rgb":[0.8,1,0.0666666666666666657],"xyz":[0.607608843772691531,0.843970590019843314,0.136195361582305913],"hpluv":[103.00230683973929,791.823376913543598,93.6226829283917681],"hsluv":[103.00230683973929,99.9999999999883755,93.6226829283917681]},"#ccff22":{"lch":[93.6551518183817535,107.364125357399203,103.187929529698394],"luv":[93.6551518183817535,-24.4946701604029187,104.532609971684906],"rgb":[0.8,1,0.133333333333333331],"xyz":[0.609484201911168477,0.844720733275234115,0.146072247778285091],"hpluv":[103.187929529698394,785.615721446726184,93.6551518183817535],"hsluv":[103.187929529698394,99.9999999999883613,93.6551518183817535]},"#ccff33":{"lch":[93.7085695338431464,105.030410790236445,103.502196488744218],"luv":[93.7085695338431464,-24.5227776356263192,102.127472150246831],"rgb":[0.8,1,0.2],"xyz":[0.612571952643626294,0.845955833568217241,0.162334401635896242],"hpluv":[103.502196488744218,775.386532390006209,93.7085695338431464],"hsluv":[103.502196488744218,99.9999999999882334,93.7085695338431464]},"#ccff44":{"lch":[93.7856006692118456,101.704796230104463,103.975902087852319],"luv":[93.7856006692118456,-24.5631097372148304,98.6940687997238],"rgb":[0.8,1,0.266666666666666663],"xyz":[0.617029947887845154,0.847739031665904808,0.18581317658878288],"hpluv":[103.975902087852319,760.597322717251814,93.7856006692118456],"hsluv":[103.975902087852319,99.9999999999883329,93.7856006692118456]},"#ccff55":{"lch":[93.8884584724407887,97.3367975087049473,104.649262803016768],"luv":[93.8884584724407887,-24.6166025777849207,94.1725810773922802],"rgb":[0.8,1,0.333333333333333315],"xyz":[0.622992361927207083,0.850123997281649557,0.217215223862756796],"hpluv":[104.649262803016768,740.773636872505676,93.8884584724407887],"hsluv":[104.649262803016768,99.999999999988,93.8884584724407887]},"#ccff66":{"lch":[94.0190298395239381,91.9106503723783561,105.578857731119598],"luv":[94.0190298395239381,-24.6839280463924027,88.5340123798424514],"rgb":[0.8,1,0.4],"xyz":[0.630577357700715324,0.853157995591052876,0.257162868269900757],"hpluv":[105.578857731119598,715.472563222964368,94.0190298395239381],"hsluv":[105.578857731119598,99.9999999999875371,94.0190298395239381]},"#ccff77":{"lch":[94.1789424927264349,85.4453105292158597,106.848417981185563],"luv":[94.1789424927264349,-24.7655268674123263,81.7775627566241781],"rgb":[0.8,1,0.466666666666666674],"xyz":[0.639891370720917174,0.856883600799133727,0.306216670176298666],"hpluv":[106.848417981185563,684.262206540111833,94.1789424927264349],"hsluv":[106.848417981185563,99.9999999999873381,94.1789424927264349]},"#ccff88":{"lch":[94.3696051468525781,77.9966506735583778,108.587502777405675],"luv":[94.3696051468525781,-24.8616333733667219,73.92818611532],"rgb":[0.8,1,0.533333333333333326],"xyz":[0.651031787822861086,0.861339767639911269,0.364889533579870862],"hpluv":[108.587502777405675,646.714804777793233,94.3696051468525781],"hsluv":[108.587502777405675,99.9999999999870397,94.3696051468525781]},"#ccff99":{"lch":[94.5922333645115572,69.6635615227201868,111.00626449694991],"luv":[94.5922333645115572,-24.9722983929036886,65.0338074927618],"rgb":[0.8,1,0.6],"xyz":[0.66408875193193373,0.866562553283540482,0.433656211220988741],"hpluv":[111.00626449694991,602.43247210261859,94.5922333645115572],"hsluv":[111.00626449694991,99.999999999986656,94.5922333645115572]},"#ccffaa":{"lch":[94.8478672375315881,60.6030718965076574,114.464397640121035],"luv":[94.8478672375315881,-25.0974127381864349,55.1620539605116],"rgb":[0.8,1,0.66666666666666663],"xyz":[0.679146444897186341,0.872585630469641549,0.512960060837987397],"hpluv":[114.464397640121035,551.164539659931279,94.8478672375315881],"hsluv":[114.464397640121035,99.9999999999858886,94.8478672375315881]},"#ccffbb":{"lch":[95.1373841969384,51.0680528276179899,119.615591899534252],"luv":[95.1373841969384,-25.2367319023901224,44.3965469658538439],"rgb":[0.8,1,0.733333333333333282],"xyz":[0.696284037004522904,0.879440667312576307,0.603218045936629088],"hpluv":[119.615591899534252,493.192076617112832,95.1373841969384],"hsluv":[119.615591899534252,99.999999999985036,95.1373841969384]},"#ccffcc":{"lch":[95.4615088709507802,41.5047839306073527,127.715012949235671],"luv":[95.4615088709507802,-25.3899015983654444,32.8329101048280876],"rgb":[0.8,1,0.8],"xyz":[0.715576412448244659,0.887157617490065165,0.704824556606899244],"hpluv":[127.715012949235671,430.524428546451247,95.4615088709507802],"hsluv":[127.715012949235671,99.9999999999844,95.4615088709507802]},"#ccffdd":{"lch":[95.8208211701733603,32.8093273722257,141.163585516297758],"luv":[95.8208211701733603,-25.5564832849791728,20.5746962243056899],"rgb":[0.8,1,0.866666666666666696],"xyz":[0.737094737998878258,0.895764947710318671,0.818154404506905242],"hpluv":[141.163585516297758,370.598640927928557,95.8208211701733603],"hsluv":[141.163585516297758,99.9999999999829612,95.8208211701733603]},"#ccffee":{"lch":[96.2157633520208293,26.8716381406037179,163.283084738459195],"luv":[96.2157633520208293,-25.7359786647352209,7.72944619800421506],"rgb":[0.8,1,0.933333333333333348],"xyz":[0.760906918265053,0.905289819816788688,0.943565220575428465],"hpluv":[163.283084738459195,336.210724351278486,96.2157633520208293],"hsluv":[163.283084738459195,99.9999999999813411,96.2157633520208293]},"#ccffff":{"lch":[96.6466465538527899,26.5246444827845806,192.177050630060279],"luv":[96.6466465538527899,-25.9278521925209873,-5.59493034995961125],"rgb":[0.8,1,1],"xyz":[0.787077966674884388,0.915758239180721412,1.08139940886721031],"hpluv":[192.177050630060279,375.729722461639881,96.6466465538527899],"hsluv":[192.177050630060279,99.9999999999789111,96.6466465538527899]},"#558800":{"lch":[51.3121649295003266,65.2833526322192,113.133039202335894],"luv":[51.3121649295003266,-25.6477049188799029,60.0342515843809466],"rgb":[0.333333333333333315,0.533333333333333326,0],"xyz":[0.125500024647865804,0.195391968690216522,0.0311019575727842744],"hpluv":[113.133039202335894,161.443824642532,51.3121649295003266],"hsluv":[113.133039202335894,100.000000000002416,51.3121649295003266]},"#558811":{"lch":[51.3586018009433758,63.5282336791645363,113.757082680238781],"luv":[51.3586018009433758,-25.5929736747770171,58.1449582756467862],"rgb":[0.333333333333333315,0.533333333333333326,0.0666666666666666657],"xyz":[0.126511690147502937,0.195796634890071375,0.0364300625375399076],"hpluv":[113.757082680238781,156.961418592175818,51.3586018009433758],"hsluv":[113.757082680238781,96.6047658949560315,51.3586018009433758]},"#558822":{"lch":[51.4445144263052754,60.3557257759597761,114.985955444381503],"luv":[51.4445144263052754,-25.4940226670596211,54.707115096615226],"rgb":[0.333333333333333315,0.533333333333333326,0.133333333333333331],"xyz":[0.128387048285979938,0.196546778145462203,0.0463069487335191],"hpluv":[114.985955444381503,148.873956641671725,51.4445144263052754],"hsluv":[114.985955444381503,90.4397474873449454,51.4445144263052754]},"#558833":{"lch":[51.5854933484676366,55.3603846502330512,117.238150003797628],"luv":[51.5854933484676366,-25.3378965271949284,49.2215723864945502],"rgb":[0.333333333333333315,0.533333333333333326,0.2],"xyz":[0.131474799018437671,0.197781878438445302,0.0625691025911302434],"hpluv":[117.238150003797628,136.179218375975154,51.5854933484676366],"hsluv":[117.238150003797628,80.6386945119108844,51.5854933484676366]},"#558844":{"lch":[51.788002513998137,48.6519311113283521,121.094634958525788],"luv":[51.788002513998137,-25.1264429677671792,41.6614001762900799],"rgb":[0.333333333333333315,0.533333333333333326,0.266666666666666663],"xyz":[0.135932794262656559,0.199565076536132896,0.0860478775440168819],"hpluv":[121.094634958525788,119.20933058927335,51.788002513998137],"hsluv":[121.094634958525788,67.2069053574962112,51.788002513998137]},"#558855":{"lch":[52.0569745246593669,40.6501953066927229,127.715012949238655],"luv":[52.0569745246593669,-24.8671203906742271,32.1568764333225801],"rgb":[0.333333333333333315,0.533333333333333326,0.333333333333333315],"xyz":[0.141895208302018572,0.201950042151877729,0.117449924817990797],"hpluv":[127.715012949238655,99.0884509425644495,52.0569745246593669],"hsluv":[127.715012949238655,50.4536826414745647,52.0569745246593669]},"#558866":{"lch":[52.3961000606252156,32.296627997442414,139.535908661945541],"luv":[52.3961000606252156,-24.57168930668605,20.9595864611130054],"rgb":[0.333333333333333315,0.533333333333333326,0.4],"xyz":[0.149480204075526729,0.20498404046128102,0.157397569225134759],"hpluv":[139.535908661945541,78.2163498792783258,52.3961000606252156],"hsluv":[139.535908661945541,52.7717106037122505,52.3961000606252156]},"#558877":{"lch":[52.8079833364028417,25.6675371494617757,160.900154113051656],"luv":[52.8079833364028417,-24.2545338981935465,8.39881233868101873],"rgb":[0.333333333333333315,0.533333333333333326,0.466666666666666674],"xyz":[0.158794217095728663,0.208709645669361843,0.206451371131532668],"hpluv":[160.900154113051656,61.6770996704155934,52.8079833364028417],"hsluv":[160.900154113051656,55.3375604028527732,52.8079833364028417]},"#558888":{"lch":[53.2942460543653311,24.4817100724115,192.177050630060762],"luv":[53.2942460543653311,-23.9308828659180151,-5.16400748714853908],"rgb":[0.333333333333333315,0.533333333333333326,0.533333333333333326],"xyz":[0.169934634197672463,0.213165812510139441,0.265124234535104808],"hpluv":[192.177050630060762,58.2908991249141764,53.2942460543653311],"hsluv":[192.177050630060762,58.0627314448554515,53.2942460543653311]},"#558899":{"lch":[53.8556132197311399,30.5464388010487,219.367537814697016],"luv":[53.8556132197311399,-23.6152401502492637,-19.3753801529742589],"rgb":[0.333333333333333315,0.533333333333333326,0.6],"xyz":[0.18299159830674519,0.218388598153768598,0.333890912176222743],"hpluv":[219.367537814697016,71.9728892793730921,53.8556132197311399],"hsluv":[219.367537814697016,60.861676067449,53.8556132197311399]},"#5588aa":{"lch":[54.491995562986105,41.1624410064978434,235.49057853568965],"luv":[54.491995562986105,-23.3202411533326384,-33.9192114024460452],"rgb":[0.333333333333333315,0.533333333333333326,0.66666666666666663],"xyz":[0.198049291271997718,0.224411675339869693,0.413194761793221343],"hpluv":[235.49057853568965,95.8534470006528494,54.491995562986105],"hsluv":[235.49057853568965,63.6587877222075207,54.491995562986105]},"#5588bb":{"lch":[55.2025746803936102,53.7318677649407164,244.589939769846183],"luv":[55.2025746803936102,-23.0560079965343867,-48.5338449823709865],"rgb":[0.333333333333333315,0.533333333333333326,0.733333333333333282],"xyz":[0.215186883379334393,0.231266712182804451,0.503452746891863],"hpluv":[244.589939769846183,123.512789385845494,55.2025746803936102],"hsluv":[244.589939769846183,66.3923972476147,55.2025746803936102]},"#5588cc":{"lch":[55.9858924676882,67.0258402153595227,250.085698604565607],"luv":[55.9858924676882,-22.8299557310329213,-63.0179052166444436],"rgb":[0.333333333333333315,0.533333333333333326,0.8],"xyz":[0.234479258823056119,0.238983662360293253,0.60505925756213319],"hpluv":[250.085698604565607,151.915814945370954,55.9858924676882],"hsluv":[250.085698604565607,69.0160689386852653,55.9858924676882]},"#5588dd":{"lch":[56.8399439373084761,80.4799585659197589,253.656315856923044],"luv":[56.8399439373084761,-22.6469326722406379,-77.2278458285038596],"rgb":[0.333333333333333315,0.533333333333333326,0.866666666666666696],"xyz":[0.255997584373689691,0.247590992580546787,0.718389105462139188],"hpluv":[253.656315856923044,179.669115472769334,56.8399439373084761],"hsluv":[253.656315856923044,71.4978966707909791,56.8399439373084761]},"#5588ee":{"lch":[57.7622712344346212,93.8110643698785083,256.11666422549024],"luv":[57.7622712344346212,-22.5095618551803298,-91.0704969970917517],"rgb":[0.333333333333333315,0.533333333333333326,0.933333333333333348],"xyz":[0.2798097646398644,0.257115864687016804,0.843799921530662411],"hpluv":[256.11666422549024,206.086302990026525,57.7622712344346212],"hsluv":[256.11666422549024,85.5354286092897098,57.7622712344346212]},"#5588ff":{"lch":[58.7500561820581169,106.871298098059711,257.890974112124525],"luv":[58.7500561820581169,-22.4186692043534066,-104.493433421771144],"rgb":[0.333333333333333315,0.533333333333333326,1],"xyz":[0.305980813049695821,0.267584284050949528,0.981634109822444256],"hpluv":[257.890974112124525,230.829932612430156,58.7500561820581169],"hsluv":[257.890974112124525,99.9999999999988489,58.7500561820581169]},"#559900":{"lch":[56.7948235068901113,75.0667586450735769,116.650835958582277],"luv":[56.7948235068901113,-33.6713638042581849,67.0914116190665766],"rgb":[0.333333333333333315,0.6,0],"xyz":[0.151369625100333277,0.247131169595152217,0.0397251577236065259],"hpluv":[116.650835958582277,167.717444253109818,56.7948235068901113],"hsluv":[116.650835958582277,100.000000000002373,56.7948235068901113]},"#559911":{"lch":[56.8345345919718,73.5501475520203343,117.179331557793219],"luv":[56.8345345919718,-33.596019870913949,65.4288289193465431],"rgb":[0.333333333333333315,0.6,0.0666666666666666657],"xyz":[0.152381290599970409,0.24753583579500707,0.0450532626883621556],"hpluv":[117.179331557793219,164.214146288467191,56.8345345919718],"hsluv":[117.179331557793219,97.3073310640873501,56.8345345919718]},"#559922":{"lch":[56.9080340332033785,70.7973668034807559,118.203267177206257],"luv":[56.9080340332033785,-33.458907670269852,62.3920559351826256],"rgb":[0.333333333333333315,0.6,0.133333333333333331],"xyz":[0.154256648738447411,0.248285979050397898,0.0549301488843413552],"hpluv":[118.203267177206257,157.863907732936383,56.9080340332033785],"hsluv":[118.203267177206257,92.3971004449738444,56.9080340332033785]},"#559933":{"lch":[57.0287279601738675,66.4302504595433163,120.024921583566851],"luv":[57.0287279601738675,-33.2401456716524066,57.5158316626386181],"rgb":[0.333333333333333315,0.6,0.2],"xyz":[0.157344399470905172,0.249521079343381,0.0711923027419525],"hpluv":[120.024921583566851,147.812625691912672,57.0287279601738675],"hsluv":[120.024921583566851,84.5348632876942645,57.0287279601738675]},"#559944":{"lch":[57.2022813646338335,60.4886548808755862,122.993651447985457],"luv":[57.2022813646338335,-32.9388613723515604,50.7337045837447178],"rgb":[0.333333333333333315,0.6,0.266666666666666663],"xyz":[0.161802394715124032,0.251304277441068591,0.0946710776948391369],"hpluv":[122.993651447985457,134.183743453609452,57.2022813646338335],"hsluv":[122.993651447985457,73.6468983233054075,57.2022813646338335]},"#559955":{"lch":[57.4331244004656583,53.227141365646645,127.715012949239252],"luv":[57.4331244004656583,-32.5608701853658573,42.1060365117673499],"rgb":[0.333333333333333315,0.6,0.333333333333333315],"xyz":[0.167764808754486017,0.253689243056813396,0.126073124968813038],"hpluv":[127.715012949239252,117.600732304920115,57.4331244004656583],"hsluv":[127.715012949239252,59.8797334066369444,57.4331244004656583]},"#559966":{"lch":[57.7247064038159152,45.1954856350919556,135.286653522876605],"luv":[57.7247064038159152,-32.1175213159608433,31.7977475037242847],"rgb":[0.333333333333333315,0.6,0.4],"xyz":[0.175349804527994202,0.256723241366216715,0.166020769375957],"hpluv":[135.286653522876605,99.3510934192793371,57.7247064038159152],"hsluv":[135.286653522876605,61.4133131906424055,57.7247064038159152]},"#559977":{"lch":[58.0796295741768631,37.4448814339638858,147.624029462041108],"luv":[58.0796295741768631,-31.624170974627738,20.0507096076703846],"rgb":[0.333333333333333315,0.6,0.466666666666666674],"xyz":[0.184663817548196107,0.260448846574297566,0.215074571282354909],"hpluv":[147.624029462041108,81.8102930750829671,58.0796295741768631],"hsluv":[147.624029462041108,63.1432913181764448,58.0796295741768631]},"#559988":{"lch":[58.4997327930321092,31.9103493306277741,167.047427400638497],"luv":[58.4997327930321092,-31.0984204046450543,7.15252701768072],"rgb":[0.333333333333333315,0.6,0.533333333333333326],"xyz":[0.195804234650139963,0.264905013415075108,0.273747434685927105],"hpluv":[167.047427400638497,69.2176742514874093,58.4997327930321092],"hsluv":[167.047427400638497,65.0191416919107752,58.4997327930321092]},"#559999":{"lch":[58.9861545428406373,31.2617491707160085,192.177050630060933],"luv":[58.9861545428406373,-30.5583742056962677,-6.59414339527129822],"rgb":[0.333333333333333315,0.6,0.6],"xyz":[0.208861198759212663,0.270127799058704321,0.342514112327045],"hpluv":[192.177050630060933,67.2515837667627494,58.9861545428406373],"hsluv":[192.177050630060933,66.9883413382070216,58.9861545428406373]},"#5599aa":{"lch":[59.5393884281606915,36.5784761777074152,214.841775998693208],"luv":[59.5393884281606915,-30.0211576326403424,-20.8977274812183715],"rgb":[0.333333333333333315,0.6,0.66666666666666663],"xyz":[0.223918891724465219,0.276150876244805388,0.421817961944043585],"hpluv":[214.841775998693208,77.957978019602777,59.5393884281606915],"hsluv":[214.841775998693208,69.0007957908225,59.5393884281606915]},"#5599bb":{"lch":[60.1593377819191488,46.1560476826162613,230.269588518041076],"luv":[60.1593377819191488,-29.5018430010724479,-35.4967885479802],"rgb":[0.333333333333333315,0.6,0.733333333333333282],"xyz":[0.241056483831801838,0.283005913087740146,0.512075947042685331],"hpluv":[230.269588518041076,97.3564866347465312,60.1593377819191488],"hsluv":[230.269588518041076,71.0120526680823758,60.1593377819191488]},"#5599cc":{"lch":[60.8453721774886276,57.9560381686168284,239.960256152221575],"luv":[60.8453721774886276,-29.0128279276179057,-50.1712883614184761],"rgb":[0.333333333333333315,0.6,0.8],"xyz":[0.260348859275523592,0.290722863265228948,0.613682457712955487],"hpluv":[239.960256152221575,120.867757439807349,60.8453721774886276],"hsluv":[239.960256152221575,72.9851794318318667,60.8453721774886276]},"#5599dd":{"lch":[61.596386585270082,70.7674616346471623,246.194917025964173],"luv":[61.596386585270082,-28.563620381934669,-64.7468394355121],"rgb":[0.333333333333333315,0.6,0.866666666666666696],"xyz":[0.281867184826157136,0.29933019348548251,0.727012305612961485],"hpluv":[246.194917025964173,145.7866339341696,61.596386585270082],"hsluv":[246.194917025964173,74.8914393241793164,61.596386585270082]},"#5599ee":{"lch":[62.4108626997728209,83.9573424358243,250.401946751580681],"luv":[62.4108626997728209,-28.1609349474859023,-79.0935970339554757],"rgb":[0.333333333333333315,0.6,0.933333333333333348],"xyz":[0.305679365092331845,0.308855065591952527,0.852423121681484708],"hpluv":[250.401946751580681,170.701691169737018,62.4108626997728209],"hsluv":[250.401946751580681,83.3865807682554845,62.4108626997728209]},"#5599ff":{"lch":[63.2869312953637,97.1853240423286309,253.372761171991215],"luv":[63.2869312953637,-27.8089904224615658,-93.1216798650875859],"rgb":[0.333333333333333315,0.6,1],"xyz":[0.331850413502163266,0.319323484955885251,0.990257309973266553],"hpluv":[253.372761171991215,194.861470594675211,63.2869312953637],"hsluv":[253.372761171991215,99.9999999999986215,63.2869312953637]},"#440000":{"lch":[10.7708306123528814,36.2226426723970221,12.1770506300617765],"luv":[10.7708306123528814,35.407649887332731,7.64056094984030221],"rgb":[0.266666666666666663,0,0],"xyz":[0.0238384275584062923,0.0122916892098035059,0.00111742629180027137],"hpluv":[12.1770506300617765,426.746789183125145,10.7708306123528814],"hsluv":[12.1770506300617765,100.000000000002203,10.7708306123528814]},"#440011":{"lch":[11.0614468716721248,32.5827232355020158,4.73042674181564848],"luv":[11.0614468716721248,32.4717377839629151,2.68702414036008763],"rgb":[0.266666666666666663,0,0.0666666666666666657],"xyz":[0.024850093058043414,0.0126963554096583605,0.00644553125655590239],"hpluv":[4.73042674181564848,373.778888471265759,11.0614468716721248],"hsluv":[4.73042674181564848,99.999999999996831,11.0614468716721248]},"#440022":{"lch":[11.5842423793746683,28.6540476811609395,350.304317532446703],"luv":[11.5842423793746683,28.2447579299318896,-4.82577434136679706],"rgb":[0.266666666666666663,0,0.133333333333333331],"xyz":[0.0267254511965204326,0.0134464986650491784,0.0163224174525351],"hpluv":[350.304317532446703,313.875682434467763,11.5842423793746683],"hsluv":[350.304317532446703,99.9999999999974847,11.5842423793746683]},"#440033":{"lch":[12.4041921203750505,27.3919603751935874,328.642516788172941],"luv":[12.4041921203750505,23.3910134404871357,-14.2541216293086901],"rgb":[0.266666666666666663,0,0.2],"xyz":[0.0298132019289781731,0.0146815989580322912,0.0325845713101462417],"hpluv":[328.642516788172941,280.216663156604227,12.4041921203750505],"hsluv":[328.642516788172941,99.9999999999981668,12.4041921203750505]},"#440044":{"lch":[13.5105146335658439,30.7747615701782742,307.715012949243601],"luv":[13.5105146335658439,18.8259784531467211,-24.3447835271332202],"rgb":[0.266666666666666663,0,0.266666666666666663],"xyz":[0.0342711971731970502,0.0164647970557198695,0.0560633462630328802],"hpluv":[307.715012949243601,289.042783730483222,13.5105146335658439],"hsluv":[307.715012949243601,99.9999999999987779,13.5105146335658439]},"#440055":{"lch":[14.871657786523194,37.5926423334987589,293.358518425732086],"luv":[14.871657786523194,14.9048564440935021,-34.5116214049025416],"rgb":[0.266666666666666663,0,0.333333333333333315],"xyz":[0.0402336112125590423,0.0188497626714647,0.0874653935370067886],"hpluv":[293.358518425732086,320.761913781574776,14.871657786523194],"hsluv":[293.358518425732086,99.999999999999261,14.871657786523194]},"#440066":{"lch":[16.4463097679727497,46.0898544445027,284.618444278650202],"luv":[16.4463097679727497,11.6321972733021664,-44.597832562922008],"rgb":[0.266666666666666663,0,0.4],"xyz":[0.0478186069860672205,0.0218837609808680139,0.127413037944150764],"hpluv":[284.618444278650202,355.611827609674208,16.4463097679727497],"hsluv":[284.618444278650202,99.9999999999996447,16.4463097679727497]},"#440077":{"lch":[18.1919811936642475,55.3198462112611651,279.251207899416613],"luv":[18.1919811936642475,8.8934050845755,-54.6002997321373],"rgb":[0.266666666666666663,0,0.466666666666666674],"xyz":[0.0571326200062691331,0.0256093661889488303,0.176466839850548673],"hpluv":[279.251207899416613,385.869357778503058,18.1919811936642475],"hsluv":[279.251207899416613,100.000000000000028,18.1919811936642475]},"#440088":{"lch":[20.0701231572475791,64.8751824688912,275.807883046004235],"luv":[20.0701231572475791,6.56492582220058196,-64.5421648949036353],"rgb":[0.266666666666666663,0,0.533333333333333326],"xyz":[0.0682730371082129611,0.0300655330297264212,0.235139703254120841],"hpluv":[275.807883046004235,410.173767132845569,20.0701231572475791],"hsluv":[275.807883046004235,100.000000000000284,20.0701231572475791]},"#440099":{"lch":[22.0482755473713041,74.5764302852581267,273.495279820248],"luv":[22.0482755473713041,4.54664979059262,-74.4377050275844283],"rgb":[0.266666666666666663,0,0.6],"xyz":[0.0813300012172856746,0.0352883186733555787,0.303906380895238748],"hpluv":[273.495279820248,429.20649964036636,22.0482755473713041],"hsluv":[273.495279820248,100.000000000000384,22.0482755473713041]},"#4400aa":{"lch":[24.1003299188330615,84.3353594354864811,271.878389761009714],"luv":[24.1003299188330615,2.7643624238057809,-84.290041828810061],"rgb":[0.266666666666666663,0,0.66666666666666663],"xyz":[0.0963876941825382166,0.0413113958594566871,0.383210230512237349],"hpluv":[271.878389761009714,444.044033459252,24.1003299188330615],"hsluv":[271.878389761009714,100.000000000000398,24.1003299188330615]},"#4400bb":{"lch":[26.2058661049044161,94.1030045511215434,270.708980538846049],"luv":[26.2058661049044161,1.16440507249082947,-94.0958002589677704],"rgb":[0.266666666666666663,0,0.733333333333333282],"xyz":[0.113525286289874863,0.0481664327023914457,0.473468215610879095],"hpluv":[270.708980538846049,455.663559843794246,26.2058661049044161],"hsluv":[270.708980538846049,100.000000000000597,26.2058661049044161]},"#4400cc":{"lch":[28.3491756730399374,103.84959146554381,269.838851579513857],"luv":[28.3491756730399374,-0.292083914573144032,-103.849180711969012],"rgb":[0.266666666666666663,0,0.8],"xyz":[0.132817661733596604,0.0558833828798802473,0.575074726281149196],"hpluv":[269.838851579513857,464.840204698682,28.3491756730399374],"hsluv":[269.838851579513857,100.00000000000054,28.3491756730399374]},"#4400dd":{"lch":[30.5182871942398464,113.556060117994207,269.175711116484081],"luv":[30.5182871942398464,-1.63362415099869285,-113.544308803456943],"rgb":[0.266666666666666663,0,0.866666666666666696],"xyz":[0.154335987284230147,0.0644907131001337813,0.688404574181155193],"hpluv":[269.175711116484081,472.160320460814546,30.5182871942398464],"hsluv":[269.175711116484081,100.000000000000583,30.5182871942398464]},"#4400ee":{"lch":[32.7041215904695406,123.209994802530275,268.6598990566049],"luv":[32.7041215904695406,-2.88151723804096926,-123.176295112519156],"rgb":[0.266666666666666663,0,0.933333333333333348],"xyz":[0.178148167550404884,0.0740155852066038122,0.813815390249678416],"hpluv":[268.6598990566049,478.060407115886846,32.7041215904695406],"hsluv":[268.6598990566049,100.000000000000682,32.7041215904695406]},"#4400ff":{"lch":[34.8998090420324161,132.803387625161918,268.251574356178935],"luv":[34.8998090420324161,-4.05197057625710322,-132.741558297197031],"rgb":[0.266666666666666663,0,1],"xyz":[0.204319215960236278,0.0844840045705365084,0.951649578541460262],"hpluv":[268.251574356178935,482.864668803745815,34.8998090420324161],"hsluv":[268.251574356178935,100.000000000000824,34.8998090420324161]},"#441100":{"lch":[13.412021407860891,32.8203905090178907,19.8063713084711637],"luv":[13.412021407860891,30.878837797926078,11.1209446277644677],"rgb":[0.266666666666666663,0.0666666666666666657,0],"xyz":[0.025842827819334703,0.0163004897316603795,0.00178555971210972225],"hpluv":[19.8063713084711637,310.519467471828818,13.412021407860891],"hsluv":[19.8063713084711637,100.00000000000226,13.412021407860891]},"#441111":{"lch":[13.6534230745514442,29.3615880370140658,12.1770506300618155],"luv":[13.6534230745514442,28.7009658227648572,6.19333616848069],"rgb":[0.266666666666666663,0.0666666666666666657,0.0666666666666666657],"xyz":[0.0268544933189718248,0.0167051559315152323,0.00711366467686535414],"hpluv":[12.1770506300618155,272.883526996448495,13.6534230745514442],"hsluv":[12.1770506300618155,63.9450685777404857,13.6534230745514442]},"#441122":{"lch":[14.0908014406849,25.4444274015795777,356.558123350094036],"luv":[14.0908014406849,25.3985311285907684,-1.52758053936917793],"rgb":[0.266666666666666663,0.0666666666666666657,0.133333333333333331],"xyz":[0.0287298514574488434,0.0174552991869060536,0.0169905508728445502],"hpluv":[356.558123350094036,229.137575437366081,14.0908014406849],"hsluv":[356.558123350094036,68.4589860949294,14.0908014406849]},"#441133":{"lch":[14.7844111345271223,24.27011571268606,331.648240125609],"luv":[14.7844111345271223,21.358884082162259,-11.5254755854986932],"rgb":[0.266666666666666663,0.0666666666666666657,0.2],"xyz":[0.0318176021899065839,0.0186903994798891665,0.0332527047304557],"hpluv":[331.648240125609,208.308572243058649,14.7844111345271223],"hsluv":[331.648240125609,73.8494669394836762,14.7844111345271223]},"#441144":{"lch":[15.733846020816415,28.3218749128348932,307.715012949243942],"luv":[15.733846020816415,17.3254634530922189,-22.4043949865608347],"rgb":[0.266666666666666663,0.0666666666666666657,0.266666666666666663],"xyz":[0.0362755974341254644,0.0204735975775767395,0.0567314796833423354],"hpluv":[307.715012949243942,228.415952286272613,15.733846020816415],"hsluv":[307.715012949243942,79.0249627886423127,15.733846020816415]},"#441155":{"lch":[16.9210970319156715,36.0495621705848492,292.339268883647492],"luv":[16.9210970319156715,13.7020846665308547,-33.3440220801582683],"rgb":[0.266666666666666663,0.0666666666666666657,0.333333333333333315],"xyz":[0.0422380114734874565,0.0228585631933215724,0.0881335269573162439],"hpluv":[292.339268883647492,270.340308544513618,16.9210970319156715],"hsluv":[292.339268883647492,83.4150097743113292,16.9210970319156715]},"#441166":{"lch":[18.3175541838796221,45.305096001334384,283.521508601515677],"luv":[18.3175541838796221,10.592801308498224,-44.0493392019540195],"rgb":[0.266666666666666663,0.0666666666666666657,0.4],"xyz":[0.0498230072469956348,0.025892561502724884,0.128081171364460206],"hpluv":[283.521508601515677,313.84766122316239,18.3175541838796221],"hsluv":[283.521508601515677,86.9023417707839485,18.3175541838796221]},"#441177":{"lch":[19.8903241139664431,55.0653797371295326,278.304914930180701],"luv":[19.8903241139664431,7.95370312292975612,-54.4879312529533735],"rgb":[0.266666666666666663,0.0666666666666666657,0.466666666666666674],"xyz":[0.0591370202671975473,0.0296181667108057,0.177134973270858115],"hpluv":[278.304914930180701,351.298345972174616,19.8903241139664431],"hsluv":[278.304914930180701,89.590178354910762,19.8903241139664431]},"#441188":{"lch":[21.6068634066631873,64.9598488176177824,275.03199667533886],"luv":[21.6068634066631873,5.69776159856002,-64.7094851716016422],"rgb":[0.266666666666666663,0.0666666666666666657,0.533333333333333326],"xyz":[0.0702774373691413823,0.0340743335515832912,0.235807836674430282],"hpluv":[275.03199667533886,381.498298720028686,21.6068634066631873],"hsluv":[275.03199667533886,91.6417594317348545,21.6068634066631873]},"#441199":{"lch":[23.437698327746169,74.8628785955689153,272.864058339832695],"luv":[23.437698327746169,3.74063102269824954,-74.769367197849931],"rgb":[0.266666666666666663,0.0666666666666666657,0.6],"xyz":[0.0833344014782140818,0.0392971191952124557,0.304574514315548162],"hpluv":[272.864058339832695,405.313331644098525,23.437698327746169],"hsluv":[272.864058339832695,93.2101268622270283,23.437698327746169]},"#4411aa":{"lch":[25.3575925472355337,84.7316846097945273,271.361966301038933],"luv":[25.3575925472355337,2.01394993465393446,-84.7077468858332878],"rgb":[0.266666666666666663,0.0666666666666666657,0.66666666666666663],"xyz":[0.0983920944434666378,0.0453201963813135572,0.383878363932546762],"hpluv":[271.361966301038933,424.011024215555381,25.3575925472355337],"hsluv":[271.361966301038933,94.4180404350203872,25.3575925472355337]},"#4411bb":{"lch":[27.345710117802,94.5503656807627,270.282295464151048],"luv":[27.345710117802,0.465846378280231621,-94.5492180693092337],"rgb":[0.266666666666666663,0.0666666666666666657,0.733333333333333282],"xyz":[0.115529686550803284,0.0521752332242483158,0.474136349031188509],"hpluv":[270.282295464151048,438.746165283595928,27.345710117802],"hsluv":[270.282295464151048,95.3579307613671,27.345710117802]},"#4411cc":{"lch":[29.3852471201757481,104.311620276565549,269.482476007084244],"luv":[29.3852471201757481,-0.942181651797373232,-104.307365120864873],"rgb":[0.266666666666666663,0.0666666666666666657,0.8],"xyz":[0.134822061994525,0.0598921834017371174,0.575742859701458665],"hpluv":[269.482476007084244,450.445933463405538,29.3852471201757481],"hsluv":[269.482476007084244,96.097629526357963,29.3852471201757481]},"#4411dd":{"lch":[31.4628506304707116,114.011096091836691,268.874895171215144],"luv":[31.4628506304707116,-2.23866735310417164,-113.989115272223103],"rgb":[0.266666666666666663,0.0666666666666666657,0.866666666666666696],"xyz":[0.156340387545158555,0.0684995136219906514,0.689072707601464662],"hpluv":[268.874895171215144,459.820552568088715,31.4628506304707116],"hsluv":[268.874895171215144,96.6865382756064378,31.4628506304707116]},"#4411ee":{"lch":[33.5680052377948073,123.64577428881995,268.40345713539682],"luv":[33.5680052377948073,-3.44493495426529961,-123.597774747940718],"rgb":[0.266666666666666663,0.0666666666666666657,0.933333333333333348],"xyz":[0.180152567811333292,0.0780243857284606823,0.814483523669987886],"hpluv":[268.40345713539682,467.404695294247745,33.5680052377948073],"hsluv":[268.40345713539682,97.1606953094382817,33.5680052377948073]},"#4411ff":{"lch":[35.6924730299026081,133.21354134861582,268.030966648817412],"luv":[35.6924730299026081,-4.57713081064657,-133.134884505082312],"rgb":[0.266666666666666663,0.0666666666666666657,1],"xyz":[0.206323616221164685,0.0884928050923933784,0.952317711961769731],"hpluv":[268.030966648817412,473.599309181226886,35.6924730299026081],"hsluv":[268.030966648817412,99.999999999999531,35.6924730299026081]},"#99aa00":{"lch":[66.1528677227115907,74.3468963767982842,94.6234982733471384],"luv":[66.1528677227115907,-5.99293371363564553,74.1049643840839565],"rgb":[0.6,0.66666666666666663,0],"xyz":[0.275106719282890377,0.355217387920677,0.0540714229698005533],"hpluv":[94.6234982733471384,142.611154102436132,66.1528677227115907],"hsluv":[94.6234982733471384,100.000000000002217,66.1528677227115907]},"#99aa11":{"lch":[66.184052262829,73.0311244080130706,94.7508326892346275],"luv":[66.184052262829,-6.04863423256243316,72.7802112955118901],"rgb":[0.6,0.66666666666666663,0.0666666666666666657],"xyz":[0.276118384782527482,0.355622054120531828,0.059399527934556183],"hpluv":[94.7508326892346275,140.021252931940353,66.184052262829],"hsluv":[94.7508326892346275,98.1390759685954,66.184052262829]},"#99aa22":{"lch":[66.2417975711995695,70.6178785015108872,94.9968669170454376],"luv":[66.2417975711995695,-6.15090676716144458,70.3494926065273],"rgb":[0.6,0.66666666666666663,0.133333333333333331],"xyz":[0.277993742921004539,0.356372197375922628,0.0692764141305353826],"hpluv":[94.9968669170454376,135.276352185575888,66.2417975711995695],"hsluv":[94.9968669170454376,94.7283581868373403,66.2417975711995695]},"#99aa33":{"lch":[66.3366981156763273,66.7162457715457,95.432805623918],"luv":[66.3366981156763273,-6.31658226271684953,66.416550937003791],"rgb":[0.6,0.66666666666666663,0.2],"xyz":[0.281081493653462244,0.357607297668905755,0.0855385679881465189],"hpluv":[95.432805623918,127.619510800204154,66.3366981156763273],"hsluv":[95.432805623918,89.220332613511431,66.3366981156763273]},"#99aa44":{"lch":[66.4733277612737652,61.2361369282317085,96.1403021162386],"luv":[66.4733277612737652,-6.55002950525979344,60.8848222414533211],"rgb":[0.6,0.66666666666666663,0.266666666666666663],"xyz":[0.28553948889768116,0.359390495766593321,0.109017342941033157],"hpluv":[96.1403021162386,116.896010950353556,66.4733277612737652],"hsluv":[96.1403021162386,81.495914591183535,66.4733277612737652]},"#99aa55":{"lch":[66.6553605356915853,54.1785870660784568,97.2658616968833769],"luv":[66.6553605356915853,-6.85216039608048888,53.7435316515674231],"rgb":[0.6,0.66666666666666663,0.333333333333333315],"xyz":[0.291501902937043145,0.361775461382338182,0.140419390215007073],"hpluv":[97.2658616968833769,103.141138146130345,66.6553605356915853],"hsluv":[97.2658616968833769,71.5645731506566563,66.6553605356915853]},"#99aa66":{"lch":[66.8857782590742573,45.6318272725976186,99.1048787772859328],"luv":[66.8857782590742573,-7.22087825912546055,45.0568815765480224],"rgb":[0.6,0.66666666666666663,0.4],"xyz":[0.29908689871055133,0.3648094596917415,0.180367034622151035],"hpluv":[99.1048787772859328,86.5711928674077882,66.8857782590742573],"hsluv":[99.1048787772859328,59.5487850828384495,66.8857782590742573]},"#99aa77":{"lch":[67.16697930835997,35.7793898766585272,102.348317274789],"luv":[67.16697930835997,-7.65157453727816339,34.9516544250255947],"rgb":[0.6,0.66666666666666663,0.466666666666666674],"xyz":[0.308400911730753235,0.368535064899822296,0.229420836528548944],"hpluv":[102.348317274789,67.5952906506277742,67.16697930835997],"hsluv":[102.348317274789,45.6652750399669927,67.16697930835997]},"#99aa88":{"lch":[67.5008436530857523,24.9656779050761699,109.02352802026725],"luv":[67.5008436530857523,-8.13772239581267165,23.6021725158659379],"rgb":[0.6,0.66666666666666663,0.533333333333333326],"xyz":[0.319541328832697036,0.372991231740599893,0.288093699932121083],"hpluv":[109.02352802026725,46.9324783865521482,67.5008436530857523],"hsluv":[109.02352802026725,30.201776912068496,67.5008436530857523]},"#99aa99":{"lch":[67.8887769686822509,14.1753245834603039,127.715012949228395],"luv":[67.8887769686822509,-8.67153282620695443,11.213578621049983],"rgb":[0.6,0.66666666666666663,0.6],"xyz":[0.332598292941769791,0.378214017384229051,0.356860377573239],"hpluv":[127.715012949228395,26.4956363039349618,67.8887769686822509],"hsluv":[127.715012949228395,13.4910013502760879,67.8887769686822509]},"#99aaaa":{"lch":[68.3317447891119798,9.45739632834534838,192.177050630059227],"luv":[68.3317447891119798,-9.24460926466251642,-1.99487965930680966],"rgb":[0.6,0.66666666666666663,0.66666666666666663],"xyz":[0.347655985907022291,0.384237094570330173,0.436164227190237619],"hpluv":[192.177050630059227,17.5625836428344968,68.3317447891119798],"hsluv":[192.177050630059227,17.4938385380963979,68.3317447891119798]},"#99aabb":{"lch":[68.8303024285350205,18.6222464744475609,238.07162859052869],"luv":[68.8303024285350205,-9.84853629911531137,-15.8048852105949411],"rgb":[0.6,0.66666666666666663,0.733333333333333282],"xyz":[0.364793578014358966,0.391092131413264932,0.52642221228887931],"hpluv":[238.07162859052869,34.3314162301526622,68.8303024285350205],"hsluv":[238.07162859052869,21.6214176811966929,68.8303024285350205]},"#99aacc":{"lch":[69.3846237501618646,31.7868422871013969,250.758533684062627],"luv":[69.3846237501618646,-10.475354770609286,-30.0111693376804425],"rgb":[0.6,0.66666666666666663,0.8],"xyz":[0.38408595345808072,0.398809081590753733,0.628028722959149466],"hpluv":[250.758533684062627,58.1330991079694357,69.3846237501618646],"hsluv":[250.758533684062627,38.7837447081888556,69.3846237501618646]},"#99aadd":{"lch":[69.9945303682966,45.800012761152324,255.951164454091042],"luv":[69.9945303682966,-11.1178995355210173,-44.4300965432191859],"rgb":[0.6,0.66666666666666663,0.866666666666666696],"xyz":[0.405604279008714208,0.40741641181100724,0.741358570859155463],"hpluv":[255.951164454091042,83.0311057452140346,69.9945303682966],"hsluv":[255.951164454091042,58.1375555879370935,69.9945303682966]},"#99aaee":{"lch":[70.6595219654936,60.0690973767372896,258.700300270425373],"luv":[70.6595219654936,-11.7699993169592201,-58.9046990972259],"rgb":[0.6,0.66666666666666663,0.933333333333333348],"xyz":[0.429416459274889,0.416941283917477257,0.866769386927678687],"hpluv":[258.700300270425373,107.874733956899746,70.6595219654936],"hsluv":[258.700300270425373,78.5353046306170199,70.6595219654936]},"#99aaff":{"lch":[71.378807837336737,74.3523754541628676,260.378973553217],"luv":[71.378807837336737,-12.4265554124673407,-73.3065921746310636],"rgb":[0.6,0.66666666666666663,1],"xyz":[0.455587507684720339,0.42740970328141,1.00460357521946064],"hpluv":[260.378973553217,132.179737350703419,71.378807837336737],"hsluv":[260.378973553217,99.99999999999784,71.378807837336737]},"#442200":{"lch":[17.3350542344952459,28.221345162136295,35.6239292836567927],"luv":[17.3350542344952459,22.9399340369809366,16.4378754448194186],"rgb":[0.266666666666666663,0.133333333333333331,0],"xyz":[0.0295584515541026382,0.023731737201196354,0.00302410095703233277],"hpluv":[35.6239292836567927,206.581692971425213,17.3350542344952459],"hsluv":[35.6239292836567927,100.000000000002331,17.3350542344952459]},"#442211":{"lch":[17.5234603686317101,24.6335663377647,28.604455948929278],"luv":[17.5234603686317101,21.6269347365689519,11.7935696215031331],"rgb":[0.266666666666666663,0.133333333333333331,0.0666666666666666657],"xyz":[0.03057011705373976,0.0241364034010512069,0.00835220592178796337],"hpluv":[28.604455948929278,178.380241443971528,17.5234603686317101],"hsluv":[28.604455948929278,74.2089163354216765,17.5234603686317101]},"#442222":{"lch":[17.8672188947691239,19.9697171584766728,12.1770506300619807],"luv":[17.8672188947691239,19.520407715454283,4.21227800744330061],"rgb":[0.266666666666666663,0.133333333333333331,0.133333333333333331],"xyz":[0.0324454751922167786,0.0248865466564420282,0.0182290921177671594],"hpluv":[12.1770506300619807,141.825486578211439,17.8672188947691239],"hsluv":[12.1770506300619807,33.2341074785113406,17.8672188947691239]},"#442233":{"lch":[18.4184657925371695,17.8165085202964129,340.00784749027008],"luv":[18.4184657925371695,16.7428760354525643,-6.09131167444770583],"rgb":[0.266666666666666663,0.133333333333333331,0.2],"xyz":[0.0355332259246745191,0.026121646949425141,0.0344912459753783],"hpluv":[340.00784749027008,122.746318288975218,18.4184657925371695],"hsluv":[340.00784749027008,42.0888291674463915,18.4184657925371695]},"#442244":{"lch":[19.1844846541763658,22.4593922221866436,307.715012949244738],"luv":[19.1844846541763658,13.7391814744519145,-17.7668002578431441],"rgb":[0.266666666666666663,0.133333333333333331,0.266666666666666663],"xyz":[0.0399912211688934,0.0279048450471127141,0.0579700209282649412],"hpluv":[307.715012949244738,148.554970924606664,19.1844846541763658],"hsluv":[307.715012949244738,51.3954955066877517,19.1844846541763658]},"#442255":{"lch":[20.1595909359386596,31.6741463862469885,290.023039430837684],"luv":[20.1595909359386596,10.8451637140407797,-29.7596030436068872],"rgb":[0.266666666666666663,0.133333333333333331,0.333333333333333315],"xyz":[0.0459536352082553917,0.030289810662857547,0.0893720682022388496],"hpluv":[290.023039430837684,199.371249454156271,20.1595909359386596],"hsluv":[290.023039430837684,59.9942694866150177,20.1595909359386596]},"#442266":{"lch":[21.3287002071660226,42.3208084503031685,281.207510247893651],"luv":[21.3287002071660226,8.22559640374024781,-41.5137373852322256],"rgb":[0.266666666666666663,0.133333333333333331,0.4],"xyz":[0.0535386309817635631,0.0333238089722608585,0.129319712609382825],"hpluv":[281.207510247893651,251.784442505332123,21.3287002071660226],"hsluv":[281.207510247893651,67.3437899952651406,21.3287002071660226]},"#442277":{"lch":[22.6709734328231463,53.1747129073287113,276.391210783405313],"luv":[22.6709734328231463,5.91922219198187882,-52.8442324328661215],"rgb":[0.266666666666666663,0.133333333333333331,0.466666666666666674],"xyz":[0.0628526440019654825,0.0370494141803416749,0.178373514515780734],"hpluv":[276.391210783405313,297.628360698128461,22.6709734328231463],"hsluv":[276.391210783405313,73.3546851738733,22.6709734328231463]},"#442288":{"lch":[24.1630625686767715,63.8732961962266543,273.501787345358252],"luv":[24.1630625686767715,3.90136026108148481,-63.7540379512086801],"rgb":[0.266666666666666663,0.133333333333333331,0.533333333333333326],"xyz":[0.0739930611039093106,0.0415055810211192727,0.237046377919352902],"hpluv":[273.501787345358252,335.433687598002,24.1630625686767715],"hsluv":[273.501787345358252,78.1624380374364875,24.1630625686767715]},"#442299":{"lch":[25.7815797239733442,74.3421908873045112,271.638748742297366],"luv":[25.7815797239733442,2.1260128283266071,-74.3117851715204836],"rgb":[0.266666666666666663,0.133333333333333331,0.6],"xyz":[0.087050025212982024,0.0467283666647484303,0.305813055560470781],"hpluv":[271.638748742297366,365.902315457699217,25.7815797239733442],"hsluv":[271.638748742297366,81.974423252689391,25.7815797239733442]},"#4422aa":{"lch":[27.5046927955253,84.5952413694672885,270.370058715866037],"luv":[27.5046927955253,0.546375125789773097,-84.5934769150692176],"rgb":[0.266666666666666663,0.133333333333333331,0.66666666666666663],"xyz":[0.102107718178234566,0.0527514438508495317,0.385116905177469382],"hpluv":[270.370058715866037,390.281946032504152,27.5046927955253],"hsluv":[270.370058715866037,84.9950544768410765,27.5046927955253]},"#4422bb":{"lch":[29.3129652277151251,94.666070770970677,269.4687873747244],"luv":[29.3129652277151251,-0.87767531850734,-94.6620020982533],"rgb":[0.266666666666666663,0.133333333333333331,0.733333333333333282],"xyz":[0.119245310285571213,0.0596064806937842903,0.475374890276111128],"hpluv":[269.4687873747244,409.801860030343846,29.3129652277151251],"hsluv":[269.4687873747244,87.3984435941311517,29.3129652277151251]},"#4422cc":{"lch":[31.1896477872922873,104.586362634530047,268.806646243455475],"luv":[31.1896477872922873,-2.17816227055809408,-104.563678484665701],"rgb":[0.266666666666666663,0.133333333333333331,0.8],"xyz":[0.138537685729292953,0.0673234308712731,0.576981400946381284],"hpluv":[268.806646243455475,425.504262664631483,31.1896477872922873],"hsluv":[268.806646243455475,89.3235413687926325,31.1896477872922873]},"#4422dd":{"lch":[33.1206275871571,114.38069493574325,268.306702684458742],"luv":[33.1206275871571,-3.37987077956927,-114.330747603157818],"rgb":[0.266666666666666663,0.133333333333333331,0.866666666666666696],"xyz":[0.160056011279926497,0.0759307610915266329,0.690311248846387282],"hpluv":[268.306702684458742,438.22131720165,33.1206275871571],"hsluv":[268.306702684458742,90.877884626449017,33.1206275871571]},"#4422ee":{"lch":[35.0941942457284952,124.066768949832422,267.920557621455941],"luv":[35.0941942457284952,-4.50178121539094178,-123.985068147498538],"rgb":[0.266666666666666663,0.133333333333333331,0.933333333333333348],"xyz":[0.183868191546101234,0.0854556331979966499,0.815722064914910505],"hpluv":[267.920557621455941,448.600262181889605,35.0941942457284952],"hsluv":[267.920557621455941,93.3452679661598523,35.0941942457284952]},"#4422ff":{"lch":[37.1007304630435,133.656986375695226,267.616535799179189],"luv":[37.1007304630435,-5.55843332369103926,-133.54135623850334],"rgb":[0.266666666666666663,0.133333333333333331,1],"xyz":[0.210039239955932627,0.0959240525619293599,0.95355625320669235],"hpluv":[267.616535799179189,457.139270395610822,37.1007304630435],"hsluv":[267.616535799179189,99.999999999999531,37.1007304630435]},"#bbaa00":{"lch":[68.9787767407419,76.4078567958722346,76.7962953219783344],"luv":[68.9787767407419,17.4526104568015299,74.3879490803561652],"rgb":[0.733333333333333282,0.66666666666666663,0],"xyz":[0.348671553863065253,0.393149255751080451,0.0575197745907461769],"hpluv":[76.7962953219783344,140.560034871296551,68.9787767407419],"hsluv":[76.7962953219783344,100.000000000002245,68.9787767407419]},"#bbaa11":{"lch":[69.0079227935645747,75.1793224892161902,76.6760735029220797],"luv":[69.0079227935645747,17.325534429098667,73.1556996185784811],"rgb":[0.733333333333333282,0.66666666666666663,0.0666666666666666657],"xyz":[0.349683219362702358,0.393553921950935304,0.0628478795555018],"hpluv":[76.6760735029220797,138.241608756115426,69.0079227935645747],"hsluv":[76.6760735029220797,98.327691673723,69.0079227935645747]},"#bbaa22":{"lch":[69.0618990033698168,72.923722885125926,76.4446579961253718],"luv":[69.0618990033698168,17.0921879270318975,70.8923583420220496],"rgb":[0.733333333333333282,0.66666666666666663,0.133333333333333331],"xyz":[0.351558577501179415,0.394304065206326104,0.072724765751481],"hpluv":[76.4446579961253718,133.98915323660276,69.0618990033698168],"hsluv":[76.4446579961253718,95.2591470849694701,69.0618990033698168]},"#bbaa33":{"lch":[69.1506211183474448,69.2704933393546298,76.037430434814425],"luv":[69.1506211183474448,16.7141363744442764,67.2237970716773248],"rgb":[0.733333333333333282,0.66666666666666663,0.2],"xyz":[0.35464632823363712,0.395539165499309231,0.0889869196090921494],"hpluv":[76.037430434814425,127.113454601419591,69.1506211183474448],"hsluv":[76.037430434814425,90.2940538071316752,69.1506211183474448]},"#bbaa44":{"lch":[69.2783900215706439,64.125663575375043,75.3840533289293688],"luv":[69.2783900215706439,16.1813855024742246,62.0504914743025964],"rgb":[0.733333333333333282,0.66666666666666663,0.266666666666666663],"xyz":[0.359104323477856036,0.397322363596996797,0.112465694561978788],"hpluv":[75.3840533289293688,117.455514697890109,69.2783900215706439],"hsluv":[75.3840533289293688,83.3108908827552455,69.2783900215706439]},"#bbaa55":{"lch":[69.4486803199850158,57.4759826537307603,74.3632861967268752],"luv":[69.4486803199850158,15.4919003466967737,55.3487994961044762],"rgb":[0.733333333333333282,0.66666666666666663,0.333333333333333315],"xyz":[0.365066737517218,0.399707329212741658,0.143867741835952689],"hpluv":[74.3632861967268752,105.017514149864908,69.4486803199850158],"hsluv":[74.3632861967268752,74.2978448337225501,69.4486803199850158]},"#bbaa66":{"lch":[69.6643364030220766,49.3851711615203186,72.7428070953876],"luv":[69.6643364030220766,14.6506772614363818,47.1619845472377079],"rgb":[0.733333333333333282,0.66666666666666663,0.4],"xyz":[0.372651733290726206,0.402741327522145,0.183815386243096651],"hpluv":[72.7428070953876,89.9550160304510342,69.6643364030220766],"hsluv":[72.7428070953876,63.3404983901227254,69.6643364030220766]},"#bbaa77":{"lch":[69.927675331165787,39.998456174204172,70.017617272721],"luv":[69.927675331165787,13.6687200676018641,37.5904587366697314],"rgb":[0.733333333333333282,0.66666666666666663,0.466666666666666674],"xyz":[0.381965746310928111,0.406466932730225772,0.23286918814949456],"hpluv":[70.017617272721,72.5827577171275635,69.927675331165787],"hsluv":[70.017617272721,50.6076787731359303,69.927675331165787]},"#bbaa88":{"lch":[70.2405480333122,29.5797452752191568,64.8698942165899837],"luv":[70.2405480333122,12.5617839686329518,26.7798975739685403],"rgb":[0.733333333333333282,0.66666666666666663,0.533333333333333326],"xyz":[0.393106163412871912,0.41092309957100337,0.291542051553066728],"hpluv":[64.8698942165899837,53.4374671266607422,70.2405480333122],"hsluv":[64.8698942165899837,36.3337734813298923,70.2405480333122]},"#bbaa99":{"lch":[70.6043801086793,18.7359983934483161,52.7186742094296079],"luv":[70.6043801086793,11.3489394865138475,14.907689570511744],"rgb":[0.733333333333333282,0.66666666666666663,0.6],"xyz":[0.406163127521944611,0.416145885214632527,0.360308729194184663],"hpluv":[52.7186742094296079,33.6732102985619051,70.6043801086793],"hsluv":[52.7186742094296079,20.7983697782308,70.6043801086793]},"#bbaaaa":{"lch":[71.0202025015365876,10.2824341490213804,12.177050630064155],"luv":[71.0202025015365876,10.0510841141786607,2.16890759569567715],"rgb":[0.733333333333333282,0.66666666666666663,0.66666666666666663],"xyz":[0.421220820487197167,0.422168962400733649,0.439612578811183263],"hpluv":[12.177050630064155,18.3718697222702261,71.0202025015365876],"hsluv":[12.177050630064155,12.5020210815887047,71.0202025015365876]},"#bbaabb":{"lch":[71.4886774714552615,14.2047670368859897,307.715012949256788],"luv":[71.4886774714552615,8.68954378602241562,-11.236869464535129],"rgb":[0.733333333333333282,0.66666666666666663,0.733333333333333282],"xyz":[0.438358412594533842,0.429023999243668408,0.529870563909825],"hpluv":[307.715012949256788,25.2136766683934965,71.4886774714552615],"hsluv":[307.715012949256788,14.1682246563909,71.4886774714552615]},"#bbaacc":{"lch":[72.010122844957138,26.1519063744379174,286.174295641089373],"luv":[72.010122844957138,7.28488198445553525,-25.1167812724863673],"rgb":[0.733333333333333282,0.66666666666666663,0.8],"xyz":[0.45765078803825554,0.43674094942115721,0.631477074580095166],"hpluv":[286.174295641089373,46.0838895939184923,72.010122844957138],"hsluv":[286.174295641089373,33.6938059680335442,72.010122844957138]},"#bbaadd":{"lch":[72.5845361735228494,39.7272427931479,278.476565574149959],"luv":[72.5845361735228494,5.85598959517198825,-39.2932717625671799],"rgb":[0.733333333333333282,0.66666666666666663,0.866666666666666696],"xyz":[0.47916911358888914,0.445348279641410716,0.744806922480101163],"hpluv":[278.476565574149959,69.451822258827633,72.5845361735228494],"hsluv":[278.476565574149959,54.5084651382981775,72.5845361735228494]},"#bbaaee":{"lch":[73.2116196006959825,53.7916684525604,274.71268656160521],"luv":[73.2116196006959825,4.41947960396952144,-53.6098106221266093],"rgb":[0.733333333333333282,0.66666666666666663,0.933333333333333348],"xyz":[0.502981293855063849,0.454873151747880733,0.870217738548624387],"hpluv":[274.71268656160521,93.2340021292866084,73.2116196006959825],"hsluv":[274.71268656160521,76.5987468488048506,73.2116196006959825]},"#bbaaff":{"lch":[73.8908057188696574,67.9996555049746121,272.519622378571285],"luv":[73.8908057188696574,2.98936916429642707,-67.9339150998584671],"rgb":[0.733333333333333282,0.66666666666666663,1],"xyz":[0.52915234226489527,0.465341571111813457,1.00805192684040623],"hpluv":[272.519622378571285,116.776549017196231,73.8908057188696574],"hsluv":[272.519622378571285,99.9999999999974847,73.8908057188696574]},"#99bb00":{"lch":[71.0859361318702696,82.3913749493211327,101.26222245755217],"luv":[71.0859361318702696,-16.0909976916487061,80.8048170552163185],"rgb":[0.6,0.733333333333333282,0],"xyz":[0.309061217191489157,0.423126383737875533,0.0653895889393331653],"hpluv":[101.26222245755217,147.074503152999483,71.0859361318702696],"hsluv":[101.26222245755217,100.000000000002302,71.0859361318702696]},"#99bb11":{"lch":[71.1136894680978457,81.2167121813616291,101.442926834262664],"luv":[71.1136894680978457,-16.1127230849120338,79.6023523040561685],"rgb":[0.6,0.733333333333333282,0.0666666666666666657],"xyz":[0.310072882691126261,0.423531049937730386,0.0707176939040888],"hpluv":[101.442926834262664,144.921066000062638,71.1136894680978457],"hsluv":[101.442926834262664,98.4331733262411,71.1136894680978457]},"#99bb22":{"lch":[71.1650900316793837,79.0601549481488917,101.789083890819583],"luv":[71.1650900316793837,-16.1527448632600859,77.392486287802754],"rgb":[0.6,0.733333333333333282,0.133333333333333331],"xyz":[0.311948240829603318,0.424281193193121187,0.080594580100068],"hpluv":[101.789083890819583,140.971066242853169,71.1650900316793837],"hsluv":[101.789083890819583,95.5563304227746357,71.1650900316793837]},"#99bb33":{"lch":[71.2495884989653,75.5680342451554168,102.392870056849247],"luv":[71.2495884989653,-16.2179420391938294,73.807222923575253],"rgb":[0.6,0.733333333333333282,0.2],"xyz":[0.315035991562061,0.425516293486104313,0.0968567339576791309],"hpluv":[102.392870056849247,134.584514176993849,71.2495884989653],"hsluv":[102.392870056849247,90.8963478676004826,71.2495884989653]},"#99bb44":{"lch":[71.3712967033779648,70.652786516275043,103.347443045401377],"luv":[71.3712967033779648,-16.3105834167977157,68.7443169368786471],"rgb":[0.6,0.733333333333333282,0.266666666666666663],"xyz":[0.319493986806279939,0.427299491583791879,0.120335508910565769],"hpluv":[103.347443045401377,125.616021445862458,71.3712967033779648],"hsluv":[103.347443045401377,84.331672265085615,71.3712967033779648]},"#99bb55":{"lch":[71.5335490617920442,64.3081830776187502,104.804237401434776],"luv":[71.5335490617920442,-16.4318507493525949,62.1734404042074189],"rgb":[0.6,0.733333333333333282,0.333333333333333315],"xyz":[0.325456400845641924,0.42968445719953674,0.151737556184539685],"hpluv":[104.804237401434776,114.076396323867073,71.5335490617920442],"hsluv":[104.804237401434776,75.8403293762878263,71.5335490617920442]},"#99bb66":{"lch":[71.7390905918245494,56.6109161874071347,107.032342660002968],"luv":[71.7390905918245494,-16.5819871692753225,54.1279367156704367],"rgb":[0.6,0.733333333333333282,0.4],"xyz":[0.33304139661915011,0.432718455508940059,0.191685200591683647],"hpluv":[107.032342660002968,100.134479122606095,71.7390905918245494],"hsluv":[107.032342660002968,65.4891515707011,71.7390905918245494]},"#99bb77":{"lch":[71.9901757540345102,47.73532562127712,110.555323727161408],"luv":[71.9901757540345102,-16.7604289857032249,44.6961892378372099],"rgb":[0.6,0.733333333333333282,0.466666666666666674],"xyz":[0.342355409639352,0.436444060717020854,0.240739002498081556],"hpluv":[110.555323727161408,84.1406731320706,71.9901757540345102],"hsluv":[110.555323727161408,53.4218452589237,71.9901757540345102]},"#99bb88":{"lch":[72.2886271035685581,38.007890289968195,116.511646356383693],"luv":[72.2886271035685581,-16.9659512259030869,34.0111191126451473],"rgb":[0.6,0.733333333333333282,0.533333333333333326],"xyz":[0.353495826741295815,0.440900227557798452,0.299411865901653695],"hpluv":[116.511646356383693,66.7180145269523592,72.2886271035685581],"hsluv":[116.511646356383693,39.8440619041218724,72.2886271035685581]},"#99bb99":{"lch":[72.6358740128595315,28.1115962970155238,127.715012949234961],"luv":[72.6358740128595315,-17.1968288028560856,22.2380512970816788],"rgb":[0.6,0.733333333333333282,0.6],"xyz":[0.366552790850368515,0.44612301320142761,0.36817854354277163],"hpluv":[127.715012949234961,49.1104221429672094,72.6358740128595315],"hsluv":[127.715012949234961,25.0059581073328268,72.6358740128595315]},"#99bbaa":{"lch":[73.0329812495468929,19.8989345424194468,151.280397210880039],"luv":[73.0329812495468929,-17.4510036711552878,9.56190706882358654],"rgb":[0.6,0.733333333333333282,0.66666666666666663],"xyz":[0.381610483815621071,0.452146090387528732,0.447482393159770231],"hpluv":[151.280397210880039,34.5740392557976648,73.0329812495468929],"hsluv":[151.280397210880039,28.0327457551748473,73.0329812495468929]},"#99bbbb":{"lch":[73.4806726048520602,18.1342571597367979,192.177050630060279],"luv":[73.4806726048520602,-17.7262447217336288,-3.82511840348453136],"rgb":[0.6,0.733333333333333282,0.733333333333333282],"xyz":[0.398748075922957745,0.45900112723046349,0.537740378258412],"hpluv":[192.177050630060279,31.3159775944509384,73.4806726048520602],"hsluv":[192.177050630060279,31.1933976709334857,73.4806726048520602]},"#99bbcc":{"lch":[73.9793524714423,25.2831678504957686,224.541830016242],"luv":[73.9793524714423,-18.0202882726228886,-17.734367401402082],"rgb":[0.6,0.733333333333333282,0.8],"xyz":[0.418040451366679444,0.466718077407952292,0.639346888928682189],"hpluv":[224.541830016242,43.3670907410057183,73.9793524714423],"hsluv":[224.541830016242,34.4349286550277398,73.9793524714423]},"#99bbdd":{"lch":[74.5291269946933284,36.8692317824205347,240.185846709470951],"luv":[74.5291269946933284,-18.3309507682094441,-31.9893184697537762],"rgb":[0.6,0.733333333333333282,0.866666666666666696],"xyz":[0.439558776917313043,0.475325407628205798,0.752676736828688187],"hpluv":[240.185846709470951,62.7736499155611796,74.5291269946933284],"hsluv":[240.185846709470951,50.9371920612126914,74.5291269946933284]},"#99bbee":{"lch":[75.129825653719962,50.0395173115419851,248.109771752659725],"luv":[75.129825653719962,-18.6562099892881648,-46.4316607672792],"rgb":[0.6,0.733333333333333282,0.933333333333333348],"xyz":[0.463370957183487753,0.484850279734675815,0.87808755289721141],"hpluv":[248.109771752659725,84.5162185097210568,75.129825653719962],"hsluv":[248.109771752659725,74.708817528734329,75.129825653719962]},"#99bbff":{"lch":[75.7810236401202104,63.8171103470632701,252.684342225014],"luv":[75.7810236401202104,-18.9942553989637197,-60.9248868270445527],"rgb":[0.6,0.733333333333333282,1],"xyz":[0.489542005593319174,0.495318699098608539,1.01592174118899314],"hpluv":[252.684342225014,106.860202909060845,75.7810236401202104],"hsluv":[252.684342225014,99.9999999999971,75.7810236401202104]},"#443300":{"lch":[22.2907133772276609,26.4379209369795269,61.2454831359909],"luv":[22.2907133772276609,12.7181702882918319,23.1778300966244757],"rgb":[0.266666666666666663,0.2,0],"xyz":[0.0356761736431134499,0.0359671813792181508,0.00506334165336921362],"hpluv":[61.2454831359909,150.502134175174433,22.2907133772276609],"hsluv":[61.2454831359909,100.000000000002217,22.2907133772276609]},"#443311":{"lch":[22.433780901835803,22.5495741902090607,57.6291729330006959],"luv":[22.433780901835803,12.072970412625418,19.0453847841311372],"rgb":[0.266666666666666663,0.2,0.0666666666666666657],"xyz":[0.0366878391427505751,0.0363718475790730036,0.0103914466181248451],"hpluv":[57.6291729330006959,127.548453681164943,22.433780901835803],"hsluv":[57.6291729330006959,82.4396262904162853,22.433780901835803]},"#443322":{"lch":[22.6962080128251955,16.3034653251506185,47.6268315603120129],"luv":[22.6962080128251955,10.9878263584328284,12.044527949459761],"rgb":[0.266666666666666663,0.2,0.133333333333333331],"xyz":[0.0385631972812275903,0.037121990834463825,0.0202683328141040411],"hpluv":[47.6268315603120129,91.1519465603444,22.6962080128251955],"hsluv":[47.6268315603120129,53.1527363908354289,22.6962080128251955]},"#443333":{"lch":[23.1206934094119845,9.67437860897999613,12.1770506300626202],"luv":[23.1206934094119845,9.4567095438703852,2.04064844418642899],"rgb":[0.266666666666666663,0.2,0.2],"xyz":[0.0416509480136853308,0.0383570911274469378,0.0365304866717151844],"hpluv":[12.1770506300626202,53.0959690287213917,23.1206934094119845],"hsluv":[12.1770506300626202,12.4420312875371923,23.1206934094119845]},"#443344":{"lch":[23.7177668131648574,12.5269391023357528,307.715012949247694],"luv":[23.7177668131648574,7.66315882209806354,-9.90960141180911],"rgb":[0.266666666666666663,0.2,0.266666666666666663],"xyz":[0.0461089432579042113,0.0401402892251345109,0.0600092616246018229],"hpluv":[307.715012949247694,67.0209373905010608,23.7177668131648574],"hsluv":[307.715012949247694,23.1872031280306743,23.7177668131648574]},"#443355":{"lch":[24.4893027034144382,23.4497607107203301,284.299245815683662],"luv":[24.4893027034144382,5.79176863833153277,-22.7232632654309157],"rgb":[0.266666666666666663,0.2,0.333333333333333315],"xyz":[0.0520713572972662,0.0425252548408793438,0.0914113088985757383],"hpluv":[284.299245815683662,121.507006770462795,24.4893027034144382],"hsluv":[284.299245815683662,34.0172562824217479,24.4893027034144382]},"#443366":{"lch":[25.4301832846655458,35.8361728283181407,276.366541048647719],"luv":[25.4301832846655458,3.97382245046802396,-35.6151655634680964],"rgb":[0.266666666666666663,0.2,0.4],"xyz":[0.0596563530707743817,0.0455592531502826553,0.1313589533057197],"hpluv":[276.366541048647719,178.818092823782393,25.4301832846655458],"hsluv":[276.366541048647719,44.0521665839457555,25.4301832846655458]},"#443377":{"lch":[26.5300434901181958,48.2102429207408818,272.708376965990851],"luv":[26.5300434901181958,2.27805419202829862,-48.1563909733176416],"rgb":[0.266666666666666663,0.2,0.466666666666666674],"xyz":[0.0689703660909762872,0.0492848583583634717,0.180412755212117609],"hpluv":[272.708376965990851,230.590114205629249,26.5300434901181958],"hsluv":[272.708376965990851,52.8563285469964583,26.5300434901181958]},"#443388":{"lch":[27.7750487339787355,60.1896827108213373,270.691543734184165],"luv":[27.7750487339787355,0.726454682878815761,-60.1852986070773568],"rgb":[0.266666666666666663,0.2,0.533333333333333326],"xyz":[0.0801107831929201153,0.0537410251991410626,0.239085618615689777],"hpluv":[270.691543734184165,274.983446475144433,27.7750487339787355],"hsluv":[270.691543734184165,60.324174233719404,27.7750487339787355]},"#443399":{"lch":[29.1495234429961272,71.6961686956082218,269.452076389218803],"luv":[29.1495234429961272,-0.685625105343165342,-71.6928903298230438],"rgb":[0.266666666666666663,0.2,0.6],"xyz":[0.0931677473019928426,0.058963810842770227,0.307852296256807656],"hpluv":[269.452076389218803,312.107220431461315,29.1495234429961272],"hsluv":[269.452076389218803,66.5368599437509,29.1495234429961272]},"#4433aa":{"lch":[30.6372824460415245,82.7612763398458924,268.632918119842316],"luv":[30.6372824460415245,-1.97450330946598829,-82.7377193188284821],"rgb":[0.266666666666666663,0.2,0.66666666666666663],"xyz":[0.108225440267245371,0.0649868880288713285,0.387156145873806257],"hpluv":[268.632918119842316,342.78062465137026,30.6372824460415245],"hsluv":[268.632918119842316,71.6553387322885698,30.6372824460415245]},"#4433bb":{"lch":[32.2226022397772525,93.4505902198726375,268.062492493372758],"luv":[32.2226022397772525,-3.15951219941267691,-93.3971642776391633],"rgb":[0.266666666666666663,0.2,0.733333333333333282],"xyz":[0.125363032374582017,0.0718419248718060871,0.477414130972448],"hpluv":[268.062492493372758,368.010970109266054,32.2226022397772525],"hsluv":[268.062492493372758,75.8581190135042789,32.2226022397772525]},"#4433cc":{"lch":[33.8908458580626331,103.832026214070311,267.649236367220567],"luv":[33.8908458580626331,-4.25888397543315911,-103.744646006447894],"rgb":[0.266666666666666663,0.2,0.8],"xyz":[0.144655407818303772,0.0795588750492948887,0.579020641642718159],"hpluv":[267.649236367220567,388.765974213008576,33.8908458580626331],"hsluv":[267.649236367220567,79.3114034284002,33.8908458580626331]},"#4433dd":{"lch":[35.628800942302739,113.96424557581804,267.340372831489958],"luv":[35.628800942302739,-5.28823530427115518,-113.841485571087048],"rgb":[0.266666666666666663,0.2,0.866666666666666696],"xyz":[0.166173733368937315,0.0881662052695484227,0.692350489542724157],"hpluv":[267.340372831489958,405.888493424646128,35.628800942302739],"hsluv":[267.340372831489958,85.5677988674314,35.628800942302739]},"#4433ee":{"lch":[37.4248062251042484,123.894025620863303,267.103630337901393],"luv":[37.4248062251042484,-6.26032296204841732,-123.73575853791813],"rgb":[0.266666666666666663,0.2,0.933333333333333348],"xyz":[0.189985913635112053,0.0976910773760184536,0.81776130561124738],"hpluv":[267.103630337901393,420.078186698807599,37.4248062251042484],"hsluv":[267.103630337901393,92.6566888343209,37.4248062251042484]},"#4433ff":{"lch":[39.2687372084732473,133.657198385904053,266.918330051954797],"luv":[39.2687372084732473,-7.18532525912719411,-133.4639193988003],"rgb":[0.266666666666666663,0.2,1],"xyz":[0.216156962044943446,0.10815949673995115,0.955595493903029225],"hpluv":[266.918330051954797,431.901531941155895,39.2687372084732473],"hsluv":[266.918330051954797,99.99999999999946,39.2687372084732473]},"#bbbb00":{"lch":[73.6141498101152223,81.1522849996882485,85.8743202181747591],"luv":[73.6141498101152223,5.83845950082822274,80.9419900380996],"rgb":[0.733333333333333282,0.733333333333333282,0],"xyz":[0.382626051771664,0.461058251568279,0.0688379405602788],"hpluv":[85.8743202181747591,139.887458074797564,73.6141498101152223],"hsluv":[85.8743202181747591,100.000000000002331,73.6141498101152223]},"#bbbb11":{"lch":[73.6403599567658205,80.0195247391518478,85.8743202181747449],"luv":[73.6403599567658205,5.75696364516240155,79.8121651696532695],"rgb":[0.733333333333333282,0.733333333333333282,0.0666666666666666657],"xyz":[0.383637717271301082,0.461462917768133862,0.0741660455250344325],"hpluv":[85.8743202181747449,137.885751829634614,73.6403599567658205],"hsluv":[85.8743202181747449,98.5690595334933732,73.6403599567658205]},"#bbbb22":{"lch":[73.6889060807276763,77.9361940700347873,85.8743202181746597],"luv":[73.6889060807276763,5.60707948923862176,77.7342331648256817],"rgb":[0.733333333333333282,0.733333333333333282,0.133333333333333331],"xyz":[0.385513075409778139,0.462213061023524663,0.0840429317210136251],"hpluv":[85.8743202181746597,134.207383902194948,73.6889060807276763],"hsluv":[85.8743202181746597,95.9395400768792541,73.6889060807276763]},"#bbbb33":{"lch":[73.768722281637082,74.5519121144895536,85.8743202181745318],"luv":[73.768722281637082,5.36359906059884217,74.3587211095223],"rgb":[0.733333333333333282,0.733333333333333282,0.2],"xyz":[0.388600826142235845,0.46344816131650779,0.100305085578624775],"hpluv":[85.8743202181745318,128.24069174643796,73.768722281637082],"hsluv":[85.8743202181745318,91.6741883163470419,73.768722281637082]},"#bbbb44":{"lch":[73.8837085661944144,69.7637661309282464,85.8743202181743328],"luv":[73.8837085661944144,5.01911835485944824,69.5829829463408629],"rgb":[0.733333333333333282,0.733333333333333282,0.266666666666666663],"xyz":[0.39305882138645476,0.465231359414195356,0.123783860531511414],"hpluv":[85.8743202181743328,119.817583791868643,73.8837085661944144],"hsluv":[85.8743202181743328,85.652842249664161,73.8837085661944144]},"#bbbb55":{"lch":[74.0370403615741,63.5337415760462747,85.8743202181740628],"luv":[74.0370403615741,4.57090243520957262,63.3691026414263376],"rgb":[0.733333333333333282,0.733333333333333282,0.333333333333333315],"xyz":[0.399021235425816745,0.467616325029940216,0.155185907805485301],"hpluv":[85.8743202181740628,108.891682763750694,74.0370403615741],"hsluv":[85.8743202181740628,77.8423486010655239,74.0370403615741]},"#bbbb66":{"lch":[74.2313474843288361,55.8815023675101799,85.8743202181735512],"luv":[74.2313474843288361,4.02036601211528843,55.7366931561128212],"rgb":[0.733333333333333282,0.733333333333333282,0.4],"xyz":[0.40660623119932493,0.470650323339343535,0.195133552212629291],"hpluv":[85.8743202181735512,95.5256619678334857,74.2313474843288361],"hsluv":[85.8743202181735512,68.2875100330713138,74.2313474843288361]},"#bbbb77":{"lch":[74.468808451125966,46.8772880877030289,85.8743202181728549],"luv":[74.468808451125966,3.37256243628739805,46.7558120565865849],"rgb":[0.733333333333333282,0.733333333333333282,0.466666666666666674],"xyz":[0.415920244219526836,0.47437592854742433,0.2441873541190272],"hpluv":[85.8743202181728549,79.8780401793102328,74.468808451125966],"hsluv":[85.8743202181728549,57.1016453359253688,74.468808451125966]},"#bbbb88":{"lch":[74.7512063572608128,36.6333476151433146,85.874320218171647],"luv":[74.7512063572608128,2.63556739569020726,36.5384173438683746],"rgb":[0.733333333333333282,0.733333333333333282,0.533333333333333326],"xyz":[0.427060661321470636,0.478832095388201928,0.30286021752259934],"hpluv":[85.874320218171647,62.1867310089120195,74.7512063572608128],"hsluv":[85.874320218171647,44.4548295213588744,74.7512063572608128]},"#bbbb99":{"lch":[75.079965438194165,25.2938928616919938,85.8743202181691316],"luv":[75.079965438194165,1.81975614231989979,25.2283472245258693],"rgb":[0.733333333333333282,0.733333333333333282,0.6],"xyz":[0.440117625430543336,0.484054881031831086,0.371626895163717275],"hpluv":[85.8743202181691316,42.7494899193068392,75.079965438194165],"hsluv":[85.8743202181691316,30.559916169503893,75.079965438194165]},"#bbbbaa":{"lch":[75.4561775549407372,13.0242335847304886,85.8743202181613583],"luv":[75.4561775549407372,0.937021801842234714,12.9904830784884187],"rgb":[0.733333333333333282,0.733333333333333282,0.66666666666666663],"xyz":[0.455175318395795891,0.490077958217932208,0.450930744780715875],"hpluv":[85.8743202181613583,21.9026519543336242,75.4561775549407372],"hsluv":[85.8743202181613583,15.6573378741524305,75.4561775549407372]},"#bbbbbb":{"lch":[75.8806235332097856,3.97454725928322e-12,0],"luv":[75.8806235332097856,3.75098259432623098e-12,1.31421287976393485e-12],"rgb":[0.733333333333333282,0.733333333333333282,0.733333333333333282],"xyz":[0.472312910503132566,0.496932995060866967,0.541188729879357622],"hpluv":[0,6.64654731741433278e-12,75.8806235332097856],"hsluv":[0,6.51507609526145538e-12,75.8806235332097856]},"#bbbbcc":{"lch":[76.3537921403793,13.6026726964261613,265.874320218192793],"luv":[76.3537921403793,-0.97863730689855577,-13.5674232449512715],"rgb":[0.733333333333333282,0.733333333333333282,0.8],"xyz":[0.491605285946854265,0.504649945238355713,0.642795240549627778],"hpluv":[265.874320218192793,23.0577392955455913,76.3537921403793],"hsluv":[265.874320218192793,22.3559583930985184,76.3537921403793]},"#bbbbdd":{"lch":[76.875898300454,27.6153317552162676,265.874320218184891],"luv":[76.875898300454,-1.98677087225565296,-27.543770429115412],"rgb":[0.733333333333333282,0.733333333333333282,0.866666666666666696],"xyz":[0.513123611497487864,0.51325727545860933,0.756125088449633775],"hpluv":[265.874320218184891,48.094692651754464,76.875898300454],"hsluv":[265.874320218184891,46.4508399898830717,76.875898300454]},"#bbbbee":{"lch":[77.4469014383288794,41.8833893600305487,265.874320218182334],"luv":[77.4469014383288794,-3.01327895494808,-41.7748543291725554],"rgb":[0.733333333333333282,0.733333333333333282,0.933333333333333348],"xyz":[0.536935791763662573,0.522782147565079347,0.881535904518157],"hpluv":[265.874320218182334,75.1781465494946,77.4469014383288794],"hsluv":[265.874320218182334,72.306149300046286,77.4469014383288794]},"#bbbbff":{"lch":[78.0665243938900915,56.270213901735211,265.874320218181083],"luv":[78.0665243938900915,-4.04833166396953814,-56.1243973979724444],"rgb":[0.733333333333333282,0.733333333333333282,1],"xyz":[0.563106840173494,0.533250566929012,1.01937009280993873],"hpluv":[265.874320218181083,104.437018855576454,78.0665243938900915],"hsluv":[265.874320218181083,99.9999999999968,78.0665243938900915]},"#99cc00":{"lch":[76.0430979526319,91.0941172293808,106.263360497649074],"luv":[76.0430979526319,-25.5111694560196547,87.4489475453331124],"rgb":[0.6,0.8,0],"xyz":[0.347284960501106077,0.499573870357110428,0.0781308367092051204],"hpluv":[106.263360497649074,152.00919412554731,76.0430979526319],"hsluv":[106.263360497649074,100.000000000002444,76.0430979526319]},"#99cc11":{"lch":[76.0679435797449202,90.0431717383104342,106.457693210299354],"luv":[76.0679435797449202,-25.5098862277023812,86.3540299079582496],"rgb":[0.6,0.8,0.0666666666666666657],"xyz":[0.348296626000743181,0.499978536556965281,0.083458941673960757],"hpluv":[106.457693210299354,150.416675371578,76.0679435797449202],"hsluv":[106.457693210299354,98.6698238814781377,76.0679435797449202]},"#99cc22":{"lch":[76.1139653123302224,88.1120975577654235,106.827460928226145],"luv":[76.1139653123302224,-25.5076232207001254,84.3392132620406301],"rgb":[0.6,0.8,0.133333333333333331],"xyz":[0.350171984139220238,0.500728679812356137,0.0933358278699399496],"hpluv":[106.827460928226145,147.536178080277807,76.1139653123302224],"hsluv":[106.827460928226145,96.2239688839219554,76.1139653123302224]},"#99cc33":{"lch":[76.1896394090333615,84.9806694979027668,107.464683868975555],"luv":[76.1896394090333615,-25.5042190273125513,81.0632407452271195],"rgb":[0.6,0.8,0.2],"xyz":[0.353259734871677944,0.501963780105339263,0.109597981727551086],"hpluv":[107.464683868975555,142.843382477451314,76.1896394090333615],"hsluv":[107.464683868975555,92.2523981769505497,76.1896394090333615]},"#99cc44":{"lch":[76.2986765643697566,80.5641186971074461,108.452476349375274],"luv":[76.2986765643697566,-25.4999909675489818,76.4220366262018445],"rgb":[0.6,0.8,0.266666666666666663],"xyz":[0.357717730115896859,0.503746978203026829,0.133076756680437724],"hpluv":[108.452476349375274,136.177549938509202,76.2986765643697566],"hsluv":[108.452476349375274,86.6370393323296,76.2986765643697566]},"#99cc55":{"lch":[76.4441084930992645,74.8483308647658276,109.915235611542258],"luv":[76.4441084930992645,-25.4955548836031696,70.3722197633315858],"rgb":[0.6,0.8,0.333333333333333315],"xyz":[0.363680144155258844,0.506131943818771579,0.16447880395441164],"hpluv":[109.915235611542258,127.465568679298812,76.4441084930992645],"hsluv":[109.915235611542258,79.3378797119037245,76.4441084930992645]},"#99cc66":{"lch":[76.6284587708723279,67.8919791104198111,112.053749389120497],"luv":[76.6284587708723279,-25.4918238993559072,62.9244606001029396],"rgb":[0.6,0.8,0.4],"xyz":[0.37126513992876703,0.509165942128174898,0.204426448361555602],"hpluv":[112.053749389120497,116.726185086844026,76.6284587708723279],"hsluv":[112.053749389120497,70.3850130172815796,76.6284587708723279]},"#99cc77":{"lch":[76.8538330837355801,59.8379910057359723,115.212918879407354],"luv":[76.8538330837355801,-25.4899847789994141,54.1372869986012262],"rgb":[0.6,0.8,0.466666666666666674],"xyz":[0.380579152948968935,0.512891547336255749,0.253480250267953511],"hpluv":[115.212918879407354,104.093311342856381,76.8538330837355801],"hsluv":[115.212918879407354,59.8707914454029577,76.8538330837355801]},"#99cc88":{"lch":[77.1219726780439885,50.9458531819172649,120.024060615406185],"luv":[77.1219726780439885,-25.4914521322680621,44.1097021597488919],"rgb":[0.6,0.8,0.533333333333333326],"xyz":[0.391719570050912735,0.517347714177033291,0.31215311367152565],"hpluv":[120.024060615406185,89.8814395273866324,77.1219726780439885],"hsluv":[120.024060615406185,47.9401368886289845,77.1219726780439885]},"#99cc99":{"lch":[77.4342891130262103,41.681173098632776,127.715012949236964],"luv":[77.4342891130262103,-25.4978049096247332,32.9724450969124447],"rgb":[0.6,0.8,0.6],"xyz":[0.40477653415998549,0.522570499820662504,0.380919791312643585],"hpluv":[127.715012949236964,74.7648437658604337,77.4342891130262103],"hsluv":[127.715012949236964,34.7788947556027495,77.4342891130262103]},"#99ccaa":{"lch":[77.7918890721377352,32.9651751214879525,140.702563314804109],"luv":[77.7918890721377352,-25.5107121176450882,20.8783701002018844],"rgb":[0.6,0.8,0.66666666666666663],"xyz":[0.419834227125238,0.528593577006763571,0.460223640929642186],"hpluv":[140.702563314804109,60.2770963674260756,77.7918890721377352],"hsluv":[140.702563314804109,37.0803100068772622,77.7918890721377352]},"#99ccbb":{"lch":[78.1955939192693421,26.7536671513630395,162.617393192268167],"luv":[78.1955939192693421,-25.5318556358660231,7.9926875226808507],"rgb":[0.6,0.8,0.733333333333333282],"xyz":[0.436971819232574665,0.535448613849698329,0.550481626028283877],"hpluv":[162.617393192268167,50.006554278151107,78.1955939192693421],"hsluv":[162.617393192268167,39.5096284608221353,78.1955939192693421]},"#99cccc":{"lch":[78.6459566685868481,26.1512486118356264,192.177050630060364],"luv":[78.6459566685868481,-25.562857556775878,-5.51616873291790277],"rgb":[0.6,0.8,0.8],"xyz":[0.45626419467629642,0.543165564027187187,0.652088136698554],"hpluv":[192.177050630060364,50.1138147500145,78.6459566685868481],"hsluv":[192.177050630060364,42.0292910605185952,78.6459566685868481]},"#99ccdd":{"lch":[79.1432779300782,32.1756084020034763,217.269502822152816],"luv":[79.1432779300782,-25.6052179328205156,-19.4844191766612091],"rgb":[0.6,0.8,0.866666666666666696],"xyz":[0.477782520226929908,0.551772894247440693,0.76541798459856],"hpluv":[217.269502822152816,63.4104034428488532,79.1432779300782],"hsluv":[217.269502822152816,44.6030324020319142,79.1432779300782]},"#99ccee":{"lch":[79.6876217339600146,42.4043636674930298,232.761609201673764],"luv":[79.6876217339600146,-25.6602666815912279,-33.7591583407321],"rgb":[0.6,0.8,0.933333333333333348],"xyz":[0.501594700493104728,0.56129776635391071,0.890828800667083254],"hpluv":[232.761609201673764,86.2263034184575901,79.6876217339600146],"hsluv":[232.761609201673764,69.2463215394111842,79.6876217339600146]},"#99ccff":{"lch":[80.278831719152322,54.6396736698167231,241.908088190648726],"luv":[80.278831719152322,-25.7291311718118969,-48.2027566419988105],"rgb":[0.6,0.8,1],"xyz":[0.527765748902936,0.571766185717843434,1.02866298895886521],"hpluv":[241.908088190648726,115.039816302159181,80.278831719152322],"hsluv":[241.908088190648726,99.9999999999963762,80.278831719152322]},"#444400":{"lch":[27.7455139749470092,30.5866720374503593,85.8743202181747307],"luv":[27.7455139749470092,2.20054242411605072,30.5074108925390952],"rgb":[0.266666666666666663,0.266666666666666663,0],"xyz":[0.044508744126079483,0.0536323223451504599,0.00800753181435780864],"hpluv":[85.8743202181747307,139.887458074797593,27.7455139749470092],"hsluv":[85.8743202181747307,100.000000000002331,27.7455139749470092]},"#444411":{"lch":[27.8552611903384602,27.0161424908788135,85.8743202181744],"luv":[27.8552611903384602,1.9436625081132386,26.9461338811715763],"rgb":[0.266666666666666663,0.266666666666666663,0.0666666666666666657],"xyz":[0.0455204096257166,0.0540369885450053128,0.0133356367791134401],"hpluv":[85.8743202181744,123.070915058641674,27.8552611903384602],"hsluv":[85.8743202181744,87.9785198418851451,27.8552611903384602]},"#444422":{"lch":[28.0572627170229296,20.802612285424587,85.8743202181735086],"luv":[28.0572627170229296,1.49663326596887214,20.7487051828516122],"rgb":[0.266666666666666663,0.266666666666666663,0.133333333333333331],"xyz":[0.0473957677641936234,0.0547871318003961341,0.0232125229750926379],"hpluv":[85.8743202181735086,94.0831614915658463,28.0572627170229296],"hsluv":[85.8743202181735086,67.2563236092702539,28.0572627170229296]},"#444433":{"lch":[28.3858756417530103,11.5666907278610811,85.8743202181704],"luv":[28.3858756417530103,0.832159628943940688,11.5367172430437677],"rgb":[0.266666666666666663,0.266666666666666663,0.2],"xyz":[0.0504835184966513639,0.056022232093379247,0.0394746768327037811],"hpluv":[85.8743202181704,51.7066205750809758,28.3858756417530103],"hsluv":[85.8743202181704,36.9630139018145201,28.3858756417530103]},"#444444":{"lch":[28.8519023983998864,1.56211738287899238e-12,0],"luv":[28.8519023983998864,1.45745810878583046e-12,5.6216241338882039e-13],"rgb":[0.266666666666666663,0.266666666666666663,0.266666666666666663],"xyz":[0.0549415137408702445,0.05780543019106682,0.0629534517855904197],"hpluv":[0,6.87034486140541504e-12,28.8519023983998864],"hsluv":[0,1.96712204652458306e-12,28.8519023983998864]},"#444455":{"lch":[29.4604491554767947,12.996237632929807,265.874320218183527],"luv":[29.4604491554767947,-0.935007647451096213,-12.9625596743385874],"rgb":[0.266666666666666663,0.266666666666666663,0.333333333333333315],"xyz":[0.0609039277802322365,0.0601903958068116529,0.094355499059564335],"hpluv":[265.874320218183527,55.9780294653588157,29.4604491554767947],"hsluv":[265.874320218183527,10.903125265393685,29.4604491554767947]},"#444466":{"lch":[30.2117995944983235,26.5936989313503034,265.874320218180401],"luv":[30.2117995944983235,-1.9132700229980284,-26.52478502590359],"rgb":[0.266666666666666663,0.266666666666666663,0.4],"xyz":[0.0684889235537404079,0.0632243941162149714,0.134303143466708297],"hpluv":[265.874320218180401,111.69699235114156,30.2117995944983235],"hsluv":[265.874320218180401,21.7557908165695544,30.2117995944983235]},"#444477":{"lch":[31.1022350000615333,40.188693881548005,265.874320218179378],"luv":[31.1022350000615333,-2.89135495838767076,-40.084550420447286],"rgb":[0.266666666666666663,0.266666666666666663,0.466666666666666674],"xyz":[0.0778029365739423273,0.0669499993242957808,0.183356945373106206],"hpluv":[265.874320218179378,163.965176201048621,31.1022350000615333],"hsluv":[265.874320218179378,31.9363305989270607,31.1022350000615333]},"#444488":{"lch":[32.1249060438116132,53.4239352836437,265.874320218178923],"luv":[32.1249060438116132,-3.84355760936744639,-53.2854945186250859],"rgb":[0.266666666666666663,0.266666666666666663,0.533333333333333326],"xyz":[0.0889433536758861554,0.0714061661650733787,0.242029808776678373],"hpluv":[265.874320218178923,211.024721596932807,32.1249060438116132],"hsluv":[265.874320218178923,41.1023574005893479,32.1249060438116132]},"#444499":{"lch":[33.2707247827276404,66.1374776044503818,265.874320218178639],"luv":[33.2707247827276404,-4.75822688765494473,-65.9660914467787336],"rgb":[0.266666666666666663,0.266666666666666663,0.6],"xyz":[0.102000317784958869,0.0766289518087025362,0.31079648641779628],"hpluv":[265.874320218178639,252.246234683596128,33.2707247827276404],"hsluv":[265.874320218178639,50.2337582903708224,33.2707247827276404]},"#4444aa":{"lch":[34.5292085317775772,78.2936422443982707,265.874320218178468],"luv":[34.5292085317775772,-5.63279591471267516,-78.090755061511743],"rgb":[0.266666666666666663,0.266666666666666663,0.66666666666666663],"xyz":[0.117058010750211411,0.0826520289948036446,0.390100336034794881],"hpluv":[265.874320218178468,287.726060771882089,34.5292085317775772],"hsluv":[265.874320218178468,59.0260968416557645,34.5292085317775772]},"#4444bb":{"lch":[35.8892144652077647,89.9250819913669801,265.874320218178354],"luv":[35.8892144652077647,-6.46961387860876,-89.6920535355044],"rgb":[0.266666666666666663,0.266666666666666663,0.733333333333333282],"xyz":[0.134195602857548058,0.0895070658377384,0.480358321133436628],"hpluv":[265.874320218178354,317.948086985701252,35.8892144652077647],"hsluv":[265.874320218178354,67.4283717547759807,35.8892144652077647]},"#4444cc":{"lch":[37.3395287853000397,101.093816173965237,265.874320218178298],"luv":[37.3395287853000397,-7.27314272811459173,-100.831845482823283],"rgb":[0.266666666666666663,0.266666666666666663,0.8],"xyz":[0.153487978301269812,0.0972240160152272,0.581964831803706728],"hpluv":[265.874320218178298,343.55405942077391,37.3395287853000397],"hsluv":[265.874320218178298,75.5808548987534294,37.3395287853000397]},"#4444dd":{"lch":[38.8693012328948697,111.868746538356049,265.874320218178241],"luv":[38.8693012328948697,-8.04833956400084105,-111.578854100252741],"rgb":[0.266666666666666663,0.266666666666666663,0.866666666666666696],"xyz":[0.175006303851903355,0.105831346235480739,0.695294679703712726],"hpluv":[265.874320218178241,365.208910634554,38.8693012328948697],"hsluv":[265.874320218178241,83.6313726076760702,38.8693012328948697]},"#4444ee":{"lch":[40.4683363226646691,122.314460404417545,265.874320218178127],"luv":[40.4683363226646691,-8.799851087852959,-121.997499338533331],"rgb":[0.266666666666666663,0.266666666666666663,0.933333333333333348],"xyz":[0.198818484118078065,0.115356218341950756,0.820705495772236],"hpluv":[265.874320218178127,383.532154053589807,40.4683363226646691],"hsluv":[265.874320218178127,91.7249319236633625,40.4683363226646691]},"#4444ff":{"lch":[42.1272645151277203,132.4867415013303,265.874320218178127],"luv":[42.1272645151277203,-9.53169063144130568,-132.143420370999962],"rgb":[0.266666666666666663,0.266666666666666663,1],"xyz":[0.224989532527909486,0.12582463770588348,0.958539684064017794],"hpluv":[265.874320218178127,399.069452944254863,42.1272645151277203],"hsluv":[265.874320218178127,99.9999999999994458,42.1272645151277203]},"#bbcc00":{"lch":[78.3160688649495711,87.6272661942945916,93.3039767998847651],"luv":[78.3160688649495711,-5.05025027162958828,87.4816137990130471],"rgb":[0.733333333333333282,0.8,0],"xyz":[0.420849795081280953,0.537505738187513904,0.081579188330150737],"hpluv":[93.3039767998847651,164.876849582678972,78.3160688649495711],"hsluv":[93.3039767998847651,100.000000000002302,78.3160688649495711]},"#bbcc11":{"lch":[78.3397318378619332,86.5943586896397193,93.3754549086192],"luv":[78.3397318378619332,-5.09856582429126703,86.4441298377475249],"rgb":[0.733333333333333282,0.8,0.0666666666666666657],"xyz":[0.421861460580918057,0.537910404387368812,0.0869072932949063737],"hpluv":[93.3754549086192,163.146061131239662,78.3397318378619332],"hsluv":[93.3754549086192,98.7690619278293,78.3397318378619332]},"#bbcc22":{"lch":[78.3835653101130134,84.6929692802742125,93.5116381573829329],"luv":[78.3835653101130134,-5.18755307791811582,84.5339478468458481],"rgb":[0.733333333333333282,0.8,0.133333333333333331],"xyz":[0.423736818719395114,0.538660547642759613,0.0967841794908855663],"hpluv":[93.5116381573829329,159.95035726483485,78.3835653101130134],"hsluv":[93.5116381573829329,96.5043106774720343,78.3835653101130134]},"#bbcc33":{"lch":[78.4556479267243,81.5996211754986405,93.7468972468941644],"luv":[78.4556479267243,-5.33246113691784,81.4251990123951],"rgb":[0.733333333333333282,0.8,0.2],"xyz":[0.42682456945185282,0.53989564793574274,0.113046333348496703],"hpluv":[93.7468972468941644,154.72407311273281,78.4556479267243],"hsluv":[93.7468972468941644,92.8230308779070157,78.4556479267243]},"#bbcc44":{"lch":[78.5595248117047475,77.2136355312914873,94.1131309849175],"luv":[78.5595248117047475,-5.53822791342104281,77.0147618547127877],"rgb":[0.733333333333333282,0.8,0.266666666666666663],"xyz":[0.431282564696071735,0.541678846033430306,0.136525108301383341],"hpluv":[94.1131309849175,147.254264694427633,78.5595248117047475],"hsluv":[94.1131309849175,87.6101015600037556,78.5595248117047475]},"#bbcc55":{"lch":[78.6981007967589079,71.4912273296626921,94.6593076474989488],"luv":[78.6981007967589079,-5.80727962831129307,71.2549723768110823],"rgb":[0.733333333333333282,0.8,0.333333333333333315],"xyz":[0.43724497873543372,0.544063811649175,0.167927155575357256],"hpluv":[94.6593076474989488,137.398731222980217,78.6981007967589079],"hsluv":[94.6593076474989488,80.8199795518833639,78.6981007967589079]},"#bbcc66":{"lch":[78.8738041161037273,64.440755538040392,95.4673459440295176],"luv":[78.8738041161037273,-6.13981465986491681,64.1475927081912403],"rgb":[0.733333333333333282,0.8,0.4],"xyz":[0.444829974508941905,0.547097809958578374,0.207874799982501218],"hpluv":[95.4673459440295176,125.075317361724217,78.8738041161037273],"hsluv":[95.4673459440295176,72.4696955468646848,78.8738041161037273]},"#bbcc77":{"lch":[79.0886730863018244,56.1202023011108153,96.6860819525870454],"luv":[79.0886730863018244,-6.5340457953894715,55.7385266387743386],"rgb":[0.733333333333333282,0.8,0.466666666666666674],"xyz":[0.454143987529143811,0.550823415166659225,0.2569286018888991],"hpluv":[96.6860819525870454,110.256785788709905,79.0886730863018244],"hsluv":[96.6860819525870454,62.6323703341884,79.0886730863018244]},"#bbcc88":{"lch":[79.3444074564468451,46.6379090458556931,98.6154841820407],"luv":[79.3444074564468451,-6.9864776714612713,46.1116437563841473],"rgb":[0.733333333333333282,0.8,0.533333333333333326],"xyz":[0.465284404631087611,0.555279582007436767,0.315601465292471295],"hpluv":[98.6154841820407,92.9740665461038702,79.3444074564468451],"hsluv":[98.6154841820407,51.4293340198482483,79.3444074564468451]},"#bbcc99":{"lch":[79.6424016540563,36.1659853952486898,101.956116252097843],"luv":[79.6424016540563,-7.49223418159530397,35.3814206410296137],"rgb":[0.733333333333333282,0.8,0.6],"xyz":[0.478341368740160311,0.560502367651066,0.38436814293358923],"hpluv":[101.956116252097843,73.3480812445522616,79.6424016540563],"hsluv":[101.956116252097843,39.0205672484538439,79.6424016540563]},"#bbccaa":{"lch":[79.9837682606211899,25.01387761080953,108.762036830266098],"luv":[79.9837682606211899,-8.04542335958215382,23.6847046866463593],"rgb":[0.733333333333333282,0.8,0.66666666666666663],"xyz":[0.493399061705412867,0.566525444837167,0.463671992550587775],"hpluv":[108.762036830266098,51.7527419020047645,79.9837682606211899],"hsluv":[108.762036830266098,25.5939208298632828,79.9837682606211899]},"#bbccbb":{"lch":[80.3693561861161356,14.1229851396422195,127.715012949226079],"luv":[80.3693561861161356,-8.63951499109438892,11.1721748094634776],"rgb":[0.733333333333333282,0.8,0.733333333333333282],"xyz":[0.510536653812749486,0.573380481680101806,0.553929977649229577],"hpluv":[127.715012949226079,29.8960175179438359,80.3693561861161356],"hsluv":[127.715012949226079,11.3539027840963094,80.3693561861161356]},"#bbcccc":{"lch":[80.7997661027856537,9.48102181692548207,192.177050630058517],"luv":[80.7997661027856537,-9.26770319062559622,-1.99986306118322021],"rgb":[0.733333333333333282,0.8,0.8],"xyz":[0.52982902925647124,0.581097431857590663,0.655536488319499733],"hpluv":[192.177050630058517,20.5979746439306091,80.7997661027856537],"hsluv":[192.177050630058517,14.8313634310922779,80.7997661027856537]},"#bbccdd":{"lch":[81.2753646562375138,18.5534915910332536,237.666646406054781],"luv":[81.2753646562375138,-9.9232294288842251,-15.6767843616051454],"rgb":[0.733333333333333282,0.8,0.866666666666666696],"xyz":[0.551347354807104839,0.589704762077844169,0.76886633621950573],"hpluv":[237.666646406054781,41.5059211719903089,81.2753646562375138],"hsluv":[237.666646406054781,34.6395739712995834,81.2753646562375138]},"#bbccee":{"lch":[81.7962983545147466,31.5457627715974915,250.366116177600304],"luv":[81.7962983545147466,-10.5996485000078611,-29.7116576534899401],"rgb":[0.733333333333333282,0.8,0.933333333333333348],"xyz":[0.575159535073279549,0.599229634184314186,0.894277152288029],"hpluv":[250.366116177600304,72.9233806917818725,81.7962983545147466],"hsluv":[250.366116177600304,65.9765826509477478,81.7962983545147466]},"#bbccff":{"lch":[82.3625076456434329,45.3963265868234203,255.598148289110497],"luv":[82.3625076456434329,-11.2910283768039683,-43.9697526234994669],"rgb":[0.733333333333333282,0.8,1],"xyz":[0.601330583483111,0.60969805354824691,1.0321113405798108],"hpluv":[255.598148289110497,108.847942718229262,82.3625076456434329],"hsluv":[255.598148289110497,99.9999999999958789,82.3625076456434329]},"#99dd00":{"lch":[81.0072374435841738,100.100388992767378,110.059278565234735],"luv":[81.0072374435841738,-34.3336498242400623,94.028125400062109],"rgb":[0.6,0.866666666666666696,0],"xyz":[0.389918951048281226,0.584841851451462,0.0923421668915964389],"hpluv":[110.059278565234735,220.251619684458433,81.0072374435841738],"hsluv":[110.059278565234735,100.000000000002245,81.0072374435841738]},"#99dd11":{"lch":[81.0296061686003,99.1554895677318626,110.248463134872608],"luv":[81.0296061686003,-34.3169109383134483,93.0277417498051733],"rgb":[0.6,0.866666666666666696,0.0666666666666666657],"xyz":[0.39093061654791833,0.585246517651316855,0.0976702718563520755],"hpluv":[110.248463134872608,218.472914234601802,81.0296061686003],"hsluv":[110.248463134872608,98.8616036668283,81.0296061686003]},"#99dd22":{"lch":[81.0710445633976,97.4178442494470431,110.606606003803336],"luv":[81.0710445633976,-34.2861684396920552,91.184949591117217],"rgb":[0.6,0.866666666666666696,0.133333333333333331],"xyz":[0.392805974686395387,0.585996660906707656,0.107547158052331268],"hpluv":[110.606606003803336,215.192819254761019,81.0710445633976],"hsluv":[110.606606003803336,96.7659338960775131,81.0710445633976]},"#99dd33":{"lch":[81.1391953168863154,94.5961335984436857,111.218234049095599],"luv":[81.1391953168863154,-34.2363517117206513,88.1833358024404106],"rgb":[0.6,0.866666666666666696,0.2],"xyz":[0.395893725418853093,0.587231761199690783,0.123809311909942404],"hpluv":[111.218234049095599,209.840835623165077,81.1391953168863154],"hsluv":[111.218234049095599,93.3562182204636599,81.1391953168863154]},"#99dd44":{"lch":[81.2374208116197565,90.6080011845065343,112.152709421166279],"luv":[81.2374208116197565,-34.1661449288095653,83.9195115533635487],"rgb":[0.6,0.866666666666666696,0.266666666666666663],"xyz":[0.400351720663072,0.589014959297378349,0.147288086862829043],"hpluv":[112.152709421166279,202.22119953609328,81.2374208116197565],"hsluv":[112.152709421166279,88.5208972681928827,81.2374208116197565]},"#99dd55":{"lch":[81.3684846041416421,85.4315699411036604,113.506988965296216],"luv":[81.3684846041416421,-34.0753153837539244,78.3417259453695607],"rgb":[0.6,0.866666666666666696,0.333333333333333315],"xyz":[0.406314134702434,0.591399924913123098,0.178690134136802958],"hpluv":[113.506988965296216,192.231211336261111,81.3684846041416421],"hsluv":[113.506988965296216,82.2103932307851579,81.3684846041416421]},"#99dd66":{"lch":[81.5347071887187695,79.1067404569191837,115.426438711198742],"luv":[81.5347071887187695,-33.9646313013793,71.4442454385217758],"rgb":[0.6,0.866666666666666696,0.4],"xyz":[0.413899130475942179,0.594433923222526417,0.21863777854394692],"hpluv":[115.426438711198742,179.864586291563711,81.5347071887187695],"hsluv":[115.426438711198742,74.4308834765056,81.5347071887187695]},"#99dd77":{"lch":[81.7380487099571,71.7428264562351217,118.139890255285593],"luv":[81.7380487099571,-33.8357763954940651,63.2627329764024324],"rgb":[0.6,0.866666666666666696,0.466666666666666674],"xyz":[0.423213143496144084,0.598159528430607268,0.267691580450344802],"hpluv":[118.139890255285593,165.232292085670224,81.7380487099571],"hsluv":[118.139890255285593,65.2389156719347,81.7380487099571]},"#99dd88":{"lch":[81.9801580086414248,63.5371271244577898,122.023063704989269],"luv":[81.9801580086414248,-33.6912346765093815,53.8689820694792942],"rgb":[0.6,0.866666666666666696,0.533333333333333326],"xyz":[0.434353560598087884,0.60261569527138481,0.326364443853917],"hpluv":[122.023063704989269,148.614644251947254,81.9801580086414248],"hsluv":[122.023063704989269,54.7350081565161943,81.9801580086414248]},"#99dd99":{"lch":[82.2624042681600827,54.8181455895933,127.715012949238044],"luv":[82.2624042681600827,-33.5341421039979721,43.3646215160552],"rgb":[0.6,0.866666666666666696,0.6],"xyz":[0.447410524707160584,0.607838480915014,0.395131121495034932],"hpluv":[127.715012949238044,130.58293025992694,82.2624042681600827],"hsluv":[127.715012949238044,43.0558433261763724,82.2624042681600827]},"#99ddaa":{"lch":[82.5858991321833855,46.1452119261310898,136.311935434488049],"luv":[82.5858991321833855,-33.3681126370237138,31.8739649675161907],"rgb":[0.6,0.866666666666666696,0.66666666666666663],"xyz":[0.46246821767241314,0.61386155810111509,0.474434971112033477],"hpluv":[136.311935434488049,112.281381223378744,82.5858991321833855],"hsluv":[136.311935434488049,44.8180878493830122,82.5858991321833855]},"#99ddbb":{"lch":[82.9515135213076,38.5190468703316,149.523212457301526],"luv":[82.9515135213076,-33.1970516149390349,19.536446347119437],"rgb":[0.6,0.866666666666666696,0.733333333333333282],"xyz":[0.479605809779749814,0.620716594944049849,0.564692956210675279],"hpluv":[149.523212457301526,96.0401150933983416,82.9515135213076],"hsluv":[149.523212457301526,46.6955526922259807,82.9515135213076]},"#99ddcc":{"lch":[83.3598915829196585,33.6584009809739158,168.866706644517421],"luv":[83.3598915829196585,-33.0249710093605202,6.49917274942921],"rgb":[0.6,0.866666666666666696,0.8],"xyz":[0.498898185223471513,0.628433545121538706,0.666299466880945435],"hpluv":[168.866706644517421,86.2854242091523,83.3598915829196585],"hsluv":[168.866706644517421,48.6618587245334879,83.3598915829196585]},"#99dddd":{"lch":[83.811463234187741,33.6120761253887,192.17705063006062],"luv":[83.811463234187741,-32.85581988586,-7.08990557672323529],"rgb":[0.6,0.866666666666666696,0.866666666666666696],"xyz":[0.520416510774105112,0.637040875341792212,0.779629314780951432],"hpluv":[192.17705063006062,88.9162454401141,83.811463234187741],"hsluv":[192.17705063006062,50.6906605199231777,83.811463234187741]},"#99ddee":{"lch":[84.3064561843391402,38.9043785470910208,212.822778279485817],"luv":[84.3064561843391402,-32.6933403312743565,-21.0878203738277712],"rgb":[0.6,0.866666666666666696,0.933333333333333348],"xyz":[0.544228691040279822,0.646565747448262229,0.905040130849474656],"hpluv":[212.822778279485817,106.615167592423816,84.3064561843391402],"hsluv":[212.822778279485817,60.6575363344623781,84.3064561843391402]},"#99ddff":{"lch":[84.8449079615810575,48.055447414973429,227.378328123916845],"luv":[84.8449079615810575,-32.5409551013358396,-35.3611689193969099],"rgb":[0.6,0.866666666666666696,1],"xyz":[0.570399739450111243,0.657034166812195,1.04287431914125639],"hpluv":[227.378328123916845,137.001856984753886,84.8449079615810575],"hsluv":[227.378328123916845,99.999999999994813,84.8449079615810575]},"#445500":{"lch":[33.4053570608210535,38.7644311760376397,101.469350612776353],"luv":[33.4053570608210535,-7.7080633936099785,37.9903525006263791],"rgb":[0.266666666666666663,0.333333333333333315,0],"xyz":[0.0563220008404254485,0.0772588357738427239,0.0119452840524730177],"hpluv":[101.469350612776353,147.25044771073371,33.4053570608210535],"hsluv":[101.469350612776353,100.000000000002245,33.4053570608210535]},"#445511":{"lch":[33.4914653280992525,35.8039831739898275,102.524785035338],"luv":[33.4914653280992525,-7.76452054412734,34.9519303021045076],"rgb":[0.266666666666666663,0.333333333333333315,0.0666666666666666657],"xyz":[0.0573336663400625668,0.0776635019736975768,0.0172733890172286492],"hpluv":[102.524785035338,135.655223597469387,33.4914653280992525],"hsluv":[102.524785035338,91.5452633494882093,33.4914653280992525]},"#445522":{"lch":[33.6502992474903806,30.5965852313305291,104.897478349629381],"luv":[33.6502992474903806,-7.86608410210478493,29.5681543001366229],"rgb":[0.266666666666666663,0.333333333333333315,0.133333333333333331],"xyz":[0.0592090244785395889,0.0784136452290883912,0.0271502752132078452],"hpluv":[104.897478349629381,115.378092601865731,33.6502992474903806],"hsluv":[104.897478349629381,76.6558497494370243,33.6502992474903806]},"#445533":{"lch":[33.9096245159150911,22.79863905315759,110.61032755328398],"luv":[33.9096245159150911,-8.02535730567797501,21.3394372651287],"rgb":[0.266666666666666663,0.333333333333333315,0.2],"xyz":[0.0622967752109973294,0.0796487455220715,0.0434124290708189919],"hpluv":[110.61032755328398,85.3149751467856419,33.9096245159150911],"hsluv":[110.61032755328398,54.1403397653178331,33.9096245159150911]},"#445544":{"lch":[34.2793424585633204,13.4702363502677187,127.715012949235046],"luv":[34.2793424585633204,-8.24020614134090401,10.6558092175245633],"rgb":[0.266666666666666663,0.333333333333333315,0.266666666666666663],"xyz":[0.0667547704552162,0.081431943619759084,0.0668912040237056305],"hpluv":[127.715012949235046,49.8634197051089814,34.2793424585633204],"hsluv":[127.715012949235046,25.3893680776039865,34.2793424585633204]},"#445555":{"lch":[34.7654846399243738,8.70030094248716424,192.177050630060222],"luv":[34.7654846399243738,-8.50454817645784544,-1.83518304377262664],"rgb":[0.266666666666666663,0.333333333333333315,0.333333333333333315],"xyz":[0.0727171844945782,0.0838169092355039169,0.098293251297679532],"hpluv":[192.177050630060222,31.7559649298661668,34.7654846399243738],"hsluv":[192.177050630060222,31.6316627668381969,34.7654846399243738]},"#445566":{"lch":[35.3707740335649916,17.7582093223154978,240.254504050727519],"luv":[35.3707740335649916,-8.81070452432763318,-15.4183489427423961],"rgb":[0.266666666666666663,0.333333333333333315,0.4],"xyz":[0.0803021802680863733,0.0868509075449072354,0.138240895704823508],"hpluv":[240.254504050727519,63.7079944588343352,35.3707740335649916],"hsluv":[240.254504050727519,38.2083413049732812,35.3707740335649916]},"#445577":{"lch":[36.0950574442792913,30.8488081821149329,252.743594747999822],"luv":[36.0950574442792913,-9.15124765847803623,-29.4602042177260124],"rgb":[0.266666666666666663,0.333333333333333315,0.466666666666666674],"xyz":[0.0896161932882882928,0.0905765127529880448,0.187294697611221417],"hpluv":[252.743594747999822,108.450105614435046,36.0950574442792913],"hsluv":[252.743594747999822,44.7362415879762878,36.0950574442792913]},"#445588":{"lch":[36.935739068143242,44.5159055243500319,257.651563208142],"luv":[36.935739068143242,-9.5200062368872409,-43.4860359874579245],"rgb":[0.266666666666666663,0.333333333333333315,0.533333333333333326],"xyz":[0.100756610390232121,0.0950326795937656427,0.245967561014793584],"hpluv":[257.651563208142,152.935302017774575,36.935739068143242],"hsluv":[257.651563208142,50.9359550606187952,36.935739068143242]},"#445599":{"lch":[37.8882410462664865,58.0440865604997711,260.167284745959819],"luv":[37.8882410462664865,-9.91231220062277885,-57.1914508600732674],"rgb":[0.266666666666666663,0.333333333333333315,0.6],"xyz":[0.113813574499304834,0.1002554652373948,0.314734238655911491],"hpluv":[260.167284745959819,194.398479571090235,37.8882410462664865],"hsluv":[260.167284745959819,56.6374271499956805,37.8882410462664865]},"#4455aa":{"lch":[38.9464770503006932,71.1678309986128141,261.658277796723496],"luv":[38.9464770503006932,-10.3247958657557941,-70.4149043837850144],"rgb":[0.266666666666666663,0.333333333333333315,0.66666666666666663],"xyz":[0.128871267464557376,0.106278542423495909,0.394038088272910092],"hpluv":[261.658277796723496,231.875507383352442,38.9464770503006932],"hsluv":[261.658277796723496,61.7617646139185652,38.9464770503006932]},"#4455bb":{"lch":[40.1033117689144,83.7900384834958,262.625350778636744],"luv":[40.1033117689144,-10.7550224317659584,-83.0969316013408417],"rgb":[0.266666666666666663,0.333333333333333315,0.733333333333333282],"xyz":[0.146008859571894023,0.113133579266430667,0.484296073371551838],"hpluv":[262.625350778636744,265.125486140416797,40.1033117689144],"hsluv":[262.625350778636744,66.2950009745661,40.1033117689144]},"#4455cc":{"lch":[41.3509797710146,95.8983760986006075,263.292411358069444],"luv":[41.3509797710146,-11.2011488171863753,-95.24196975873555],"rgb":[0.266666666666666663,0.333333333333333315,0.8],"xyz":[0.165301235015615777,0.120850529443919469,0.585902584041821939],"hpluv":[263.292411358069444,294.28272942652967,41.3509797710146],"hsluv":[263.292411358069444,71.9850161095278906,41.3509797710146]},"#4455dd":{"lch":[42.6814446156526657,107.523441304607104,263.773623462042394],"luv":[42.6814446156526657,-11.661670844638417,-106.88917561239117],"rgb":[0.266666666666666663,0.333333333333333315,0.866666666666666696],"xyz":[0.186819560566249321,0.129457859664173,0.699232431941827937],"hpluv":[263.773623462042394,319.67109728436958,42.6814446156526657],"hsluv":[263.773623462042394,81.2732363837730247,42.6814446156526657]},"#4455ee":{"lch":[44.0866885883675,118.714724855013472,264.132858108854521],"luv":[44.0866885883675,-12.1352655753704255,-118.092850024109339],"rgb":[0.266666666666666663,0.333333333333333315,0.933333333333333348],"xyz":[0.21063174083242403,0.13898273177064302,0.82464324801035116],"hpluv":[264.132858108854521,341.693279595385377,44.0866885883675],"hsluv":[264.132858108854521,90.5684283810677186,44.0866885883675]},"#4455ff":{"lch":[45.5589321196955765,129.526958246416882,264.408404412275218],"luv":[45.5589321196955765,-12.6207071057408875,-128.910630534181024],"rgb":[0.266666666666666663,0.333333333333333315,1],"xyz":[0.236802789242255451,0.149451151134575744,0.962477436302133],"hpluv":[264.408404412275218,360.766296003954039,45.5589321196955765],"hsluv":[264.408404412275218,99.9999999999992752,45.5589321196955765]},"#bbdd00":{"lch":[83.0607051195576673,95.2176030862527796,99.223939245402],"luv":[83.0607051195576673,-15.2627740644400269,93.9863802119702427],"rgb":[0.733333333333333282,0.866666666666666696,0],"xyz":[0.463483785628456102,0.622773719281865423,0.0957905185125420555],"hpluv":[99.223939245402,239.164338292747971,83.0607051195576673],"hsluv":[99.223939245402,100.00000000000216,83.0607051195576673]},"#bbdd11":{"lch":[83.082156377860457,94.2793845093074765,99.3314951275217481],"luv":[83.082156377860457,-15.2870500651298524,93.0317604034238457],"rgb":[0.733333333333333282,0.866666666666666696,0.0666666666666666657],"xyz":[0.464495451128093206,0.623178385481720332,0.101118623477297692],"hpluv":[99.3314951275217481,237.15213625798873,83.082156377860457],"hsluv":[99.3314951275217481,98.93507934353417,83.082156377860457]},"#bbdd22":{"lch":[83.1218967422411765,92.5513012339483794,99.5354402549794486],"luv":[83.1218967422411765,-15.3318301742674485,91.2725497814347],"rgb":[0.733333333333333282,0.866666666666666696,0.133333333333333331],"xyz":[0.466370809266570263,0.623928528737111132,0.110995509673276885],"hpluv":[99.5354402549794486,233.433860498438293,83.1218967422411765],"hsluv":[99.5354402549794486,96.9737920722735538,83.1218967422411765]},"#bbdd33":{"lch":[83.1872593514570298,89.7372330308786,99.8847694763800718],"luv":[83.1872593514570298,-15.4049421957575614,88.4050832700449263],"rgb":[0.733333333333333282,0.866666666666666696,0.2],"xyz":[0.469458559999027969,0.625163629030094259,0.127257663530888021],"hpluv":[99.8847694763800718,227.34486653748678,83.1872593514570298],"hsluv":[99.8847694763800718,93.7802848880547373,83.1872593514570298]},"#bbdd44":{"lch":[83.2814760883348697,85.7419087717973,100.421139587323779],"luv":[83.2814760883348697,-15.5091702542505097,84.3275788686944452],"rgb":[0.733333333333333282,0.866666666666666696,0.266666666666666663],"xyz":[0.473916555243246884,0.626946827127781825,0.15073643848377466],"hpluv":[100.421139587323779,218.62539011377612,83.2814760883348697],"hsluv":[100.421139587323779,89.2463889616074511,83.2814760883348697]},"#bbdd55":{"lch":[83.4072088624658,80.5207963453540572,101.204557559233223],"luv":[83.4072088624658,-15.6461875861262687,78.9860459708531835],"rgb":[0.733333333333333282,0.866666666666666696,0.333333333333333315],"xyz":[0.479878969282608869,0.629331792743526575,0.182138485757748575],"hpluv":[101.204557559233223,207.093501481883948,83.4072088624658],"hsluv":[101.204557559233223,83.3201121340644448,83.4072088624658]},"#bbdd66":{"lch":[83.5666996797624364,74.0772937371066149,102.328486133362119],"luv":[83.5666996797624364,-15.816696660053216,72.3690372616455164],"rgb":[0.733333333333333282,0.866666666666666696,0.4],"xyz":[0.487463965056117055,0.632365791052929893,0.222086130164892537],"hpluv":[102.328486133362119,192.635686460640301,83.5666996797624364],"hsluv":[102.328486133362119,75.9999631534792854,83.5666996797624364]},"#bbdd77":{"lch":[83.7618505003220122,66.4632811318093388,103.948126608074304],"luv":[83.7618505003220122,-16.0205304866066705,64.5035684418593149],"rgb":[0.733333333333333282,0.866666666666666696,0.466666666666666674],"xyz":[0.49677797807631896,0.636091396261010744,0.271139932071290446],"hpluv":[103.948126608074304,175.207590447676779,83.7618505003220122],"hsluv":[103.948126608074304,67.3303268013154,83.7618505003220122]},"#bbdd88":{"lch":[83.9942706402616,57.7845188457632091,106.339844930601203],"luv":[83.9942706402616,-16.2567564016803381,55.4505950331715454],"rgb":[0.733333333333333282,0.866666666666666696,0.533333333333333326],"xyz":[0.50791839517826276,0.640547563101788286,0.329812795474862641],"hpluv":[106.339844930601203,154.850612540446264,83.9942706402616],"hsluv":[106.339844930601203,57.39610210967858,83.9942706402616]},"#bbdd99":{"lch":[84.2653073070245711,48.2191913160874819,110.040291826115165],"luv":[84.2653073070245711,-16.5237946272095257,45.2996095159246153],"rgb":[0.733333333333333282,0.866666666666666696,0.6],"xyz":[0.520975359287335515,0.6457703487454175,0.39857947311598052],"hpluv":[110.040291826115165,131.749772406416298,84.2653073070245711],"hsluv":[110.040291826115165,46.3161497548768466,84.2653073070245711]},"#bbddaa":{"lch":[84.5760668100806328,38.0784660246866622,116.212889721452115],"luv":[84.5760668100806328,-16.8195514991441222,34.1624393473425059],"rgb":[0.733333333333333282,0.866666666666666696,0.66666666666666663],"xyz":[0.536033052252588,0.651793425931518566,0.477883322732979121],"hpluv":[116.212889721452115,106.421399158629868,84.5760668100806328],"hsluv":[116.212889721452115,34.2356923349747433,84.5760668100806328]},"#bbddbb":{"lch":[84.9274305013996553,28.0212505683590543,127.715012949233824],"luv":[84.9274305013996553,-17.1415612181778,22.1665821095230058],"rgb":[0.733333333333333282,0.866666666666666696,0.733333333333333282],"xyz":[0.55317064435992469,0.658648462774453325,0.568141307831620868],"hpluv":[127.715012949233824,80.3800713533813109,84.9274305013996553],"hsluv":[127.715012949233824,21.3181094477761164,84.9274305013996553]},"#bbddcc":{"lch":[85.3200677868051,19.876471170849122,151.617083508593169],"luv":[85.3200677868051,-17.4871274790593141,9.44851727715650291],"rgb":[0.733333333333333282,0.866666666666666696,0.8],"xyz":[0.572463019803646445,0.666365412951942182,0.669747818501891],"hpluv":[151.617083508593169,58.7374284962306703,85.3200677868051],"hsluv":[151.617083508593169,24.0698773292010699,85.3200677868051]},"#bbdddd":{"lch":[85.7544476215988,18.2643967282432129,192.177050630059739],"luv":[85.7544476215988,-17.8534562098583329,-3.85256916996079246],"rgb":[0.733333333333333282,0.866666666666666696,0.866666666666666696],"xyz":[0.593981345354279933,0.674972743172195688,0.783077666401897],"hpluv":[192.177050630059739,55.8245506661868234,85.7544476215988],"hsluv":[192.177050630059739,26.9205986284609722,85.7544476215988]},"#bbddee":{"lch":[86.2308493598319359,25.3453434934362818,223.980933900351914],"luv":[86.2308493598319359,-18.2377721186398958,-17.6002870700688909],"rgb":[0.733333333333333282,0.866666666666666696,0.933333333333333348],"xyz":[0.617793525620454753,0.684497615278665705,0.908488482470420244],"hpluv":[223.980933900351914,80.4705047412629142,86.2308493598319359],"hsluv":[223.980933900351914,55.5800524236117397,86.2308493598319359]},"#bbddff":{"lch":[86.7493734858622076,36.743147173338194,239.520163688183],"luv":[86.7493734858622076,-18.6374141011141354,-31.6655279416778761],"rgb":[0.733333333333333282,0.866666666666666696,1],"xyz":[0.643964574030286063,0.694966034642598429,1.0463226707622022],"hpluv":[239.520163688183,121.752323062157373,86.7493734858622076],"hsluv":[239.520163688183,99.9999999999938325,86.7493734858622076]},"#99ee00":{"lch":[85.9664003491010646,109.204546268980621,112.979852313128234],"luv":[85.9664003491010646,-42.6342645949387915,100.538313136150634],"rgb":[0.6,0.933333333333333348,0],"xyz":[0.437097727388796042,0.679199404132492912,0.108068425671767623],"hpluv":[112.979852313128234,339.428934639809256,85.9664003491010646],"hsluv":[112.979852313128234,100.000000000002444,85.9664003491010646]},"#99ee11":{"lch":[85.9866468155118326,108.350123359521945,113.156064955940181],"luv":[85.9866468155118326,-42.6072764400583495,99.6211284135251702],"rgb":[0.6,0.933333333333333348,0.0666666666666666657],"xyz":[0.438109392888433147,0.67960407033234782,0.11339653063652326],"hpluv":[113.156064955940181,337.317445797395,85.9866468155118326],"hsluv":[113.156064955940181,99.0182391276988,85.9866468155118326]},"#99ee22":{"lch":[86.0241571186350455,106.77763062148405,113.488368653358094],"luv":[86.0241571186350455,-42.5576013317541353,97.9301433166804287],"rgb":[0.6,0.933333333333333348,0.133333333333333331],"xyz":[0.439984751026910204,0.680354213587738621,0.123273416832502453],"hpluv":[113.488368653358094,333.419677856626379,86.0241571186350455],"hsluv":[113.488368653358094,97.2091916908085238,86.0241571186350455]},"#99ee33":{"lch":[86.0858572784747906,104.220652596579697,114.05202992935186],"luv":[86.0858572784747906,-42.476800751453851,95.1717701084636],"rgb":[0.6,0.933333333333333348,0.2],"xyz":[0.443072501759367909,0.681589313880721748,0.139535570690113603],"hpluv":[114.05202992935186,327.048640581280779,86.0858572784747906],"hsluv":[114.05202992935186,94.2610252844147709,86.0858572784747906]},"#99ee44":{"lch":[86.1748066309051239,100.599171066032113,114.904029942881266],"luv":[86.1748066309051239,-42.3622716989010186,91.2448966007484756],"rgb":[0.6,0.933333333333333348,0.266666666666666663],"xyz":[0.447530497003586825,0.683372511978409314,0.163014345643000241],"hpluv":[114.904029942881266,317.953677409096201,86.1748066309051239],"hsluv":[114.904029942881266,90.0700159696272777,86.1748066309051239]},"#99ee55":{"lch":[86.2935317577421586,95.884762204841536,116.119599614249481],"luv":[86.2935317577421586,-42.2129155656731854,86.0927254913233355],"rgb":[0.6,0.933333333333333348,0.333333333333333315],"xyz":[0.45349291104294881,0.685757477594154063,0.194416392916974157],"hpluv":[116.119599614249481,305.984138616458665,86.2935317577421586],"hsluv":[116.119599614249481,84.5822993375075924,86.2935317577421586]},"#99ee66":{"lch":[86.4441689863048879,90.1009507230509143,117.805124209421223],"luv":[86.4441689863048879,-42.0290075887870955,79.6978283411745565],"rgb":[0.6,0.933333333333333348,0.4],"xyz":[0.461077906816457,0.688791475903557382,0.234364037324118091],"hpluv":[117.805124209421223,291.090686380889622,86.4441689863048879],"hsluv":[117.805124209421223,77.7887546135139587,86.4441689863048879]},"#99ee77":{"lch":[86.6285404402691199,83.3280712532883712,120.117619079442107],"luv":[86.6285404402691199,-41.8120893585486826,72.0785449510868261],"rgb":[0.6,0.933333333333333348,0.466666666666666674],"xyz":[0.470391919836658901,0.692517081111638233,0.283417839230516],"hpluv":[120.117619079442107,273.344218704658658,86.6285404402691199],"hsluv":[120.117619079442107,69.7211272565473,86.6285404402691199]},"#99ee88":{"lch":[86.8481992617441563,75.7142340291470646,123.296374810060541],"luv":[86.8481992617441563,-41.5648380664255939,63.2851441582641],"rgb":[0.6,0.933333333333333348,0.533333333333333326],"xyz":[0.481532336938602701,0.696973247952415775,0.342090702634088195],"hpluv":[123.296374810060541,252.981665625798911,86.8481992617441563],"hsluv":[123.296374810060541,60.4476982156994964,86.8481992617441563]},"#99ee99":{"lch":[87.1044587056640864,67.4980907628946483,127.715012949238613],"luv":[87.1044587056640864,-41.2908999939099388,53.3952604107227131],"rgb":[0.6,0.933333333333333348,0.6],"xyz":[0.4945893010476754,0.702196033596045,0.410857380275206074],"hpluv":[127.715012949238613,230.504268403717248,87.1044587056640864],"hsluv":[127.715012949238613,50.0680020008431583,87.1044587056640864]},"#99eeaa":{"lch":[87.3984122167822477,59.0554460818204134,133.961345837807],"luv":[87.3984122167822477,-40.9946911699179566,42.5085992218733182],"rgb":[0.6,0.933333333333333348,0.66666666666666663],"xyz":[0.509646994012928,0.708219110782146,0.490161229892204675],"hpluv":[133.961345837807,206.883546406693341,87.3984122167822477],"hsluv":[133.961345837807,51.4281429353489514,87.3984122167822477]},"#99eebb":{"lch":[87.7309483141988409,50.9899623050450046,142.923108379062683],"luv":[87.7309483141988409,-40.6811762109167603,30.7411476358032338],"rgb":[0.6,0.933333333333333348,0.733333333333333282],"xyz":[0.526784586120264575,0.715074147625080814,0.580419214990846477],"hpluv":[142.923108379062683,183.977628608542716,87.7309483141988409],"hsluv":[142.923108379062683,52.8887094272277523,87.7309483141988409]},"#99eecc":{"lch":[88.1027624984453581,44.2777406304916781,155.702396707036257],"luv":[88.1027624984453581,-40.3556400464907483,18.219237958245273],"rgb":[0.6,0.933333333333333348,0.8],"xyz":[0.546076961563986329,0.722791097802569671,0.682025725661116633],"hpluv":[155.702396707036257,165.259943503195302,88.1027624984453581],"hsluv":[155.702396707036257,54.4312604691531305,88.1027624984453581]},"#99eedd":{"lch":[88.514367527899708,40.3437945821223494,172.775068456479858],"luv":[88.514367527899708,-40.023467685182176,5.07383442158517628],"rgb":[0.6,0.933333333333333348,0.866666666666666696],"xyz":[0.567595287114619929,0.731398428022823177,0.795355573561122631],"hpluv":[172.775068456479858,156.503534311163719,88.514367527899708],"hsluv":[172.775068456479858,56.0368199873083199,88.514367527899708]},"#99eeee":{"lch":[88.9661029048661476,40.6035054290346196,192.177050630060762],"luv":[88.9661029048661476,-39.6899452486728,-8.56463071492281891],"rgb":[0.6,0.933333333333333348,0.933333333333333348],"xyz":[0.591407467380794638,0.740923300129293194,0.920766389629645854],"hpluv":[192.177050630060762,164.568757380081195,88.9661029048661476],"hsluv":[192.177050630060762,57.6866071933722324,88.9661029048661476]},"#99eeff":{"lch":[89.4581440962481338,45.3723498615675496,209.831659516829347],"luv":[89.4581440962481338,-39.3600920674606272,-22.5706287994267498],"rgb":[0.6,0.933333333333333348,1],"xyz":[0.617578515790626059,0.751391719493225918,1.05860057792142759],"hpluv":[209.831659516829347,193.255751503994162,89.4581440962481338],"hsluv":[209.831659516829347,99.9999999999917293,89.4581440962481338]},"#446600":{"lch":[39.1245088935371612,48.4489514943966242,110.29724752770484],"luv":[39.1245088935371612,-16.806485623906017,45.4405429311736668],"rgb":[0.266666666666666663,0.4,0],"xyz":[0.0713500585462719106,0.107314951185536064,0.0169546366210883669],"hpluv":[110.29724752770484,157.13568029472475,39.1245088935371612],"hsluv":[110.29724752770484,100.000000000002302,39.1245088935371612]},"#446611":{"lch":[39.1937103273453289,46.0071342898824156,111.370502443062165],"luv":[39.1937103273453289,-16.7648801632844737,42.843846683952],"rgb":[0.266666666666666663,0.4,0.0666666666666666657],"xyz":[0.0723617240459090288,0.107719617385390917,0.022282741585844],"hpluv":[111.370502443062165,148.9526145018813,39.1937103273453289],"hsluv":[111.370502443062165,93.861989786091,39.1937103273453289]},"#446622":{"lch":[39.3215343087732165,41.6757739733598,113.610346420587263],"luv":[39.3215343087732165,-16.6917518579939177,38.1871124358693947],"rgb":[0.266666666666666663,0.4,0.133333333333333331],"xyz":[0.0742370821843860579,0.108469760640781732,0.0321596277818231926],"hpluv":[113.610346420587263,134.490790122462073,39.3215343087732165],"hsluv":[113.610346420587263,82.9003633409612,39.3215343087732165]},"#446633":{"lch":[39.530716823468623,35.0960892868442684,118.194686061271412],"luv":[39.530716823468623,-16.5818151114938139,30.931842668007679],"rgb":[0.266666666666666663,0.4,0.2],"xyz":[0.0773248329168437915,0.109704860933764844,0.0484217816394343359],"hpluv":[118.194686061271412,112.658344014206364,39.530716823468623],"hsluv":[118.194686061271412,65.945418212904,39.530716823468623]},"#446644":{"lch":[39.8299759493166761,26.8801274380109838,127.715012949238059],"luv":[39.8299759493166761,-16.4434970133495142,21.2638815143349724],"rgb":[0.266666666666666663,0.4,0.266666666666666663],"xyz":[0.0817828281610626651,0.111488059031452424,0.0719005565923209744],"hpluv":[127.715012949238059,85.6368345314009,39.8299759493166761],"hsluv":[127.715012949238059,43.6044123282566858,39.8299759493166761]},"#446655":{"lch":[40.2252775564066809,18.9132283301115756,149.466153210293243],"luv":[40.2252775564066809,-16.2905155992652197,9.6088140463343148],"rgb":[0.266666666666666663,0.4,0.333333333333333315],"xyz":[0.087745242200424664,0.113873024647197257,0.10330260386629489],"hpluv":[149.466153210293243,59.6631175613842473,40.2252775564066809],"hsluv":[149.466153210293243,47.2452022491104273,40.2252775564066809]},"#446666":{"lch":[40.7202569602655728,16.510473073285187,192.177050630060847],"luv":[40.7202569602655728,-16.1389950297194247,-3.48260829470770128],"rgb":[0.266666666666666663,0.4,0.4],"xyz":[0.0953302379739328354,0.116907022956600576,0.143250248273438852],"hpluv":[192.177050630060847,51.4503500463259655,40.7202569602655728],"hsluv":[192.177050630060847,51.2489582821824214,40.7202569602655728]},"#446677":{"lch":[41.3164898648363632,23.6752994583974647,227.46784435344162],"luv":[41.3164898648363632,-16.0045942322577233,-17.4462823519963166],"rgb":[0.266666666666666663,0.4,0.466666666666666674],"xyz":[0.104644250994134755,0.120632628164681385,0.192304050179836761],"hpluv":[227.46784435344162,72.7128872034151783,41.3164898648363632],"hsluv":[227.46784435344162,55.4049423234493261,41.3164898648363632]},"#446688":{"lch":[42.0137303768536654,35.5424939627414,243.425378218088099],"luv":[42.0137303768536654,-15.9003964812462133,-31.7875175002811758],"rgb":[0.266666666666666663,0.4,0.533333333333333326],"xyz":[0.115784668096078583,0.125088795005458969,0.2509769135834089],"hpluv":[243.425378218088099,107.348500116853913,42.0137303768536654],"hsluv":[243.425378218088099,59.5313600522085409,42.0137303768536654]},"#446699":{"lch":[42.8101553746289696,48.7666560663799089,251.050944767945737],"luv":[42.8101553746289696,-15.8358652521886238,-46.1238779333558782],"rgb":[0.266666666666666663,0.4,0.6],"xyz":[0.128841632205151296,0.130311580649088155,0.319743591224526835],"hpluv":[251.050944767945737,144.549135771893674,42.8101553746289696],"hsluv":[251.050944767945737,63.4907652576423231,42.8101553746289696]},"#4466aa":{"lch":[43.7026231888915078,62.2363741998113298,255.27738032783347],"luv":[43.7026231888915078,-15.8167390859625119,-60.1929982491778404],"rgb":[0.266666666666666663,0.4,0.66666666666666663],"xyz":[0.143899325170403825,0.136334657835189249,0.399047440841525436],"hpluv":[255.27738032783347,180.707469421570693,43.7026231888915078],"hsluv":[255.27738032783347,67.1924648453768896,43.7026231888915078]},"#4466bb":{"lch":[44.6869405362706402,75.5191451090451409,257.888120209084718],"luv":[44.6869405362706402,-15.8455247037125186,-73.83807029483539],"rgb":[0.266666666666666663,0.4,0.733333333333333282],"xyz":[0.161036917277740499,0.143189694678124,0.489305425940167182],"hpluv":[257.888120209084718,214.444923406304468,44.6869405362706402],"hsluv":[257.888120209084718,70.5866413561882098,44.6869405362706402]},"#4466cc":{"lch":[45.7581261645645299,88.428992560325014,259.626929599743789],"luv":[45.7581261645645299,-15.9222446749778896,-86.983727499712],"rgb":[0.266666666666666663,0.4,0.8],"xyz":[0.180329292721462225,0.150906644855612809,0.590911936610437283],"hpluv":[259.626929599743789,245.225581131482073,45.7581261645645299],"hsluv":[259.626929599743789,73.6549291646736179,45.7581261645645299]},"#4466dd":{"lch":[46.9106590907269165,100.895184366494064,260.849495088158733],"luv":[46.9106590907269165,-16.0451985527389489,-99.6111933055317422],"rgb":[0.266666666666666663,0.4,0.866666666666666696],"xyz":[0.201847618272095769,0.159513975075866343,0.704241784510443281],"hpluv":[260.849495088158733,272.92180192815988,46.9106590907269165],"hsluv":[260.849495088158733,78.541907894368677,46.9106590907269165]},"#4466ee":{"lch":[48.1387014995781897,112.90717489320852,261.744736192665698],"luv":[48.1387014995781897,-16.2116120228509466,-111.737253313235385],"rgb":[0.266666666666666663,0.4,0.933333333333333348],"xyz":[0.225659798538270506,0.16903884718233636,0.829652600578966504],"hpluv":[261.744736192665698,297.623004098842955,48.1387014995781897],"hsluv":[261.744736192665698,89.2025828989012126,48.1387014995781897]},"#4466ff":{"lch":[49.4362898036433194,124.485902067172418,262.421323096893047],"luv":[49.4362898036433194,-16.4181334215125325,-123.398479360286501],"rgb":[0.266666666666666663,0.4,1],"xyz":[0.251830846948101872,0.179507266546269084,0.967486788870748349],"hpluv":[262.421323096893047,319.531462910383539,49.4362898036433194],"hsluv":[262.421323096893047,99.9999999999992,49.4362898036433194]},"#bbee00":{"lch":[87.830324097455545,103.474670767003104,103.901308289378321],"luv":[87.830324097455545,-24.8598111448325625,100.444000717728017],"rgb":[0.733333333333333282,0.933333333333333348,0],"xyz":[0.510662561968970863,0.717131271962896388,0.111516777292713254],"hpluv":[103.901308289378321,376.707439149390723,87.830324097455545],"hsluv":[103.901308289378321,100.000000000002331,87.830324097455545]},"#bbee11":{"lch":[87.8498503793181413,102.621932764236291,104.023160127863235],"luv":[87.8498503793181413,-24.8667401733108697,99.5635792718425705],"rgb":[0.733333333333333282,0.933333333333333348,0.0666666666666666657],"xyz":[0.511674227468608,0.717535938162751297,0.116844882257468891],"hpluv":[104.023160127863235,374.263941750279344,87.8498503793181413],"hsluv":[104.023160127863235,99.0733759990956315,87.8498503793181413]},"#bbee22":{"lch":[87.8860274909110757,101.050540606732312,104.253301125000391],"luv":[87.8860274909110757,-24.8795662288424886,97.9398741125263],"rgb":[0.733333333333333282,0.933333333333333348,0.133333333333333331],"xyz":[0.513549585607085,0.718286081418142097,0.126721768453448069],"hpluv":[104.253301125000391,369.744422226518111,87.8860274909110757],"hsluv":[104.253301125000391,97.3653524759520224,87.8860274909110757]},"#bbee33":{"lch":[87.9455377581158899,98.4895893313188111,104.644745385959411],"luv":[87.9455377581158899,-24.9006321902472507,95.2898615970127878],"rgb":[0.733333333333333282,0.933333333333333348,0.2],"xyz":[0.516637336339542785,0.719521181711125224,0.142983922311059219],"hpluv":[104.644745385959411,362.331462484484575,87.9455377581158899],"hsluv":[104.644745385959411,94.5802259429375454,87.9455377581158899]},"#bbee44":{"lch":[88.03133674845418,94.8494424101932339,105.239087045756335],"luv":[88.03133674845418,-24.9309340294718567,91.5142898892991781],"rgb":[0.733333333333333282,0.933333333333333348,0.266666666666666663],"xyz":[0.521095331583761645,0.72130437980881279,0.166462697263945858],"hpluv":[105.239087045756335,351.690778632920285,88.03133674845418],"hsluv":[105.239087045756335,90.61757843521751,88.03133674845418]},"#bbee55":{"lch":[88.145869167101,90.085489786575252,106.092871571181419],"luv":[88.145869167101,-24.9712578135623886,86.5553681367929499],"rgb":[0.733333333333333282,0.933333333333333348,0.333333333333333315],"xyz":[0.527057745623123575,0.72368934542455754,0.197864744537919773],"hpluv":[106.092871571181419,337.573290416608245,88.145869167101],"hsluv":[106.092871571181419,85.422816781051381,88.145869167101]},"#bbee66":{"lch":[88.2912067804751786,84.1961694748550116,107.288882190620882],"luv":[88.2912067804751786,-25.0222263001917433,80.3920589686599527],"rgb":[0.733333333333333282,0.933333333333333348,0.4],"xyz":[0.534642741396631815,0.726723343733960858,0.237812388945063735],"hpluv":[107.288882190620882,319.804166688067426,88.2912067804751786],"hsluv":[107.288882190620882,78.9823949944632631,88.2912067804751786]},"#bbee77":{"lch":[88.4691221578712828,77.2243366572971439,108.954917992899311],"luv":[88.4691221578712828,-25.0843250262429365,73.0368044901840534],"rgb":[0.733333333333333282,0.933333333333333348,0.466666666666666674],"xyz":[0.543956754416833665,0.730448948942041709,0.286866190851461644],"hpluv":[108.954917992899311,298.285685525501094,88.4691221578712828],"hsluv":[108.954917992899311,71.3203705839542,88.4691221578712828]},"#bbee88":{"lch":[88.6811325759484106,69.2626802552854599,111.298371855766348],"luv":[88.6811325759484106,-25.1579200624522237,64.5321465184381822],"rgb":[0.733333333333333282,0.933333333333333348,0.533333333333333326],"xyz":[0.555097171518777577,0.734905115782819252,0.34553905425503384],"hpluv":[111.298371855766348,273.019747479454225,88.6811325759484106],"hsluv":[111.298371855766348,62.4946759175697224,88.6811325759484106]},"#bbee99":{"lch":[88.9285282571087095,60.4678989000773228,114.674688063820184],"luv":[88.9285282571087095,-25.2432722518949362,54.9467378777547069],"rgb":[0.733333333333333282,0.933333333333333348,0.6],"xyz":[0.568154135627850221,0.740127901426448465,0.414305731896151719],"hpluv":[114.674688063820184,244.173567048365754,88.9285282571087095],"hsluv":[114.674688063820184,52.5925914284503548,88.9285282571087095]},"#bbeeaa":{"lch":[89.2123917942545148,51.0969811847688931,119.731125412935242],"luv":[89.2123917942545148,-25.3405499711494109,44.3706886734509212],"rgb":[0.733333333333333282,0.933333333333333348,0.66666666666666663],"xyz":[0.583211828593102832,0.746150978612549531,0.493609581513150319],"hpluv":[119.731125412935242,212.254877789093854,89.2123917942545148],"hsluv":[119.731125412935242,41.7253920748903084,89.2123917942545148]},"#bbeebb":{"lch":[89.5336124490095,41.6027669810227181,127.715012949236097],"luv":[89.5336124490095,-25.4498411950279184,32.9104208971130276],"rgb":[0.733333333333333282,0.933333333333333348,0.733333333333333282],"xyz":[0.600349420700439396,0.75300601545548429,0.583867566611792066],"hpluv":[127.715012949236097,178.587287563939924,89.5336124490095],"hsluv":[127.715012949236097,37.7465419844818,89.5336124490095]},"#bbeecc":{"lch":[89.8928974614309766,32.8889663829363883,141.03222670888556],"luv":[89.8928974614309766,-25.571165029146556,20.6833176446640721],"rgb":[0.733333333333333282,0.933333333333333348,0.8],"xyz":[0.61964179614416115,0.760722965632973147,0.685474077282062222],"hpluv":[141.03222670888556,146.627829178506289,89.8928974614309766],"hsluv":[141.03222670888556,37.1073685119788,89.8928974614309766]},"#bbeedd":{"lch":[90.290781675649967,26.8655052232995288,163.094148385079734],"luv":[90.290781675649967,-25.704482585445124,7.81248653872008436],"rgb":[0.733333333333333282,0.933333333333333348,0.866666666666666696],"xyz":[0.641160121694794749,0.769330295853226653,0.79880392518206822],"hpluv":[163.094148385079734,125.084011642469022,90.290781675649967],"hsluv":[163.094148385079734,36.2429238875219255,90.290781675649967]},"#bbeeee":{"lch":[90.7276363011350782,26.4447005646089579,192.177050630060336],"luv":[90.7276363011350782,-25.8497069757021904,-5.5780675168164624],"rgb":[0.733333333333333282,0.933333333333333348,0.933333333333333348],"xyz":[0.664972301960969459,0.77885516795969667,0.924214741250591443],"hpluv":[192.177050630060336,129.38009793870765,90.7276363011350782],"hsluv":[192.177050630060336,36.8413123479339077,90.7276363011350782]},"#bbeeff":{"lch":[91.2036773284388289,32.4261328799939648,216.675663960190036],"luv":[91.2036773284388289,-26.0067122100428421,-19.367627980086624],"rgb":[0.733333333333333282,0.933333333333333348,1],"xyz":[0.69114335037080088,0.789323587323629394,1.06204892954237318],"hpluv":[216.675663960190036,167.86892764061264,91.2036773284388289],"hsluv":[216.675663960190036,99.9999999999901235,91.2036773284388289]},"#99ff00":{"lch":[90.9122626200542214,118.290950299530564,115.261698016578393],"luv":[90.9122626200542214,-50.4810643573161286,106.978554225220847],"rgb":[0.6,1,0],"xyz":[0.48895009981846993,0.782904148991842,0.125352549814991721],"hpluv":[115.261698016578393,591.369219456757151,90.9122626200542214],"hsluv":[115.261698016578393,100.000000000002402,90.9122626200542214]},"#99ff11":{"lch":[90.9306796583728,117.513960007406183,115.422432906031332],"luv":[90.9306796583728,-50.4474247175277384,106.134764031356056],"rgb":[0.6,1,0.0666666666666666657],"xyz":[0.489961765318107034,0.783308815191696928,0.130680654779747357],"hpluv":[115.422432906031332,588.764777700997797,90.9306796583728],"hsluv":[115.422432906031332,99.9999999999905356,90.9306796583728]},"#99ff22":{"lch":[90.9648031673089577,116.082935310332914,115.724658723180369],"luv":[90.9648031673089577,-50.3854319755480944,104.577990585497247],"rgb":[0.6,1,0.133333333333333331],"xyz":[0.491837123456584091,0.784058958447087728,0.140557540975726536],"hpluv":[115.724658723180369,583.951350293788323,90.9648031673089577],"hsluv":[115.724658723180369,99.9999999999904219,90.9648031673089577]},"#99ff33":{"lch":[91.0209396556716399,113.753057852482627,116.234667099004312],"luv":[91.0209396556716399,-50.2843870930134642,102.035477092383132],"rgb":[0.6,1,0.2],"xyz":[0.494924874189041797,0.785294058740070855,0.156819694833337686],"hpluv":[116.234667099004312,576.067585056329449,91.0209396556716399],"hsluv":[116.234667099004312,99.9999999999905924,91.0209396556716399]},"#99ff44":{"lch":[91.1018839706868562,110.446777199697451,116.999375135233294],"luv":[91.1018839706868562,-50.1407143313292565,98.409345898362929],"rgb":[0.6,1,0.266666666666666663],"xyz":[0.499382869433260712,0.787077256837758421,0.180298469786224325],"hpluv":[116.999375135233294,564.777897061868,91.1018839706868562],"hsluv":[116.999375135233294,99.9999999999903793,91.1018839706868562]},"#99ff55":{"lch":[91.2099533036034558,106.130684884370282,118.07780645420398],"luv":[91.2099533036034558,-49.9525457622324112,93.6400846106921279],"rgb":[0.6,1,0.333333333333333315],"xyz":[0.505345283472622642,0.789462222453503171,0.21170051706019824],"hpluv":[118.07780645420398,549.854625367801646,91.2099533036034558],"hsluv":[118.07780645420398,99.9999999999901377,91.2099533036034558]},"#99ff66":{"lch":[91.3471179899501351,100.815112661229691,119.549522622156928],"luv":[91.3471179899501351,-49.7195590247369807,87.7020660605103899],"rgb":[0.6,1,0.4],"xyz":[0.512930279246130882,0.792496220762906489,0.251648161467342202],"hpluv":[119.549522622156928,531.176396965461777,91.3471179899501351],"hsluv":[119.549522622156928,99.9999999999902656,91.3471179899501351]},"#99ff77":{"lch":[91.5150716426202,94.5571579863012488,121.52621580287979],"luv":[91.5150716426202,-49.442863485124569,80.6006164792656534],"rgb":[0.6,1,0.466666666666666674],"xyz":[0.522244292266332732,0.79622182597098734,0.300701963373740111],"hpluv":[121.52621580287979,508.746904082031563,91.5150716426202],"hsluv":[121.52621580287979,99.9999999999900098,91.5150716426202]},"#99ff88":{"lch":[91.7152730008064481,87.4673964918121385,124.169042550433474],"luv":[91.7152730008064481,-49.1248751175299461,72.3691377159004077],"rgb":[0.6,1,0.533333333333333326],"xyz":[0.533384709368276644,0.800677992811764883,0.359374826777312251],"hpluv":[124.169042550433474,482.74240688111388,91.7152730008064481],"hsluv":[124.169042550433474,99.999999999989754,91.7152730008064481]},"#99ff99":{"lch":[91.9489728509177,79.7227767672504,127.715012949239039],"luv":[91.9489728509177,-48.7691602166467675,63.0657604984184559],"rgb":[0.6,1,0.6],"xyz":[0.546441673477349288,0.805900778455394096,0.428141504418430185],"hpluv":[127.715012949239039,453.611771943482722,91.9489728509177],"hsluv":[127.715012949239039,99.9999999999896119,91.9489728509177]},"#99ffaa":{"lch":[92.2172324754492365,71.5909188251234525,132.515331265000469],"luv":[92.2172324754492365,-48.380245540777544,52.769418223432119],"rgb":[0.6,1,0.66666666666666663],"xyz":[0.561499366442601899,0.811923855641495162,0.507445354035428786],"hpluv":[132.515331265000469,422.278899597361089,92.2172324754492365],"hsluv":[132.515331265000469,99.999999999989285,92.2172324754492365]},"#99ffbb":{"lch":[92.5209371039878334,63.4744472180726902,139.080731133451],"luv":[92.5209371039878334,-47.9634018094000325,41.5754439123617558],"rgb":[0.6,1,0.733333333333333282],"xyz":[0.578636958549938463,0.818778892484429921,0.597703339134070477],"hpluv":[139.080731133451,390.542311531215887,92.5209371039878334],"hsluv":[139.080731133451,99.9999999999889866,92.5209371039878334]},"#99ffcc":{"lch":[92.8608063839845,55.9838497302527216,148.091690615728766],"luv":[92.8608063839845,-47.524412431304512,29.5909049148346774],"rgb":[0.6,1,0.8],"xyz":[0.597929333993660217,0.826495842661918778,0.699309849804340633],"hpluv":[148.091690615728766,361.818313682118117,92.8608063839845],"hsluv":[148.091690615728766,99.999999999988475,92.8608063839845]},"#99ffdd":{"lch":[93.237403107538583,50.0214511206169306,160.217319691395858],"luv":[93.237403107538583,-47.0693412211659066,16.9299347080170577],"rgb":[0.6,1,0.866666666666666696],"xyz":[0.619447659544293816,0.835103172882172284,0.812639697704346631],"hpluv":[160.217319691395858,342.295010089686684,93.237403107538583],"hsluv":[160.217319691395858,99.999999999988,93.237403107538583]},"#99ffee":{"lch":[93.6511409780710267,46.7516947594382444,175.449324589633676],"luv":[93.6511409780710267,-46.6043124006013088,3.70931645277729727],"rgb":[0.6,1,0.933333333333333348],"xyz":[0.643259839810468526,0.844628044988642301,0.938050513772869854],"hpluv":[175.449324589633676,341.869484566500148,93.6511409780710267],"hsluv":[175.449324589633676,99.9999999999875,93.6511409780710267]},"#99ffff":{"lch":[94.102291921527609,47.1972299789563579,192.177050630060847],"luv":[94.102291921527609,-46.1353140316371437,-9.95546668362271703],"rgb":[0.6,1,1],"xyz":[0.6694308882203,0.855096464352575,1.07588470206465181],"hpluv":[192.177050630060847,372.830957625984183,94.102291921527609],"hsluv":[192.177050630060847,99.999999999986585,94.102291921527609]},"#447700":{"lch":[44.83248944102629,58.4741115144389809,115.479055163134589],"luv":[44.83248944102629,-25.1544589141716,52.7870714677211339],"rgb":[0.266666666666666663,0.466666666666666674,0],"xyz":[0.0898037965996895393,0.144222427292371835,0.0231058826388940708],"hpluv":[115.479055163134589,165.50461307776385,44.83248944102629],"hsluv":[115.479055163134589,100.00000000000216,44.83248944102629]},"#447711":{"lch":[44.8893318820142468,56.4264635629906337,116.3750363045054],"luv":[44.8893318820142468,-25.0671673404006405,50.5527735317644158],"rgb":[0.266666666666666663,0.466666666666666674,0.0666666666666666657],"xyz":[0.0908154620993266576,0.144627093492226688,0.0284339876036497],"hpluv":[116.3750363045054,159.506732057184706,44.8893318820142468],"hsluv":[116.3750363045054,95.4073228169634433,44.8893318820142468]},"#447722":{"lch":[44.9944227930058389,52.7636609180533824,118.171656995978211],"luv":[44.9944227930058389,-24.9105023189221484,46.5131248971114388],"rgb":[0.266666666666666663,0.466666666666666674,0.133333333333333331],"xyz":[0.0926908202378036866,0.145377236747617516,0.0383108737996289],"hpluv":[118.171656995978211,148.804327803607492,44.9944227930058389],"hsluv":[118.171656995978211,87.128369469673089,44.9944227930058389]},"#447733":{"lch":[45.1666686690004795,47.1090234718488,121.574089601592789],"luv":[45.1666686690004795,-24.6663168629185812,40.1351828809748881],"rgb":[0.266666666666666663,0.466666666666666674,0.2],"xyz":[0.0957785709702614202,0.146612337040600615,0.0545730276572400433],"hpluv":[121.574089601592789,132.350433634303585,45.1666686690004795],"hsluv":[121.574089601592789,74.1245535442141232,45.1666686690004795]},"#447744":{"lch":[45.4136534494367368,39.7908238780444137,127.715012949239082],"luv":[45.4136534494367368,-24.3414133770851677,31.4770592606648769],"rgb":[0.266666666666666663,0.466666666666666674,0.266666666666666663],"xyz":[0.100236566214480294,0.148395535138288209,0.0780518026101266749],"hpluv":[127.715012949239082,111.18234158710581,45.4136534494367368],"hsluv":[127.715012949239082,56.6116285441109,45.4136534494367368]},"#447755":{"lch":[45.7409133262359902,31.7219583115713704,139.030718806592802],"luv":[45.7409133262359902,-23.9520203549447466,20.798638417872084],"rgb":[0.266666666666666663,0.466666666666666674,0.333333333333333315],"xyz":[0.106198980253842293,0.150780500754033042,0.10945384988410059],"hpluv":[139.030718806592802,88.0023935360314766,45.7409133262359902],"hsluv":[139.030718806592802,58.7992252631310066,45.7409133262359902]},"#447766":{"lch":[46.1522822994750328,25.0075472636366349,160.141849635166039],"luv":[46.1522822994750328,-23.5205108300662609,8.49488024846472],"rgb":[0.266666666666666663,0.466666666666666674,0.4],"xyz":[0.113783976027350464,0.153814499063436333,0.149401494291244552],"hpluv":[160.141849635166039,68.7570511480334,46.1522822994750328],"hsluv":[160.141849635166039,61.2825519214888672,46.1522822994750328]},"#447777":{"lch":[46.650089933282672,23.6026970305602966,192.177050630060933],"luv":[46.650089933282672,-23.0716472128555,-4.97859438013953248],"rgb":[0.266666666666666663,0.466666666666666674,0.466666666666666674],"xyz":[0.123097989047552384,0.157540104271517156,0.198455296197642461],"hpluv":[192.177050630060933,64.2019875277067,46.650089933282672],"hsluv":[192.177050630060933,63.9506821134950414,46.650089933282672]},"#447788":{"lch":[47.2353114433284134,29.6592888392359697,220.273189901853613],"luv":[47.2353114433284134,-22.6291741496980734,-19.1727382434503575],"rgb":[0.266666666666666663,0.466666666666666674,0.533333333333333326],"xyz":[0.134238406149496226,0.161996271112294754,0.257128159601214601],"hpluv":[220.273189901853613,79.6770556088496,47.2353114433284134],"hsluv":[220.273189901853613,66.6958169909158585,47.2353114433284134]},"#447799":{"lch":[47.9077085122244526,40.3569508451274856,236.603980798736757],"luv":[47.9077085122244526,-22.2133832668581981,-33.6934576046404],"rgb":[0.266666666666666663,0.466666666666666674,0.6],"xyz":[0.147295370258568925,0.167219056755923912,0.325894837242332536],"hpluv":[236.603980798736757,106.893740352524901,47.9077085122244526],"hsluv":[236.603980798736757,69.4246608010291197,47.9077085122244526]},"#4477aa":{"lch":[48.6659751090485,52.9419227285019574,245.636459716194196],"luv":[48.6659751090485,-21.8398581964299439,-48.2272513849846476],"rgb":[0.266666666666666663,0.466666666666666674,0.66666666666666663],"xyz":[0.162353063223821481,0.173242133942025,0.405198686859331136],"hpluv":[245.636459716194196,138.042751347741245,48.6659751090485],"hsluv":[245.636459716194196,72.0643617009564,48.6659751090485]},"#4477bb":{"lch":[49.5078912458612,66.145388752002,251.014275727268966],"luv":[49.5078912458612,-21.5192486824625604,-62.5470573991759125],"rgb":[0.266666666666666663,0.466666666666666674,0.733333333333333282],"xyz":[0.1794906553311581,0.180097170784959765,0.495456671957972883],"hpluv":[251.014275727268966,169.536991245322184,49.5078912458612],"hsluv":[251.014275727268966,74.5637193650047578,49.5078912458612]},"#4477cc":{"lch":[50.4304819457797606,79.4031370336833,254.471410742848605],"luv":[50.4304819457797606,-21.2577420931439356,-76.5046833330565761],"rgb":[0.266666666666666663,0.466666666666666674,0.8],"xyz":[0.198783030774879854,0.187814120962448566,0.597063182628243094],"hpluv":[254.471410742848605,199.794656417231295,50.4304819457797606],"hsluv":[254.471410742848605,76.8911855438839638,50.4304819457797606]},"#4477dd":{"lch":[51.4301761714764183,92.4467030892661654,256.833353640671476],"luv":[51.4301761714764183,-21.0578873175855144,-90.0164334652001514],"rgb":[0.266666666666666663,0.466666666666666674,0.866666666666666696],"xyz":[0.220301356325513398,0.1964214511827021,0.710393030528249092],"hpluv":[256.833353640671476,228.093412194404408,51.4301761714764183],"hsluv":[256.833353640671476,79.0312420746427904,51.4301761714764183]},"#4477ee":{"lch":[52.5029598761355913,105.148975578657073,258.524369979875587],"luv":[52.5029598761355913,-20.9195063280493,-103.046985983248078],"rgb":[0.266666666666666663,0.466666666666666674,0.933333333333333348],"xyz":[0.244113536591688135,0.205946323289172145,0.835803846596772315],"hpluv":[258.524369979875587,254.132720010738154,52.5029598761355913],"hsluv":[258.524369979875587,87.6254974090696,52.5029598761355913]},"#4477ff":{"lch":[53.6445179522116,117.458222301342076,259.779939364455799],"luv":[53.6445179522116,-20.8405325230258285,-115.594576820663164],"rgb":[0.266666666666666663,0.466666666666666674,1],"xyz":[0.270284585001519528,0.216414742653104841,0.973638034888554],"hpluv":[259.779939364455799,277.841684308431127,53.6445179522116],"hsluv":[259.779939364455799,99.999999999999,53.6445179522116]},"#bbff00":{"lch":[92.6117448358007778,112.09772632761252,107.605046807390437],"luv":[92.6117448358007778,-33.9043888880720843,106.847520616749406],"rgb":[0.733333333333333282,1,0],"xyz":[0.56251493439864475,0.820836016822245496,0.128800901435937365],"hpluv":[107.605046807390437,698.685604225905081,92.6117448358007778],"hsluv":[107.605046807390437,100.000000000002302,92.6117448358007778]},"#bbff11":{"lch":[92.6295901709342,111.320425805292416,107.729052066712285],"luv":[92.6295901709342,-33.8988588935206678,106.033506813595423],"rgb":[0.733333333333333282,1,0.0666666666666666657],"xyz":[0.56352659989828191,0.821240683022100404,0.134129006400693],"hpluv":[107.729052066712285,695.618439183936061,92.6295901709342],"hsluv":[107.729052066712285,99.9999999999893703,92.6295901709342]},"#bbff22":{"lch":[92.6626551654141,109.887399193340656,107.962519071076329],"luv":[92.6626551654141,-33.888700280085942,104.531318248662245],"rgb":[0.733333333333333282,1,0.133333333333333331],"xyz":[0.565401958036758856,0.821990826277491204,0.14400589259667218],"hpluv":[107.962519071076329,689.937572971075,92.6626551654141],"hsluv":[107.962519071076329,99.9999999999891713,92.6626551654141]},"#bbff33":{"lch":[92.7170524122382318,107.550157892444602,108.357408717671873],"luv":[92.7170524122382318,-33.8722333827189388,102.076972272674624],"rgb":[0.733333333333333282,1,0.2],"xyz":[0.568489708769216673,0.823225926570474331,0.160268046454283331],"hpluv":[108.357408717671873,680.59767216104342,92.7170524122382318],"hsluv":[108.357408717671873,99.9999999999894271,92.7170524122382318]},"#bbff44":{"lch":[92.7954935084343475,104.224206838295117,108.951712424811362],"luv":[92.7954935084343475,-33.8490183743317,98.5744857768270464],"rgb":[0.733333333333333282,1,0.266666666666666663],"xyz":[0.572947704013435533,0.825009124668161897,0.183746821407169969],"hpluv":[108.951712424811362,667.142517523628385,92.7954935084343475],"hsluv":[108.951712424811362,99.9999999999890576,92.7954935084343475]},"#bbff55":{"lch":[92.9002292713318809,99.8647848732016,109.794505003516988],"luv":[92.9002292713318809,-33.8189779888925628,93.9640994505754605],"rgb":[0.733333333333333282,1,0.333333333333333315],"xyz":[0.578910118052797462,0.827394090283906647,0.215148868681143884],"hpluv":[109.794505003516988,649.201221057988732,92.9002292713318809],"hsluv":[109.794505003516988,99.9999999999888445,92.9002292713318809]},"#bbff66":{"lch":[93.0331768315467826,94.4651128464689691,110.953951756581517],"luv":[93.0331768315467826,-33.7823795150753,88.2179595059619146],"rgb":[0.733333333333333282,1,0.4],"xyz":[0.586495113826305703,0.83042808859331,0.255096513088287846],"hpluv":[110.953951756581517,626.470359589551208,93.0331768315467826],"hsluv":[110.953951756581517,99.9999999999888871,93.0331768315467826]},"#bbff77":{"lch":[93.1959878807374196,88.0576290523864742,112.529317332402641],"luv":[93.1959878807374196,-33.7398191848892566,81.3373876867131571],"rgb":[0.733333333333333282,1,0.466666666666666674],"xyz":[0.595809126846507553,0.834153693801390816,0.304150314994685755],"hpluv":[112.529317332402641,598.713569857690459,93.1959878807374196],"hsluv":[112.529317332402641,99.9999999999886455,93.1959878807374196]},"#bbff88":{"lch":[93.3900894470196334,80.7182094219550805,114.670873894576516],"luv":[93.3900894470196334,-33.6921989698203319,73.3502901212028888],"rgb":[0.733333333333333282,1,0.533333333333333326],"xyz":[0.606949543948451464,0.838609860642168359,0.362823178398257951],"hpluv":[114.670873894576516,565.785048639302204,93.3900894470196334],"hsluv":[114.670873894576516,99.9999999999880913,93.3900894470196334]},"#bbff99":{"lch":[93.6167101348934239,72.575742292483838,117.61482369288214],"luv":[93.6167101348934239,-33.6406927329059684,64.3081811417119411],"rgb":[0.733333333333333282,1,0.6],"xyz":[0.620006508057524108,0.843832646285797572,0.43158985603937583],"hpluv":[117.61482369288214,527.702623330867254,93.6167101348934239],"hsluv":[117.61482369288214,99.9999999999881,93.6167101348934239]},"#bbffaa":{"lch":[93.8768980816178384,63.8331941826517948,121.746607961207644],"luv":[93.8768980816178384,-33.5867019719833948,54.2826872050868303],"rgb":[0.733333333333333282,1,0.66666666666666663],"xyz":[0.63506420102277672,0.849855723471898639,0.510893705656374486],"hpluv":[121.746607961207644,484.836572610502856,93.8768980816178384],"hsluv":[121.746607961207644,99.9999999999878781,93.8768980816178384]},"#bbffbb":{"lch":[94.1715339943383,54.8143223318485937,127.715012949237362],"luv":[94.1715339943383,-33.5318032859449531,43.3615970772812602],"rgb":[0.733333333333333282,1,0.733333333333333282],"xyz":[0.652201793130113283,0.856710760314833397,0.601151690755016177],"hpluv":[127.715012949237362,438.38038704048256,94.1715339943383],"hsluv":[127.715012949237362,99.999999999986926,94.1715339943383]},"#bbffcc":{"lch":[94.5013412228876888,46.0666753200389323,136.612331153023604],"luv":[94.5013412228876888,-33.4776907719138919,31.6446329670924698],"rgb":[0.733333333333333282,1,0.8],"xyz":[0.671494168573835,0.864427710492322254,0.702758201425286333],"hpluv":[136.612331153023604,391.513584290668746,94.5013412228876888],"hsluv":[136.612331153023604,99.9999999999865707,94.5013412228876888]},"#bbffdd":{"lch":[94.8668940681869515,38.5674836948257322,150.076437256866],"luv":[94.8668940681869515,-33.4261169986321818,19.2391658068743077],"rgb":[0.733333333333333282,1,0.866666666666666696],"xyz":[0.693012494124468637,0.873035040712575761,0.816088049325292331],"hpluv":[150.076437256866,352.109825744613431,94.8668940681869515],"hsluv":[150.076437256866,99.9999999999853628,94.8668940681869515]},"#bbffee":{"lch":[95.2686250900245568,33.9600576278843675,169.384373669661102],"luv":[95.2686250900245568,-33.3788361105619771,6.25610214058809699],"rgb":[0.733333333333333282,1,0.933333333333333348],"xyz":[0.716824674390643346,0.882559912819045778,0.941498865393815554],"hpluv":[169.384373669661102,337.406400875084444,95.2686250900245568],"hsluv":[169.384373669661102,99.9999999999845,95.2686250900245568]},"#bbffff":{"lch":[95.7068319095003,34.1048965933827191,192.177050630060478],"luv":[95.7068319095003,-33.3375521201936849,-7.19385781613020914],"rgb":[0.733333333333333282,1,1],"xyz":[0.742995722800474767,0.893028332182978501,1.0793330536855974],"hpluv":[192.177050630060478,374.679972152143307,95.7068319095003],"hsluv":[192.177050630060478,99.9999999999829186,95.7068319095003]},"#448800":{"lch":[50.4956227619448157,68.4221216779621244,118.715311426014551],"luv":[50.4956227619448157,-32.873947818662586,60.0074186224478723],"rgb":[0.266666666666666663,0.533333333333333326,0],"xyz":[0.111876166324659992,0.18836716674231338,0.0304633392138840171],"hpluv":[118.715311426014551,171.942062028892252,50.4956227619448157],"hsluv":[118.715311426014551,100.000000000002373,50.4956227619448157]},"#448811":{"lch":[50.543205868460916,66.6756511812714763,119.435612575278299],"luv":[50.543205868460916,-32.7674265649617098,58.0683925794095899],"rgb":[0.266666666666666663,0.533333333333333326,0.0666666666666666657],"xyz":[0.112887831824297111,0.188771832942168233,0.0357914441786396503],"hpluv":[119.435612575278299,167.395510973175305,50.543205868460916],"hsluv":[119.435612575278299,96.4702491056824272,50.543205868460916]},"#448822":{"lch":[50.6312327062127565,63.5295563644356918,120.846986072134357],"luv":[50.6312327062127565,-32.5745953261955492,54.5426463530750425],"rgb":[0.266666666666666663,0.533333333333333326,0.133333333333333331],"xyz":[0.11476318996277414,0.189521976197559061,0.0456683303746188429],"hpluv":[120.846986072134357,159.219643782083125,50.6312327062127565],"hsluv":[120.846986072134357,90.0662104861249,50.6312327062127565]},"#448833":{"lch":[50.775662969350762,58.6076690216783831,123.408487274566809],"luv":[50.775662969350762,-32.2696404838739213,48.9237076599487182],"rgb":[0.266666666666666663,0.533333333333333326,0.2],"xyz":[0.117850940695231873,0.19075707649054216,0.0619304842322299931],"hpluv":[123.408487274566809,146.466455796741883,50.775662969350762],"hsluv":[123.408487274566809,79.8990388198805732,50.775662969350762]},"#448844":{"lch":[50.9830910358637652,52.0733509329185,127.715012949239537],"luv":[50.9830910358637652,-31.855056956676961,41.1933152789351382],"rgb":[0.266666666666666663,0.533333333333333326,0.266666666666666663],"xyz":[0.122308935939450747,0.192540274588229754,0.0854092591851166316],"hpluv":[127.715012949239537,129.607069016793787,50.9830910358637652],"hsluv":[127.715012949239537,65.9930987522981241,50.9830910358637652]},"#448855":{"lch":[51.2585265038955384,44.4350179761376651,134.860489600104756],"luv":[51.2585265038955384,-31.3437036744621551,31.4967151066136601],"rgb":[0.266666666666666663,0.533333333333333326,0.333333333333333315],"xyz":[0.128271349978812732,0.194925240203974587,0.116811306459090533],"hpluv":[134.860489600104756,110.001490313735033,51.2585265038955384],"hsluv":[134.860489600104756,67.3517725464548676,51.2585265038955384]},"#448866":{"lch":[51.6056896491522537,36.7437212642011914,146.829747927558799],"luv":[51.6056896491522537,-30.7562765884277063,20.1035445321824895],"rgb":[0.266666666666666663,0.533333333333333326,0.4],"xyz":[0.135856345752320917,0.197959238513377878,0.156758950866234509],"hpluv":[146.829747927558799,90.3493178961374781,51.6056896491522537],"hsluv":[146.829747927558799,68.9308752248562797,51.6056896491522537]},"#448877":{"lch":[52.0271709342862039,31.0045548915217921,166.266503182991642],"luv":[52.0271709342862039,-30.1181499011556575,7.36067052332227245],"rgb":[0.266666666666666663,0.533333333333333326,0.466666666666666674],"xyz":[0.145170358772522823,0.201684843721458701,0.205812752772632418],"hpluv":[166.266503182991642,75.6196418937204555,52.0271709342862039],"hsluv":[166.266503182991642,70.6726995402934506,52.0271709342862039]},"#448888":{"lch":[52.5245390493459041,30.1341009641634088,192.177050630061],"luv":[52.5245390493459041,-29.456097564679137,-6.35628485662009179],"rgb":[0.266666666666666663,0.533333333333333326,0.533333333333333326],"xyz":[0.156310775874466679,0.206141010562236299,0.264485616176204585],"hpluv":[192.177050630061,72.8006598676027181,52.5245390493459041],"hsluv":[192.177050630061,72.5156967272479847,52.5245390493459041]},"#448899":{"lch":[53.0984315279962118,35.4547108695225,215.690916113393854],"luv":[53.0984315279962118,-28.7954664423823949,-20.6847198484066084],"rgb":[0.266666666666666663,0.533333333333333326,0.6],"xyz":[0.169367739983539378,0.211363796205865456,0.333252293817322465],"hpluv":[215.690916113393854,84.7289026839812,53.0984315279962118],"hsluv":[215.690916113393854,74.4011420122721319,53.0984315279962118]},"#4488aa":{"lch":[53.7486427971268625,45.1587425535104146,231.425064236121358],"luv":[53.7486427971268625,-28.1581765792043193,-35.3048030832715654],"rgb":[0.266666666666666663,0.533333333333333326,0.66666666666666663],"xyz":[0.184425432948791934,0.217386873391966551,0.412556143434321065],"hpluv":[231.425064236121358,106.613859301848393,53.7486427971268625],"hsluv":[231.425064236121358,76.2778611087785,53.7486427971268625]},"#4488bb":{"lch":[54.4742155909258514,57.0545505189943469,241.113543257937238],"luv":[54.4742155909258514,-27.5616516575745152,-49.9557513488787208],"rgb":[0.266666666666666663,0.533333333333333326,0.733333333333333282],"xyz":[0.201563025056128553,0.224241910234901309,0.502814128532962812],"hpluv":[241.113543257937238,132.904176722924205,54.4742155909258514],"hsluv":[241.113543257937238,78.1047803623200707,54.4742155909258514]},"#4488cc":{"lch":[55.273536978614473,69.875332030770025,247.25266296501286],"luv":[55.273536978614473,-27.0185618464256976,-64.4403549195783398],"rgb":[0.266666666666666663,0.533333333333333326,0.8],"xyz":[0.220855400499850307,0.231958860412390111,0.604420639203233],"hpluv":[247.25266296501286,160.415361718249983,55.273536978614473],"hsluv":[247.25266296501286,79.8515774594708603,55.273536978614473]},"#4488dd":{"lch":[56.1444377207636194,82.97891177410213,251.348812353132246],"luv":[56.1444377207636194,-26.53714651812043,-78.6211145551246631],"rgb":[0.266666666666666663,0.533333333333333326,0.866666666666666696],"xyz":[0.242373726050483851,0.240566190632643645,0.717750487103239],"hpluv":[251.348812353132246,187.542769341675751,56.1444377207636194],"hsluv":[251.348812353132246,81.4979766670821,56.1444377207636194]},"#4488ee":{"lch":[57.0842924141545609,96.0325607902411775,254.216059778839536],"luv":[57.0842924141545609,-26.1218678035424112,-92.4115834426919776],"rgb":[0.266666666666666663,0.533333333333333326,0.933333333333333348],"xyz":[0.266185906316658616,0.25009106273911369,0.843161303171762189],"hpluv":[254.216059778839536,213.472145126724115,57.0842924141545609],"hsluv":[254.216059778839536,85.8050168900109469,57.0842924141545609]},"#4488ff":{"lch":[58.090117466996233,108.861046277687535,256.304473865935392],"luv":[58.090117466996233,-25.7741898685227575,-105.765866579412872],"rgb":[0.266666666666666663,0.533333333333333326,1],"xyz":[0.29235695472649,0.260559482103046358,0.980995491463544],"hpluv":[256.304473865935392,237.798754650411269,58.090117466996233],"hsluv":[256.304473865935392,99.9999999999988631,58.090117466996233]},"#449900":{"lch":[56.0984423000037538,78.159424491283,120.852962610827774],"luv":[56.0984423000037538,-40.0830169860907191,67.0987882610508279],"rgb":[0.266666666666666663,0.6,0],"xyz":[0.137745766777127493,0.240106367647249075,0.0390865393647062687],"hpluv":[120.852962610827774,176.794958777624345,56.0984423000037538],"hsluv":[120.852962610827774,100.000000000002416,56.0984423000037538]},"#449911":{"lch":[56.1389235634784143,76.6482268999804859,121.431666795625887],"luv":[56.1389235634784143,-39.9706170908808929,65.4010738159938256],"rgb":[0.266666666666666663,0.6,0.0666666666666666657],"xyz":[0.138757432276764625,0.240511033847103928,0.0444146443294619],"hpluv":[121.431666795625887,173.251641588156104,56.1389235634784143],"hsluv":[121.431666795625887,97.2234127009916,56.1389235634784143]},"#449922":{"lch":[56.21384509356389,73.9109075723002746,122.549403254372123],"luv":[56.21384509356389,-39.7660359546788555,62.3015621201611793],"rgb":[0.266666666666666663,0.6,0.133333333333333331],"xyz":[0.140632790415241626,0.241261177102494756,0.0542915305254411],"hpluv":[122.549403254372123,166.841685682494415,56.21384509356389],"hsluv":[122.549403254372123,92.1627352690631,56.21384509356389]},"#449933":{"lch":[56.3368647095541064,69.5846668696270143,124.526315047954697],"luv":[56.3368647095541064,-39.4395235157555177,57.3284383897480296],"rgb":[0.266666666666666663,0.6,0.2],"xyz":[0.143720541147699388,0.242496277395477855,0.0705536843830522342],"hpluv":[124.526315047954697,156.73291295139785,56.3368647095541064],"hsluv":[124.526315047954697,84.0665441712718859,56.3368647095541064]},"#449944":{"lch":[56.5137417426914368,63.7361451042890153,127.715012949239735],"luv":[56.5137417426914368,-38.9895886498958575,50.4193233757345922],"rgb":[0.266666666666666663,0.6,0.266666666666666663],"xyz":[0.148178536391918247,0.244279475493165449,0.0940324593359388727],"hpluv":[127.715012949239735,143.110354253444,56.5137417426914368],"hsluv":[127.715012949239735,72.8686777069245,56.5137417426914368]},"#449955":{"lch":[56.7489681974646629,56.6620380577650309,132.698160989074609],"luv":[56.7489681974646629,-38.4245724364924328,41.642992086692793],"rgb":[0.266666666666666663,0.6,0.333333333333333315],"xyz":[0.154140950431280233,0.246664441108910282,0.125434506609912788],"hpluv":[132.698160989074609,126.69910537289924,56.7489681974646629],"hsluv":[132.698160989074609,73.7405349232989664,56.7489681974646629]},"#449966":{"lch":[57.0460268500437166,48.9673458777373511,140.456743036678859],"luv":[57.0460268500437166,-37.7608817984154683,31.1755796757022061],"rgb":[0.266666666666666663,0.6,0.4],"xyz":[0.161725946204788418,0.249698439418313572,0.16538215101705675],"hpluv":[140.456743036678859,108.923224533285605,57.0460268500437166],"hsluv":[140.456743036678859,74.7718537787272766,57.0460268500437166]},"#449977":{"lch":[57.4075272841014481,41.7361359201695734,152.500832231763781],"luv":[57.4075272841014481,-37.0206846158697,19.2710651526888199],"rgb":[0.266666666666666663,0.6,0.466666666666666674],"xyz":[0.171039959224990323,0.253424044626394396,0.214435952923454659],"hpluv":[152.500832231763781,92.2534727828265915,57.4075272841014481],"hsluv":[152.500832231763781,75.9325502249844817,57.4075272841014481]},"#449988":{"lch":[57.8352917232380861,36.7607331244742284,170.245603374965924],"luv":[57.8352917232380861,-36.2292854489646174,6.22819200942437323],"rgb":[0.266666666666666663,0.6,0.533333333333333326],"xyz":[0.182180376326934179,0.257880211467172,0.273108816327026827],"hpluv":[170.245603374965924,80.6548633994409414,57.8352917232380861],"hsluv":[170.245603374965924,77.1878957355486222,57.8352917232380861]},"#449999":{"lch":[58.3304201548299517,36.2276744984656105,192.17705063006116],"luv":[58.3304201548299517,-35.4125684996312486,-7.64162232943372643],"rgb":[0.266666666666666663,0.6,0.6],"xyz":[0.195237340436006879,0.263102997110801151,0.341875493968144761],"hpluv":[192.17705063006116,78.8106081595615251,58.3304201548299517],"hsluv":[192.17705063006116,78.5021203184449803,58.3304201548299517]},"#4499aa":{"lch":[58.8933484328044585,41.0197173156303379,212.502133513081617],"luv":[58.8933484328044585,-34.5948579745346478,-22.041166266239177],"rgb":[0.266666666666666663,0.6,0.66666666666666663],"xyz":[0.210295033401259435,0.269126074296902273,0.421179343585143307],"hpluv":[212.502133513081617,88.3823902117899536,58.8933484328044585],"hsluv":[212.502133513081617,79.8414276244135692,58.8933484328044585]},"#4499bb":{"lch":[59.523905851944221,49.8962585520308082,227.36281958486083],"luv":[59.523905851944221,-33.7974051546762055,-36.7065664738854878],"rgb":[0.266666666666666663,0.6,0.733333333333333282],"xyz":[0.227432625508596054,0.275981111139837032,0.511437328683785108],"hpluv":[227.36281958486083,106.36919851968392,59.523905851944221],"hsluv":[227.36281958486083,81.1761313086710885,59.523905851944221]},"#4499cc":{"lch":[60.2213749252976385,61.1171242450200438,237.278146949597897],"luv":[60.2213749252976385,-33.0375484580145766,-51.4181219791773],"rgb":[0.266666666666666663,0.6,0.8],"xyz":[0.246725000952317808,0.283698061317325834,0.613043839354055264],"hpluv":[237.278146949597897,128.780934100622716,60.2213749252976385],"hsluv":[237.278146949597897,82.4818489079811741,60.2213749252976385]},"#4499dd":{"lch":[60.9845539619455508,73.4958381074912,243.904542785491344],"luv":[60.9845539619455508,-32.3284648877968195,-66.0038527445257728],"rgb":[0.266666666666666663,0.6,0.866666666666666696],"xyz":[0.268243326502951351,0.29230539153757934,0.726373687254061262],"hpluv":[243.904542785491344,152.926314240713424,60.9845539619455508],"hsluv":[243.904542785491344,83.7398679369964469,60.9845539619455508]},"#4499ee":{"lch":[61.8118218103912653,86.3580647779335351,248.479300934605874],"luv":[61.8118218103912653,-31.6793620640961606,-80.3376211460214193],"rgb":[0.266666666666666663,0.6,0.933333333333333348],"xyz":[0.292055506769126061,0.301830263644049357,0.851784503322584485],"hpluv":[248.479300934605874,177.284466220706,61.8118218103912653],"hsluv":[248.479300934605874,84.9368954206658344,61.8118218103912653]},"#4499ff":{"lch":[62.7012034705467585,99.3269113509348,251.755860244601337],"luv":[62.7012034705467585,-31.0959452870692914,-94.3338619225358173],"rgb":[0.266666666666666663,0.6,1],"xyz":[0.318226555178957482,0.312298683007982081,0.98961869161436633],"hpluv":[251.755860244601337,201.015886170810859,62.7012034705467585],"hsluv":[251.755860244601337,99.9999999999986073,62.7012034705467585]},"#330000":{"lch":[6.35863201887414942,21.3842798011123882,12.1770506300617836],"luv":[6.35863201887414942,20.9031433498234946,4.51065635013277699],"rgb":[0.2,0,0],"xyz":[0.0136521011456799905,0.00703936465324139522,0.000639942241203736136],"hpluv":[12.1770506300617836,426.746789183125031,6.35863201887414942],"hsluv":[12.1770506300617836,100.000000000002217,6.35863201887414942]},"#330011":{"lch":[6.72416549840036915,18.2596394021459751,358.956333183931122],"luv":[6.72416549840036915,18.2566101970553,-0.332588648601129133],"rgb":[0.2,0,0.0666666666666666657],"xyz":[0.0146637666453171122,0.00744403085309625,0.00596804720595936738],"hpluv":[358.956333183931122,344.582429927088697,6.72416549840036915],"hsluv":[358.956333183931122,99.9999999999970868,6.72416549840036915]},"#330022":{"lch":[7.4017671226143058,16.6083885778583671,334.642609555635659],"luv":[7.4017671226143058,15.0082373074967617,-7.11276205668364714],"rgb":[0.2,0,0.133333333333333331],"xyz":[0.0165391247837941326,0.00819417410848706854,0.0158449334019385643],"hpluv":[334.642609555635659,284.728805881674077,7.4017671226143058],"hsluv":[334.642609555635659,99.999999999998,7.4017671226143058]},"#330033":{"lch":[8.50665746950019,19.3767863388894384,307.715012949243601],"luv":[8.50665746950019,11.8534455994177517,-15.3282639670843448],"rgb":[0.2,0,0.2],"xyz":[0.0196268755162518696,0.00942927440147018139,0.0321070872595497075],"hpluv":[307.715012949243601,289.042783730483279,8.50665746950019],"hsluv":[307.715012949243601,99.9999999999987921,8.50665746950019]},"#330044":{"lch":[9.96321399083228343,25.9151774110163871,290.632214162589],"luv":[9.96321399083228343,9.13167627644372,-24.2530185467023678],"rgb":[0.2,0,0.266666666666666663],"xyz":[0.0240848707604707502,0.0112124724991577579,0.0555858622124363461],"hpluv":[290.632214162589,330.060881015257678,9.96321399083228343],"hsluv":[290.632214162589,99.9999999999994,9.96321399083228343]},"#330055":{"lch":[11.6870713271151807,34.2775786608295405,281.502617436257196],"luv":[11.6870713271151807,6.83538450996046,-33.589133919325],"rgb":[0.2,0,0.333333333333333315],"xyz":[0.0300472847998327422,0.0135974381149025891,0.0869879094864102614],"hpluv":[281.502617436257196,372.172061509357604,11.6870713271151807],"hsluv":[281.502617436257196,99.9999999999999289,11.6870713271151807]},"#330066":{"lch":[13.6097387714237676,43.4818398400869768,276.434806151814087],"luv":[13.6097387714237676,4.87312317733106592,-43.2079051375733059],"rgb":[0.2,0,0.4],"xyz":[0.0376322805733409205,0.0166314364243059024,0.126935553893554209],"hpluv":[276.434806151814087,405.412793254212261,13.6097387714237676],"hsluv":[276.434806151814087,100.00000000000027,13.6097387714237676]},"#330077":{"lch":[15.6735112457106673,53.108485659557914,273.408523183706109],"luv":[15.6735112457106673,3.15755804167271537,-53.0145364618510655],"rgb":[0.2,0,0.466666666666666674],"xyz":[0.046946293593542833,0.0203570416323867187,0.175989355799952119],"hpluv":[273.408523183706109,429.968801903614121,15.6735112457106673],"hsluv":[273.408523183706109,100.000000000000313,15.6735112457106673]},"#330088":{"lch":[17.8339183845063687,62.9511834901283365,271.47985970994057],"luv":[17.8339183845063687,1.62574911173865799,-62.9301870538574448],"rgb":[0.2,0,0.533333333333333326],"xyz":[0.058086710695486661,0.0248132084731643096,0.234662219203524286],"hpluv":[271.47985970994057,447.91587095992594,17.8339183845063687],"hsluv":[271.47985970994057,100.000000000000441,17.8339183845063687]},"#330099":{"lch":[20.0583065104412341,72.8932825114363,270.184356583024851],"luv":[20.0583065104412341,0.234543162084408924,-72.8929051746271313],"rgb":[0.2,0,0.6],"xyz":[0.0711436748045593814,0.0300359941167934706,0.303428896844642193],"hpluv":[270.184356583024851,461.139761646516433,20.0583065104412341],"hsluv":[270.184356583024851,100.000000000000625,20.0583065104412341]},"#3300aa":{"lch":[22.3232943619689834,82.8637729479105474,269.276671227287579],"luv":[22.3232943619689834,-1.04608331699459467,-82.8571697371855578],"rgb":[0.2,0,0.66666666666666663],"xyz":[0.0862013677698119235,0.0360590713028945756,0.382732746461640794],"hpluv":[269.276671227287579,471.026936966419044,22.3232943619689834],"hsluv":[269.276671227287579,100.000000000000554,22.3232943619689834]},"#3300bb":{"lch":[24.6123405885396807,92.8181896970849,268.61855571411644],"luv":[24.6123405885396807,-2.23769945956788,-92.7912120826788538],"rgb":[0.2,0,0.733333333333333282],"xyz":[0.10333895987714857,0.0429141081458293341,0.47299073156028254],"hpluv":[268.61855571411644,478.541387025058441,24.6123405885396807],"hsluv":[268.61855571411644,100.000000000000625,24.6123405885396807]},"#3300cc":{"lch":[26.9138017967000778,102.728605647013808,268.127719933063759],"luv":[26.9138017967000778,-3.35631165306985224,-102.673762910819349],"rgb":[0.2,0,0.8],"xyz":[0.122631335320870311,0.0506310583233181358,0.574597242230552752],"hpluv":[268.127719933063759,484.345947247320225,26.9138017967000778],"hsluv":[268.127719933063759,100.000000000000881,26.9138017967000778]},"#3300dd":{"lch":[29.2194977691074271,112.577730384171886,267.752877980499],"luv":[29.2194977691074271,-4.41413050162269105,-112.49115889867052],"rgb":[0.2,0,0.866666666666666696],"xyz":[0.144149660871503854,0.0592383885435716698,0.687927090130558749],"hpluv":[267.752877980499,488.89890937186334,29.2194977691074271],"hsluv":[267.752877980499,100.000000000000753,29.2194977691074271]},"#3300ee":{"lch":[31.5236887929336334,122.355215968494591,267.460804758990776],"luv":[31.5236887929336334,-5.42068013199621,-122.235081304851008],"rgb":[0.2,0,0.933333333333333348],"xyz":[0.167961841137678591,0.0687632606500417,0.813337906199082],"hpluv":[267.460804758990776,492.52103452607281,31.5236887929336334],"hsluv":[267.460804758990776,100.000000000000824,31.5236887929336334]},"#3300ff":{"lch":[33.8223579343154,132.055276159319874,267.229255072945307],"luv":[33.8223579343154,-6.38352242786170443,-131.900896899631505],"rgb":[0.2,0,1],"xyz":[0.194132889547509985,0.0792316800139744,0.951172094490863818],"hpluv":[267.229255072945307,495.440155164142311,33.8223579343154],"hsluv":[267.229255072945307,100.000000000000881,33.8223579343154]},"#331100":{"lch":[9.83576796362177319,19.9321083570360571,25.9770166386959609],"luv":[9.83576796362177319,17.918363864654,8.73047421223431108],"rgb":[0.2,0.0666666666666666657,0],"xyz":[0.0156565014066084,0.0110481651750982679,0.00130807566151318702],"hpluv":[25.9770166386959609,257.148675223584291,9.83576796362177319],"hsluv":[25.9770166386959609,100.000000000002302,9.83576796362177319]},"#331111":{"lch":[10.1474261289244687,16.4836545456174051,12.1770506300618813],"luv":[10.1474261289244687,16.1127799065782149,3.4769513746129066],"rgb":[0.2,0.0666666666666666657,0.0666666666666666657],"xyz":[0.0166681669062455212,0.0114528313749531225,0.00663618062626881826],"hpluv":[12.1770506300618813,206.127972902374523,10.1474261289244687],"hsluv":[12.1770506300618813,48.3021731216650707,10.1474261289244687]},"#331122":{"lch":[10.7062693823806221,14.2435433110065777,342.375847990242676],"luv":[10.7062693823806221,13.5749958919169824,-4.31254131423193],"rgb":[0.2,0.0666666666666666657,0.133333333333333331],"xyz":[0.0185435250447225398,0.0122029746303439404,0.0165130668222480161],"hpluv":[342.375847990242676,168.818174775843545,10.7062693823806221],"hsluv":[342.375847990242676,57.1044970617697913,10.7062693823806221]},"#331133":{"lch":[11.5784810016780177,17.5377888786733784,307.715012949244169],"luv":[11.5784810016780177,10.7284677021084427,-13.8735006223280077],"rgb":[0.2,0.0666666666666666657,0.2],"xyz":[0.0216312757771802804,0.0134380749233270532,0.0327752206798591628],"hpluv":[307.715012949244169,192.204068690519591,11.5784810016780177],"hsluv":[307.715012949244169,66.4967539441281,11.5784810016780177]},"#331144":{"lch":[12.7480449023252049,25.2894553184220108,288.641508688419037],"luv":[12.7480449023252049,8.08366941467993172,-23.9626968243691536],"rgb":[0.2,0.0666666666666666657,0.266666666666666663],"xyz":[0.0260892710213991574,0.0152212730210146297,0.0562539956327458],"hpluv":[288.641508688419037,251.73014018207067,12.7480449023252049],"hsluv":[288.641508688419037,74.5439781366083309,12.7480449023252049]},"#331155":{"lch":[14.1772863520069095,34.570642435857458,279.659572498507771],"luv":[14.1772863520069095,5.80074057604611415,-34.0805036230000695],"rgb":[0.2,0.0666666666666666657,0.333333333333333315],"xyz":[0.0320516850607611564,0.0176062386367594609,0.0876560429067197],"hpluv":[279.659572498507771,309.423764447612427,14.1772863520069095],"hsluv":[279.659572498507771,80.733364837348816,14.1772863520069095]},"#331166":{"lch":[15.8197098676790517,44.2946391552180785,274.993838621827194],"luv":[15.8197098676790517,3.85578699555013271,-44.1264995726595686],"rgb":[0.2,0.0666666666666666657,0.4],"xyz":[0.0396366808342693278,0.0206402369461627724,0.127603687313863678],"hpluv":[274.993838621827194,355.297359803625511,15.8197098676790517],"hsluv":[274.993838621827194,85.2848648605675095,15.8197098676790517]},"#331177":{"lch":[17.6293493428787755,54.1580116435351115,272.303494486185969],"luv":[17.6293493428787755,2.17675853502087469,-54.1142490242773135],"rgb":[0.2,0.0666666666666666657,0.466666666666666674],"xyz":[0.0489506938544712472,0.0243658421542435888,0.176657489220261588],"hpluv":[272.303494486185969,389.821469213037517,17.6293493428787755],"hsluv":[272.303494486185969,88.5936990192462588,17.6293493428787755]},"#331188":{"lch":[19.5658128626021437,64.0679547566568,270.623065923527406],"luv":[19.5658128626021437,0.696696562564985133,-64.064166587888522],"rgb":[0.2,0.0666666666666666657,0.533333333333333326],"xyz":[0.0600911109564150753,0.0288220089950211832,0.235330352623833755],"hpluv":[270.623065923527406,415.51077593183,19.5658128626021437],"hsluv":[270.623065923527406,91.0112456871911348,19.5658128626021437]},"#331199":{"lch":[21.5959931816331263,73.9854871429769645,269.508319412823],"luv":[21.5959931816331263,-0.634894604710849,-73.9827629696574576],"rgb":[0.2,0.0666666666666666657,0.6],"xyz":[0.0731480750654877887,0.0340447946386503442,0.304097030264951662],"hpluv":[269.508319412823,434.723064450461493,21.5959931816331263],"hsluv":[269.508319412823,92.7998436287799,21.5959931816331263]},"#3311aa":{"lch":[23.6938673935249824,83.8866252842298792,268.733700318675346],"luv":[23.6938673935249824,-1.85383566080119344,-83.8661385478044821],"rgb":[0.2,0.0666666666666666657,0.66666666666666663],"xyz":[0.0882057680307403308,0.0400678718247514457,0.383400879881950263],"hpluv":[268.733700318675346,449.258286440651602,23.6938673935249824],"hsluv":[268.733700318675346,94.1436997610677,23.6938673935249824]},"#3311bb":{"lch":[25.8394818705352094,93.7535423490500079,268.175268957576],"luv":[25.8394818705352094,-2.98531729009247,-93.7060007879569525],"rgb":[0.2,0.0666666666666666657,0.733333333333333282],"xyz":[0.105343360138076977,0.0469229086676862042,0.473658864980592],"hpluv":[268.175268957576,460.408371224539451,25.8394818705352094],"hsluv":[268.175268957576,95.1697562295976525,25.8394818705352094]},"#3311cc":{"lch":[28.017750605254669,103.572636018550753,267.760492630427507],"luv":[28.017750605254669,-4.04728980779695124,-103.493528189171812],"rgb":[0.2,0.0666666666666666657,0.8],"xyz":[0.124635735581798718,0.0546398588451750059,0.57526537565086211],"hpluv":[267.760492630427507,469.084508820223505,28.017750605254669],"hsluv":[267.760492630427507,95.9655004656031423,28.017750605254669]},"#3311dd":{"lch":[30.2173526676312889,113.33386550323506,267.444704079349265],"luv":[30.2173526676312889,-5.05282540459801588,-113.221173043455181],"rgb":[0.2,0.0666666666666666657,0.866666666666666696],"xyz":[0.146154061132432261,0.0632471890654285329,0.688595223550868107],"hpluv":[267.444704079349265,475.929488946899937,30.2173526676312889],"hsluv":[267.444704079349265,96.591763702558211,30.2173526676312889]},"#3311ee":{"lch":[32.429822932533412,123.030197380053124,267.199217974228532],"luv":[32.429822932533412,-6.01167404447580456,-122.883234180085807],"rgb":[0.2,0.0666666666666666657,0.933333333333333348],"xyz":[0.169966241398607,0.0727720611718985777,0.814006039619391331],"hpluv":[267.199217974228532,481.400425551936735,32.429822932533412],"hsluv":[267.199217974228532,97.0913881744298095,32.429822932533412]},"#3311ff":{"lch":[34.6488414224811834,132.657034918193688,267.004954598207064],"luv":[34.6488414224811834,-6.93127707868383425,-132.475832933200962],"rgb":[0.2,0.0666666666666666657,1],"xyz":[0.196137289808438392,0.0832404805358312738,0.951840227911173176],"hpluv":[267.004954598207064,485.826158631145177,34.6488414224811834],"hsluv":[267.004954598207064,99.999999999999531,34.6488414224811834]},"#88aa00":{"lch":[64.9493872277699467,75.8454165204624502,102.522158340464031],"luv":[64.9493872277699467,-16.4445883060260414,74.0412231301438624],"rgb":[0.533333333333333326,0.66666666666666663,0],"xyz":[0.245272120749672057,0.339833923051985953,0.0526729261635559762],"hpluv":[102.522158340464031,148.181371186867864,64.9493872277699467],"hsluv":[102.522158340464031,100.000000000002217,64.9493872277699467]},"#88aa11":{"lch":[64.9815053546997206,74.514883993558044,102.764001416735823],"luv":[64.9815053546997206,-16.4630035423646639,72.6734989589568414],"rgb":[0.533333333333333326,0.66666666666666663,0.0666666666666666657],"xyz":[0.246283786249309189,0.340238589251840806,0.0580010311283116059],"hpluv":[102.764001416735823,145.509915409181133,64.9815053546997206],"hsluv":[102.764001416735823,98.0498740713468635,64.9815053546997206]},"#88aa22":{"lch":[65.040976504183746,72.0784265262596762,103.230826782560158],"luv":[65.040976504183746,-16.4969246852166869,70.1651697527462801],"rgb":[0.533333333333333326,0.66666666666666663,0.133333333333333331],"xyz":[0.24815914438778619,0.340988732507231607,0.0678779173242908],"hpluv":[103.230826782560158,140.623392494363173,65.040976504183746],"hsluv":[103.230826782560158,94.4776072436414296,65.040976504183746]},"#88aa33":{"lch":[65.138705174337673,68.1506383708936596,104.056367163177015],"luv":[65.138705174337673,-16.5521781693680836,66.1100212389152],"rgb":[0.533333333333333326,0.66666666666666663,0.2],"xyz":[0.251246895120243952,0.342223832800214733,0.0841400711819019487],"hpluv":[104.056367163177015,132.760883332008575,65.138705174337673],"hsluv":[104.056367163177015,88.7139905695652544,65.138705174337673]},"#88aa44":{"lch":[65.2793887406011,62.6606585185119442,105.391240881396499],"luv":[65.2793887406011,-16.6306856640551395,60.4133960336360687],"rgb":[0.533333333333333326,0.66666666666666663,0.266666666666666663],"xyz":[0.255704890364462811,0.344007030897902299,0.107618846134788587],"hpluv":[105.391240881396499,121.803060858356815,65.2793887406011],"hsluv":[105.391240881396499,80.6421361820775,65.2793887406011]},"#88aa55":{"lch":[65.4667902277309821,55.6467221212728731,107.50018297907917],"luv":[65.4667902277309821,-16.7334615527701551,53.0711687011330397],"rgb":[0.533333333333333326,0.66666666666666663,0.333333333333333315],"xyz":[0.261667304403824796,0.34639199651364716,0.139020893408762503],"hpluv":[107.50018297907917,107.859366541167589,65.4667902277309821],"hsluv":[107.50018297907917,70.2829236383929157,65.4667902277309821]},"#88aa66":{"lch":[65.7039511656785606,47.2674293485405386,110.898270106627507],"luv":[65.7039511656785606,-16.8607549547505542,44.1579530727492582],"rgb":[0.533333333333333326,0.66666666666666663,0.4],"xyz":[0.269252300177333,0.349425994823050479,0.178968537815906464],"hpluv":[110.898270106627507,91.2871867148882075,65.7039511656785606],"hsluv":[110.898270106627507,57.7776943224234358,65.7039511656785606]},"#88aa77":{"lch":[65.993303036365262,37.8517489546572605,116.707912668539493],"luv":[65.993303036365262,-17.0121797895697142,33.8133204186420073],"rgb":[0.533333333333333326,0.66666666666666663,0.466666666666666674],"xyz":[0.278566313197534887,0.353151600031131274,0.228022339722304374],"hpluv":[116.707912668539493,72.782239014817236,65.993303036365262],"hsluv":[116.707912668539493,43.3670204896631262,65.993303036365262]},"#88aa88":{"lch":[66.3367341259492,28.0952907790087707,127.715012949235486],"luv":[66.3367341259492,-17.1868541575625393,22.2251526006848934],"rgb":[0.533333333333333326,0.66666666666666663,0.533333333333333326],"xyz":[0.289706730299478743,0.357607766871908872,0.286695203125876541],"hpluv":[127.715012949235486,53.7426121206727316,66.3367341259492],"hsluv":[127.715012949235486,27.3645684281827677,66.3367341259492]},"#88aa99":{"lch":[66.7356352778598705,19.8636867466165334,151.061783220075199],"luv":[66.7356352778598705,-17.3835461247401071,9.6113669837720046],"rgb":[0.533333333333333326,0.66666666666666663,0.6],"xyz":[0.302763694408551443,0.36283055251553803,0.35546188076699442],"hpluv":[151.061783220075199,37.7695130125235536,66.7356352778598705],"hsluv":[151.061783220075199,30.5390729913306274,66.7356352778598705]},"#88aaaa":{"lch":[67.1909358184889811,18.0059400546344968,192.177050630060364],"luv":[67.1909358184889811,-17.6008146924254447,-3.79805205519771905],"rgb":[0.533333333333333326,0.66666666666666663,0.66666666666666663],"xyz":[0.317821387373804,0.368853629701639152,0.434765730383993],"hpluv":[192.177050630060364,34.0051297749840913,67.1909358184889811],"hsluv":[192.177050630060364,33.872023720911649,67.1909358184889811]},"#88aabb":{"lch":[67.7031355134684674,25.1829477340388976,224.903065382651],"luv":[67.7031355134684674,-17.8371340556046292,-17.7768812016541453],"rgb":[0.533333333333333326,0.66666666666666663,0.733333333333333282],"xyz":[0.334958979481140617,0.37570866654457391,0.525023715482634823],"hpluv":[224.903065382651,47.1994684953027459,67.7031355134684674],"hsluv":[224.903065382651,37.296330310174362,67.7031355134684674]},"#88aacc":{"lch":[68.2723356589922901,36.8600300209604939,240.606662797769701],"luv":[68.2723356589922901,-18.0909926283411373,-32.1150712106857341],"rgb":[0.533333333333333326,0.66666666666666663,0.8],"xyz":[0.354251354924862372,0.383425616722062712,0.626630226152905],"hpluv":[240.606662797769701,68.5094136262693,68.2723356589922901],"hsluv":[240.606662797769701,40.7502319604911136,68.2723356589922901]},"#88aadd":{"lch":[68.8982708583434,50.1120766914241216,248.506358436024811],"luv":[68.8982708583434,-18.3609632112572676,-46.6271944285953168],"rgb":[0.533333333333333326,0.66666666666666663,0.866666666666666696],"xyz":[0.375769680475495915,0.392032946942316218,0.739960074052911],"hpluv":[248.506358436024811,92.2939864083951278,68.8982708583434],"hsluv":[248.506358436024811,59.5109742880650217,68.8982708583434]},"#88aaee":{"lch":[69.5803420919898,63.9362726255054454,253.044423586561948],"luv":[69.5803420919898,-18.6457452648911577,-61.1570367231747554],"rgb":[0.533333333333333326,0.66666666666666663,0.933333333333333348],"xyz":[0.39958186074167068,0.401557819048786235,0.8653708901214342],"hpluv":[253.044423586561948,116.600410917186778,69.5803420919898],"hsluv":[253.044423586561948,79.2673662112875093,69.5803420919898]},"#88aaff":{"lch":[70.3176511000829549,77.916964899147743,255.928474825822],"luv":[70.3176511000829549,-18.9441834980668631,-75.578907974954177],"rgb":[0.533333333333333326,0.66666666666666663,1],"xyz":[0.425752909151502046,0.412026238412718959,1.00320507841321604],"hpluv":[255.928474825822,140.607018245256825,70.3176511000829549],"hsluv":[255.928474825822,99.9999999999979394,70.3176511000829549]},"#332200":{"lch":[14.6681357538016819,18.4720509904151484,54.0318728094203635],"luv":[14.6681357538016819,10.8492842291989344,14.9502407842332925],"rgb":[0.2,0.133333333333333331,0],"xyz":[0.0193721251413763347,0.0184794126446342424,0.00254661690643579732],"hpluv":[54.0318728094203635,159.801011716648361,14.6681357538016819],"hsluv":[54.0318728094203635,100.000000000002359,14.6681357538016819]},"#332211":{"lch":[14.8903804788128475,14.003495227987683,44.8263438888978243],"luv":[14.8903804788128475,9.93193249146711,9.87190941941900668],"rgb":[0.2,0.133333333333333331,0.0666666666666666657],"xyz":[0.0203837906410134564,0.0188840788444890953,0.00787472187119143],"hpluv":[44.8263438888978243,119.33558852926538,14.8903804788128475],"hsluv":[44.8263438888978243,67.0844803779226595,14.8903804788128475]},"#332222":{"lch":[15.2941064614028619,8.70381909014442101,12.1770506300622809],"luv":[15.2941064614028619,8.50798716741232397,1.83592513820952408],"rgb":[0.2,0.133333333333333331,0.133333333333333331],"xyz":[0.0222591487794904751,0.0196342220998799166,0.0177516080671706253],"hpluv":[12.1770506300622809,72.2146104972558476,15.2941064614028619],"hsluv":[12.1770506300622809,16.9221215783466867,15.2941064614028619]},"#332233":{"lch":[15.9369990430381634,10.9638268591401484,307.7150129492465],"luv":[15.9369990430381634,6.70694938589646661,-8.67308072902737],"rgb":[0.2,0.133333333333333331,0.2],"xyz":[0.0253468995119482156,0.0208693223928630295,0.0340137619247817685],"hpluv":[307.7150129492465,87.2961214462547,15.9369990430381634],"hsluv":[307.7150129492465,30.2017993044426838,15.9369990430381634]},"#332244":{"lch":[16.8218835175385664,20.7382675483863608,283.478697838556343],"luv":[16.8218835175385664,4.83375477674434428,-20.1670661145035197],"rgb":[0.2,0.133333333333333331,0.266666666666666663],"xyz":[0.0298048947561670927,0.0226525204905506025,0.057492536877668407],"hpluv":[283.478697838556343,156.436171283708973,16.8218835175385664],"hsluv":[283.478697838556343,43.2894908809756558,16.8218835175385664]},"#332255":{"lch":[17.9355503164319856,31.8518286021958055,275.537546938931484],"luv":[17.9355503164319856,3.0736387963894658,-31.7031816992078603],"rgb":[0.2,0.133333333333333331,0.333333333333333315],"xyz":[0.0357673087955290847,0.0250374861062954354,0.0888945841516423224],"hpluv":[275.537546938931484,225.350740722061715,17.9355503164319856],"hsluv":[275.537546938931484,54.6600619512456092,17.9355503164319856]},"#332266":{"lch":[19.2543827660255502,42.9346801988288,271.988815040461645],"luv":[19.2543827660255502,1.49002234071320738,-42.9088172430781114],"rgb":[0.2,0.133333333333333331,0.4],"xyz":[0.043352304569037263,0.028071484415698747,0.12884222855878627],"hpluv":[271.988815040461645,282.955381276792764,19.2543827660255502],"hsluv":[271.988815040461645,63.8744485302889515,19.2543827660255502]},"#332277":{"lch":[20.7496984269819,53.7295137018198687,270.083996688769219],"luv":[20.7496984269819,0.0787684479011579453,-53.7294559637975908],"rgb":[0.2,0.133333333333333331,0.466666666666666674],"xyz":[0.0526663175892391755,0.0317970896237795633,0.17789603046518418],"hpluv":[270.083996688769219,328.579487011522247,20.7496984269819],"hsluv":[270.083996688769219,71.0892762838988546,20.7496984269819]},"#332288":{"lch":[22.3919640579388926,64.2366699579867,268.940142222195846],"luv":[22.3919640579388926,-1.18818265954209568,-64.2256801385464087],"rgb":[0.2,0.133333333333333331,0.533333333333333326],"xyz":[0.063806734691183,0.0362532564645571542,0.236568893868756347],"hpluv":[268.940142222195846,364.024117005976393,22.3919640579388926],"hsluv":[268.940142222195846,76.6637840765232426,22.3919640579388926]},"#332299":{"lch":[24.1535324867621668,74.5121507797046689,268.199285594367666],"luv":[24.1535324867621668,-2.34141182983712737,-74.4753543426316469],"rgb":[0.2,0.133333333333333331,0.6],"xyz":[0.076863698800255717,0.0414760421081863187,0.305335571509874282],"hpluv":[268.199285594367666,391.458538227207669,24.1535324867621668],"hsluv":[268.199285594367666,80.9654036049547301,24.1535324867621668]},"#3322aa":{"lch":[26.0100477302332607,84.6098540849434926,267.692459882235937],"luv":[26.0100477302332607,-3.40667075751279169,-84.541244387726735],"rgb":[0.2,0.133333333333333331,0.66666666666666663],"xyz":[0.0919213917655082591,0.0474991192942874202,0.384639421126872882],"hpluv":[267.692459882235937,412.780453116303818,26.0100477302332607],"hsluv":[267.692459882235937,84.3023702715129,26.0100477302332607]},"#3322bb":{"lch":[27.9408960039881222,94.5690254119923281,267.330995248517297],"luv":[27.9408960039881222,-4.40370835341661504,-94.4664380619492761],"rgb":[0.2,0.133333333333333331,0.733333333333333282],"xyz":[0.109058983872844906,0.0543541561372221788,0.474897406225514629],"hpluv":[267.330995248517297,429.484911570580266,27.9408960039881222],"hsluv":[267.330995248517297,86.9134730370406743,27.9408960039881222]},"#3322cc":{"lch":[29.9290875828623939,104.415306333233346,267.064581258752071],"luv":[29.9290875828623939,-5.34714045276937444,-104.278302084572317],"rgb":[0.2,0.133333333333333331,0.8],"xyz":[0.12835135931656666,0.0620711063147109804,0.576503916895784729],"hpluv":[267.064581258752071,442.700503900749,29.9290875828623939],"hsluv":[267.064581258752071,88.9774620844202389,29.9290875828623939]},"#3322dd":{"lch":[31.9608605817263296,114.164622106097937,266.862904678446171],"luv":[31.9608605817263296,-6.2476920173399213,-113.993540541052639],"rgb":[0.2,0.133333333333333331,0.866666666666666696],"xyz":[0.149869684867200204,0.0706784365349645144,0.689833764795790727],"hpluv":[266.862904678446171,453.265229710644405,31.9608605817263296],"hsluv":[266.862904678446171,90.6264253960307826,31.9608605817263296]},"#3322ee":{"lch":[34.0251904593745635,123.826689560879501,266.706806867468629],"luv":[34.0251904593745635,-7.11327635006579229,-123.622208147136817],"rgb":[0.2,0.133333333333333331,0.933333333333333348],"xyz":[0.173681865133374941,0.0802033086414345453,0.815244580864314],"hpluv":[266.706806867468629,461.799038215803307,34.0251904593745635],"hsluv":[266.706806867468629,93.6430785136650741,34.0251904593745635]},"#3322ff":{"lch":[36.1133053940478774,133.407509730883817,266.583697157343806],"luv":[36.1133053940478774,-7.94980801741223875,-133.170432923686747],"rgb":[0.2,0.133333333333333331,1],"xyz":[0.199852913543206334,0.0906717280053672414,0.953078769156095795],"hpluv":[266.583697157343806,468.761962088723578,36.1133053940478774],"hsluv":[266.583697157343806,99.999999999999531,36.1133053940478774]},"#aaaa00":{"lch":[67.4983691984715506,74.4102446110960472,85.8743202181747449],"luv":[67.4983691984715506,5.35340686476390193,74.217420717938225],"rgb":[0.66666666666666663,0.66666666666666663,0],"xyz":[0.309512896760441802,0.372958073182539818,0.0556842125390607443],"hpluv":[85.8743202181747449,139.887458074797593,67.4983691984715506],"hsluv":[85.8743202181747449,100.000000000002373,67.4983691984715506]},"#aaaa11":{"lch":[67.528557359020084,73.1276023311446863,85.8743202181746881],"luv":[67.528557359020084,5.26112782412359792,72.9381022286724345],"rgb":[0.66666666666666663,0.66666666666666663,0.0666666666666666657],"xyz":[0.310524562260078907,0.373362739382394671,0.061012317503816374],"hpluv":[85.8743202181746881,137.414698385368666,67.528557359020084],"hsluv":[85.8743202181746881,98.2323220941626118,67.528557359020084]},"#aaaa22":{"lch":[67.5844605157977,70.7729399531690575,85.8743202181746],"luv":[67.5844605157977,5.09172284764045369,70.589541633712912],"rgb":[0.66666666666666663,0.66666666666666663,0.133333333333333331],"xyz":[0.312399920398555964,0.374112882637785471,0.0708892036997955666],"hpluv":[85.8743202181746,132.880028295953878,67.5844605157977],"hsluv":[85.8743202181746,94.9906661574379854,67.5844605157977]},"#aaaa33":{"lch":[67.6763416895574181,66.9597491826677924,85.8743202181744607],"luv":[67.6763416895574181,4.81738479440415723,66.7862322215321882],"rgb":[0.66666666666666663,0.66666666666666663,0.2],"xyz":[0.315487671131013669,0.375347982930768598,0.0871513575574067167],"hpluv":[85.8743202181744607,125.549870841925909,67.6763416895574181],"hsluv":[85.8743202181744607,89.7506270896691376,67.6763416895574181]},"#aaaa44":{"lch":[67.8086418759902898,61.5895608625658824,85.8743202181741623],"luv":[67.8086418759902898,4.43102935143870269,61.429960004304057],"rgb":[0.66666666666666663,0.66666666666666663,0.266666666666666663],"xyz":[0.319945666375232585,0.377131181028456164,0.110630132510293355],"hpluv":[85.8743202181741623,115.255428047766188,67.8086418759902898],"hsluv":[85.8743202181741623,82.3915379076671854,67.8086418759902898]},"#aaaa55":{"lch":[67.9849384953625844,54.6449851984581514,85.8743202181737786],"luv":[67.9849384953625844,3.93140541890911,54.5033802508787772],"rgb":[0.66666666666666663,0.66666666666666663,0.333333333333333315],"xyz":[0.32590808041459457,0.379516146644201,0.142032179784267271],"hpluv":[85.8743202181737786,101.994541545207838,67.9849384953625844],"hsluv":[85.8743202181737786,72.9118556794948631,67.9849384953625844]},"#aaaa66":{"lch":[68.2081473948541515,46.1798212544818156,85.8743202181731675],"luv":[68.2081473948541515,3.32238354287766668,46.0601526125338268],"rgb":[0.66666666666666663,0.66666666666666663,0.4],"xyz":[0.333493076188102755,0.382550144953604343,0.181979824191411232],"hpluv":[85.8743202181731675,85.9122949373369806,68.2081473948541515],"hsluv":[85.8743202181731675,61.415294923296095,68.2081473948541515]},"#aaaa77":{"lch":[68.4806287458147551,36.3079853189649668,85.874320218171988],"luv":[68.4806287458147551,2.61215937225179973,36.2138981792368284],"rgb":[0.66666666666666663,0.66666666666666663,0.466666666666666674],"xyz":[0.342807089208304661,0.386275750161685139,0.231033626097809142],"hpluv":[85.874320218171988,67.2781031791916604,68.4806287458147551],"hsluv":[85.874320218171988,48.0944497134402909,68.4806287458147551]},"#aaaa88":{"lch":[68.804250183835336,25.1900382005990835,85.8743202181696574],"luv":[68.804250183835336,1.81228437202058101,25.1247616884732103],"rgb":[0.66666666666666663,0.66666666666666663,0.533333333333333326],"xyz":[0.353947506310248461,0.390731917002462736,0.289706489501381281],"hpluv":[85.8743202181696574,46.4571845078746506,68.804250183835336],"hsluv":[85.8743202181696574,33.210400093935057,68.804250183835336]},"#aaaa99":{"lch":[69.1804292601881485,13.0180161266067085,85.8743202181625236],"luv":[69.1804292601881485,0.936574490007753058,12.9842817320504498],"rgb":[0.66666666666666663,0.66666666666666663,0.6],"xyz":[0.36700447041932116,0.395954702646091894,0.358473167142499216],"hpluv":[85.8743202181625236,23.8781611725121081,69.1804292601881485],"hsluv":[85.8743202181625236,17.0695511242654057,69.1804292601881485]},"#aaaaaa":{"lch":[69.6101658300367916,3.6866289517569387e-12,0],"luv":[69.6101658300367916,3.46613397703382525e-12,1.25584564385283521e-12],"rgb":[0.66666666666666663,0.66666666666666663,0.66666666666666663],"xyz":[0.382062163384573716,0.401977779832193,0.437777016759497817],"hpluv":[0,6.72041492281092149e-12,69.6101658300367916],"hsluv":[0,4.48262290109626775e-12,69.6101658300367916]},"#aaaabb":{"lch":[70.0940699613229441,13.6540669730780309,265.874320218191428],"luv":[70.0940699613229441,-0.982334841759501587,-13.618684340418703],"rgb":[0.66666666666666663,0.66666666666666663,0.733333333333333282],"xyz":[0.399199755491910391,0.408832816675127775,0.528035001858139563],"hpluv":[265.874320218191428,24.7183841606301087,70.0940699613229441],"hsluv":[265.874320218191428,17.6184615311656536,70.0940699613229441]},"#aaaacc":{"lch":[70.6323884029978188,27.7441307883788433,265.87432021818438],"luv":[70.6323884029978188,-1.99603725260327192,-27.6722356973355303],"rgb":[0.66666666666666663,0.66666666666666663,0.8],"xyz":[0.41849213093563209,0.416549766852616576,0.629641512528409719],"hpluv":[265.87432021818438,49.8432735452352063,70.6323884029978188],"hsluv":[265.87432021818438,36.467826786828347,70.6323884029978188]},"#aaaadd":{"lch":[71.2250312240615813,42.0886841218373817,265.874320218182],"luv":[71.2250312240615813,-3.02804878123905441,-41.979617097899343],"rgb":[0.66666666666666663,0.66666666666666663,0.866666666666666696],"xyz":[0.440010456486265689,0.425157097072870083,0.742971360428415717],"hpluv":[265.874320218182,74.9845908684596,71.2250312240615813],"hsluv":[265.874320218182,56.4865697219014891,71.2250312240615813]},"#aaaaee":{"lch":[71.8715993709786432,56.5301989351418541,265.874320218180742],"luv":[71.8715993709786432,-4.0670361537863835,-56.3837087159979902],"rgb":[0.66666666666666663,0.66666666666666663,0.933333333333333348],"xyz":[0.463822636752440398,0.4346819691793401,0.86838217649693894],"hpluv":[265.874320218180742,99.8073514218055,71.8715993709786432],"hsluv":[265.874320218180742,77.6546881169827259,71.8715993709786432]},"#aaaaff":{"lch":[72.5714133442747595,70.9376272522327,265.87432021818006],"luv":[72.5714133442747595,-5.10357119085512778,-70.7538021683399],"rgb":[0.66666666666666663,0.66666666666666663,1],"xyz":[0.489993685162271819,0.445150388543272824,1.00621636478872079],"hpluv":[265.87432021818006,124.036757123492009,72.5714133442747595],"hsluv":[265.87432021818006,99.999999999997641,72.5714133442747595]},"#88bb00":{"lch":[70.0174964893220135,84.793654921948729,107.670265811619984],"luv":[70.0174964893220135,-25.7381496181260658,80.7930168347331659],"rgb":[0.533333333333333326,0.733333333333333282,0],"xyz":[0.279226618658270809,0.407742918869184512,0.0639910921330886],"hpluv":[107.670265811619984,153.672481251000221,70.0174964893220135],"hsluv":[107.670265811619984,100.000000000002288,70.0174964893220135]},"#88bb11":{"lch":[70.045943224524,83.6147085810298,107.921872667069366],"luv":[70.045943224524,-25.7299069713944561,79.5574721715938296],"rgb":[0.533333333333333326,0.733333333333333282,0.0666666666666666657],"xyz":[0.280238284157907913,0.408147585069039365,0.0693191970978442318],"hpluv":[107.921872667069366,151.474322676164348,70.045943224524],"hsluv":[107.921872667069366,98.3704135852689,70.045943224524]},"#88bb22":{"lch":[70.0986261940145567,81.4532385975490172,108.403169751544382],"luv":[70.0986261940145567,-25.7149121100318041,77.2876016784231],"rgb":[0.533333333333333326,0.733333333333333282,0.133333333333333331],"xyz":[0.28211364229638497,0.408897728324430165,0.0791960832938234244],"hpluv":[108.403169751544382,147.447759071005407,70.0986261940145567],"hsluv":[108.403169751544382,95.3794817356858431,70.0986261940145567]},"#88bb33":{"lch":[70.185227758130182,77.9617926087192643,109.240455548552404],"luv":[70.185227758130182,-25.6910124331637526,73.6071530961765887],"rgb":[0.533333333333333326,0.733333333333333282,0.2],"xyz":[0.285201393028842676,0.410132828617413292,0.0954582371514345607],"hpluv":[109.240455548552404,140.95335886915251,70.185227758130182],"hsluv":[109.240455548552404,90.5378353052476399,70.185227758130182]},"#88bb44":{"lch":[70.3099541281250708,73.067556170236557,110.558097475340105],"luv":[70.3099541281250708,-25.6581823155790048,68.4143657790612281],"rgb":[0.533333333333333326,0.733333333333333282,0.266666666666666663],"xyz":[0.289659388273061591,0.411916026715100858,0.118937012104321199],"hpluv":[110.558097475340105,131.870330314080604,70.3099541281250708],"hsluv":[110.558097475340105,83.7238240635208655,70.3099541281250708]},"#88bb55":{"lch":[70.4762099132372,66.7907607981454845,112.553407091589676],"luv":[70.4762099132372,-25.6172250438111178,61.682765089203194],"rgb":[0.533333333333333326,0.733333333333333282,0.333333333333333315],"xyz":[0.295621802312423576,0.414300992330845719,0.150339059378295115],"hpluv":[112.553407091589676,120.257778383662554,70.4762099132372],"hsluv":[112.553407091589676,74.9213657205140606,70.4762099132372]},"#88bb66":{"lch":[70.6867901559138687,59.2534136994931373,115.564788197424377],"luv":[70.6867901559138687,-25.56971066242372,53.4523800375924836],"rgb":[0.533333333333333326,0.733333333333333282,0.4],"xyz":[0.303206798085931761,0.417334990640249037,0.190286703785439076],"hpluv":[115.564788197424377,106.368844477737383,70.6867901559138687],"hsluv":[115.564788197424377,64.2082802413586791,70.6867901559138687]},"#88bb77":{"lch":[70.9439811929011483,50.7088031944788611,120.213509646437856],"luv":[70.9439811929011483,-25.5178724843925657,43.8203252530908287],"rgb":[0.533333333333333326,0.733333333333333282,0.466666666666666674],"xyz":[0.312520811106133667,0.421060595848329833,0.239340505691836986],"hpluv":[120.213509646437856,90.6999673798200519,70.9439811929011483],"hsluv":[120.213509646437856,51.7430673824667338,70.9439811929011483]},"#88bb88":{"lch":[71.2496205680497781,41.6266624709187667,127.715012949237462],"luv":[71.2496205680497781,-25.4644588867656232,32.9293237414924747],"rgb":[0.533333333333333326,0.733333333333333282,0.533333333333333326],"xyz":[0.323661228208077467,0.425516762689107431,0.298013369095409153],"hpluv":[127.715012949237462,74.1358655131278397,71.2496205680497781],"hsluv":[127.715012949237462,37.7483692132655,71.2496205680497781]},"#88bb99":{"lch":[71.605136773449729,32.9376822973712677,140.491872589160209],"luv":[71.605136773449729,-25.4125532319559895,20.9545473192710077],"rgb":[0.533333333333333326,0.733333333333333282,0.6],"xyz":[0.336718192317150167,0.430739548332736588,0.366780046736527088],"hpluv":[140.491872589160209,58.3697971606621948,71.605136773449729],"hsluv":[140.491872589160209,40.0947707109065163,71.605136773449729]},"#88bbaa":{"lch":[72.0115788449514298,26.624214972975043,162.310745910586235],"luv":[72.0115788449514298,-25.3653817896029707,8.0898843993512255],"rgb":[0.533333333333333326,0.733333333333333282,0.66666666666666663],"xyz":[0.351775885282402723,0.43676262551883771,0.446083896353525633],"hpluv":[162.310745910586235,46.9152251525928463,72.0115788449514298],"hsluv":[162.310745910586235,42.5902472855224445,72.0115788449514298]},"#88bbbb":{"lch":[72.4696411221425478,25.9090725846495289,192.177050630060563],"luv":[72.4696411221425478,-25.3261303787159093,-5.46508574835939687],"rgb":[0.533333333333333326,0.733333333333333282,0.733333333333333282],"xyz":[0.368913477389739397,0.443617662361772469,0.536341881452167435],"hpluv":[192.177050630060563,45.3664800039612786,72.4696411221425478],"hsluv":[192.177050630060563,45.1889022919971595,72.4696411221425478]},"#88bbcc":{"lch":[72.9796861172365539,31.9509756483125074,217.648879320727843],"luv":[72.9796861172365539,-25.297786835453639,-19.5163220435359541],"rgb":[0.533333333333333326,0.733333333333333282,0.8],"xyz":[0.388205852833461096,0.451334612539261271,0.637948392122437591],"hpluv":[217.648879320727843,55.5547835161394303,72.9796861172365539],"hsluv":[217.648879320727843,47.846459663484211,72.9796861172365539]},"#88bbdd":{"lch":[73.5417671198988501,42.2771793498237827,233.271065498294831],"luv":[73.5417671198988501,-25.2830202693059967,-33.8840490472881442],"rgb":[0.533333333333333326,0.733333333333333282,0.866666666666666696],"xyz":[0.409724178384094695,0.459941942759514777,0.751278240022443589],"hpluv":[233.271065498294831,72.9476439375157781,73.5417671198988501],"hsluv":[233.271065498294831,52.600286903313318,73.5417671198988501]},"#88bbee":{"lch":[74.1556513704433655,54.6140049995012049,242.42172167609948],"luv":[74.1556513704433655,-25.2841013367454792,-48.4087157615106349],"rgb":[0.533333333333333326,0.733333333333333282,0.933333333333333348],"xyz":[0.433536358650269404,0.469466814865984794,0.876689056090966812],"hpluv":[242.42172167609948,93.4542589851821646,74.1556513704433655],"hsluv":[242.42172167609948,75.5983078602269387,74.1556513704433655]},"#88bbff":{"lch":[74.8208441285393206,67.8489412305869877,248.103607922481928],"luv":[74.8208441285393206,-25.3028619495915343,-62.9543009116260492],"rgb":[0.533333333333333326,0.733333333333333282,1],"xyz":[0.459707407060100826,0.479935234229917518,1.01452324438274855],"hpluv":[248.103607922481928,115.069386567942303,74.8208441285393206],"hsluv":[248.103607922481928,99.9999999999973568,74.8208441285393206]},"#333300":{"lch":[20.3279441284931792,22.4095383785379596,85.8743202181747449],"luv":[20.3279441284931792,1.61224273913978733,22.3514671484727536],"rgb":[0.2,0.2,0],"xyz":[0.0254898472303871464,0.0307148568226560392,0.00458585760277267773],"hpluv":[85.8743202181747449,139.887458074797735,20.3279441284931792],"hsluv":[85.8743202181747449,100.000000000002458,20.3279441284931792]},"#333311":{"lch":[20.4867879892499971,17.9332091798965507,85.8743202181741],"luv":[20.4867879892499971,1.2901955319819518,17.8867377399899183],"rgb":[0.2,0.2,0.0666666666666666657],"xyz":[0.0265015127300242681,0.0311195230225108921,0.00991396256752831],"hpluv":[85.8743202181741,111.076827622251201,20.4867879892499971],"hsluv":[85.8743202181741,79.4044220625277717,20.4867879892499971]},"#333322":{"lch":[20.7776374982028358,10.4602453251552614,85.8743202181717749],"luv":[20.7776374982028358,0.752556982220839221,10.4331390411008691],"rgb":[0.2,0.2,0.133333333333333331],"xyz":[0.0283768708685012867,0.0318696662779017134,0.019790848763507507],"hpluv":[85.8743202181717749,63.8829601302186703,20.7776374982028358],"hsluv":[85.8743202181717749,45.6673964981637113,20.7776374982028358]},"#333333":{"lch":[21.246731294981295,1.12524964979295229e-12,0],"luv":[21.246731294981295,1.05794917113478783e-12,3.83314917077821647e-13],"rgb":[0.2,0.2,0.2],"xyz":[0.0314646216009590307,0.0331047665708848263,0.0360530026211186502],"hpluv":[0,6.72041492281092149e-12,21.246731294981295],"hsluv":[0,1.92419399944792236e-12,21.246731294981295]},"#333344":{"lch":[21.9038391599933462,12.2084714240410825,265.874320218182163],"luv":[21.9038391599933462,-0.878332211796974,-12.176834853004598],"rgb":[0.2,0.2,0.266666666666666663],"xyz":[0.0359226168451779043,0.0348879646685724,0.0595317775740052887],"hpluv":[265.874320218182163,70.7262082967351517,21.9038391599933462],"hsluv":[265.874320218182163,13.7757030029577514,21.9038391599933462]},"#333355":{"lch":[22.7485838486986935,25.0264321710322868,265.874320218179776],"luv":[22.7485838486986935,-1.80051382017376982,-24.9615796213830023],"rgb":[0.2,0.2,0.333333333333333315],"xyz":[0.0418850308845399,0.0372729302843172322,0.0909338248479792],"hpluv":[265.874320218179776,139.599512106194084,22.7485838486986935],"hsluv":[265.874320218179776,27.1905063829271256,22.7485838486986935]},"#333366":{"lch":[23.7726526978294,37.7235732610660364,265.874320218179],"luv":[23.7726526978294,-2.71400312032964841,-37.625817820292724],"rgb":[0.2,0.2,0.4],"xyz":[0.0494700266580480746,0.0403069285937205438,0.130881469255123173],"hpluv":[265.874320218179,201.360603518100845,23.7726526978294],"hsluv":[265.874320218179,39.2200280117306193,23.7726526978294]},"#333377":{"lch":[24.9621315786770737,49.9646270765614062,265.874320218178639],"luv":[24.9621315786770737,-3.59467945556105306,-49.8351506319748268],"rgb":[0.2,0.2,0.466666666666666674],"xyz":[0.0587840396782499941,0.0440325338018013601,0.179935271161521082],"hpluv":[265.874320218178639,253.992158426909725,24.9621315786770737],"hsluv":[265.874320218178639,49.4713434217918646,24.9621315786770737]},"#333388":{"lch":[26.2997861111378413,61.6680265106551175,265.874320218178468],"luv":[26.2997861111378413,-4.43667452222106906,-61.5082223194812912],"rgb":[0.2,0.2,0.533333333333333326],"xyz":[0.0699244567801938222,0.048488700642578958,0.238608134565093222],"hpluv":[265.874320218178468,297.541234413863208,26.2997861111378413],"hsluv":[265.874320218178468,57.953618257344317,26.2997861111378413]},"#333399":{"lch":[27.7670269025285634,72.8744236647892336,265.874320218178354],"luv":[27.7670269025285634,-5.24291301488723782,-72.6855796399362788],"rgb":[0.2,0.2,0.6],"xyz":[0.0829814208892665356,0.0537114862862081155,0.307374812206211157],"hpluv":[265.874320218178354,333.031319879373427,27.7670269025285634],"hsluv":[265.874320218178354,64.8662025552495862,27.7670269025285634]},"#3333aa":{"lch":[29.34539826905295,83.6653121043175361,265.874320218178241],"luv":[29.34539826905295,-6.01925794630032573,-83.4485049793509575],"rgb":[0.2,0.2,0.66666666666666663],"xyz":[0.0980391138545190777,0.059734563472309217,0.386678661823209757],"hpluv":[265.874320218178241,361.780166220798492,29.34539826905295],"hsluv":[265.874320218178241,70.4657614516561353,29.34539826905295]},"#3333bb":{"lch":[31.0175640968910713,94.1237197643615247,265.874320218178184],"luv":[31.0175640968910713,-6.77168271864664284,-93.8798111173964855],"rgb":[0.2,0.2,0.733333333333333282],"xyz":[0.115176705961855724,0.0665896003152439686,0.476936646921851504],"hpluv":[265.874320218178184,385.062051502536349,31.0175640968910713],"hsluv":[265.874320218178184,75.0004925607309758,31.0175640968910713]},"#3333cc":{"lch":[32.7678589751368321,104.319620441623087,265.874320218178127],"luv":[32.7678589751368321,-7.50522156082274261,-104.049290523324899],"rgb":[0.2,0.2,0.8],"xyz":[0.134469081405577451,0.0743065504927327702,0.578543157592121604],"hpluv":[265.874320218178127,403.977575952485893,32.7678589751368321],"hsluv":[265.874320218178127,79.524052836351089,32.7678589751368321]},"#3333dd":{"lch":[34.5825131799139243,114.307143948468337,265.874320218178127],"luv":[34.5825131799139243,-8.22376881440244745,-114.010932739554079],"rgb":[0.2,0.2,0.866666666666666696],"xyz":[0.155987406956211,0.0829138807129863,0.691873005492127602],"hpluv":[265.874320218178127,419.426773039758132,34.5825131799139243],"hsluv":[265.874320218178127,86.1542613798901584,34.5825131799139243]},"#3333ee":{"lch":[36.4496605331747929,124.126383834434506,265.87432021817807],"luv":[36.4496605331747929,-8.93020898923314732,-123.80472741871364],"rgb":[0.2,0.2,0.933333333333333348],"xyz":[0.179799587222385732,0.092438752819456349,0.817283821560650825],"hpluv":[265.87432021817807,432.12554656995303,36.4496605331747929],"hsluv":[265.87432021817807,92.9362870993519,36.4496605331747929]},"#3333ff":{"lch":[38.3592184432327414,133.806417871427385,265.87432021817807],"luv":[38.3592184432327414,-9.62663407069321231,-133.45967698167118],"rgb":[0.2,0.2,1],"xyz":[0.205970635632217125,0.102907172183389045,0.95511800985243267],"hpluv":[265.87432021817807,442.635784237250618,38.3592184432327414],"hsluv":[265.87432021817807,99.99999999999946,38.3592184432327414]},"#aabb00":{"lch":[72.2864137555308162,81.0402066187271686,93.9104624709461291],"luv":[72.2864137555308162,-5.52673715975233737,80.8515322376329664],"rgb":[0.66666666666666663,0.733333333333333282,0],"xyz":[0.343467394669040582,0.440867068999738376,0.0670023785085933632],"hpluv":[93.9104624709461291,142.260125307220505,72.2864137555308162],"hsluv":[93.9104624709461291,100.00000000000226,72.2864137555308162]},"#aabb11":{"lch":[72.3134178153803759,79.8795424406406198,94.0047051989067199],"luv":[72.3134178153803759,-5.5786590117117969,79.6845020324350912],"rgb":[0.66666666666666663,0.733333333333333282,0.0666666666666666657],"xyz":[0.344479060168677687,0.441271735199593229,0.072330483473349],"hpluv":[94.0047051989067199,140.170301198642704,72.3134178153803759],"hsluv":[94.0047051989067199,98.4998030851846522,72.3134178153803759]},"#aabb22":{"lch":[72.3634325080893319,77.7463008610920667,94.1853407287125179],"luv":[72.3634325080893319,-5.67416055225396132,77.5389656857163],"rgb":[0.66666666666666663,0.733333333333333282,0.133333333333333331],"xyz":[0.346354418307154743,0.44202187845498403,0.0822073696693281925],"hpluv":[94.1853407287125179,136.332658010127801,72.3634325080893319],"hsluv":[94.1853407287125179,95.7441801677588131,72.3634325080893319]},"#aabb33":{"lch":[72.4456578556837343,74.284969405898,94.5007685828256427],"luv":[72.4456578556837343,-5.82932493434540167,74.0558954469191377],"rgb":[0.66666666666666663,0.733333333333333282,0.2],"xyz":[0.349442169039612449,0.443256978747967156,0.0984695235269393288],"hpluv":[94.5007685828256427,130.115164427369336,72.4456578556837343],"hsluv":[94.5007685828256427,91.2774770665997721,72.4456578556837343]},"#aabb44":{"lch":[72.5641031469497193,69.3968632274838768,95.0004815565242922],"luv":[72.5641031469497193,-6.04891620231322502,69.1327363742496317],"rgb":[0.66666666666666663,0.733333333333333282,0.266666666666666663],"xyz":[0.353900164283831364,0.445040176845654722,0.121948298479825967],"hpluv":[95.0004815565242922,121.354905136961719,72.5641031469497193],"hsluv":[95.0004815565242922,84.978619462346515,72.5641031469497193]},"#aabb55":{"lch":[72.7220260779140659,63.0543258899363366,95.7659530899235705],"luv":[72.7220260779140659,-6.33475857174489843,62.7353078200147181],"rgb":[0.66666666666666663,0.733333333333333282,0.333333333333333315],"xyz":[0.359862578323193349,0.447425142461399583,0.153350345753799883],"hpluv":[95.7659530899235705,110.024206089370551,72.7220260779140659],"hsluv":[95.7659530899235705,76.8198788639563475,72.7220260779140659]},"#aabb66":{"lch":[72.922116394456026,55.2958006214329245,96.9449007941817342],"luv":[72.922116394456026,-6.68608027099689206,54.8900892418207675],"rgb":[0.66666666666666663,0.733333333333333282,0.4],"xyz":[0.367447574096701535,0.450459140770802902,0.193297990160943844],"hpluv":[96.9449007941817342,96.2215198645611167,72.922116394456026],"hsluv":[96.9449007941817342,66.8569788454327778,72.922116394456026]},"#aabb77":{"lch":[73.1665925415562555,46.2248747385797927,98.8352478745929801],"luv":[73.1665925415562555,-7.09985217623529596,45.6763740206356488],"rgb":[0.66666666666666663,0.733333333333333282,0.466666666666666674],"xyz":[0.37676158711690344,0.454184745978883697,0.242351792067341754],"hpluv":[98.8352478745929801,80.1682197570307267,73.1665925415562555],"hsluv":[98.8352478745929801,55.2184354086421223,73.1665925415562555]},"#aabb88":{"lch":[73.4572589636137,36.0214199172978056,102.133241078873],"luv":[73.4572589636137,-7.57119112276486117,35.2167539367396216],"rgb":[0.66666666666666663,0.733333333333333282,0.533333333333333326],"xyz":[0.387902004218847241,0.458640912819661295,0.301024655470913949],"hpluv":[102.133241078873,62.2250760292602862,73.4572589636137],"hsluv":[102.133241078873,42.0922357464751116,73.4572589636137]},"#aabb99":{"lch":[73.7955437608147236,25.0118273668521454,108.880774444702425],"luv":[73.7955437608147236,-8.09382587885112592,23.6660408786948082],"rgb":[0.66666666666666663,0.733333333333333282,0.6],"xyz":[0.40095896832792,0.463863698463290453,0.369791333112031828],"hpluv":[108.880774444702425,43.0085312761643337,73.7955437608147236],"hsluv":[108.880774444702425,27.7101400322224,73.7955437608147236]},"#aabbaa":{"lch":[74.1825262226786464,14.1574418893213867,127.715012949227386],"luv":[74.1825262226786464,-8.66059336811296632,11.1994322785447302],"rgb":[0.66666666666666663,0.733333333333333282,0.66666666666666663],"xyz":[0.416016661293172496,0.469886775649391575,0.449095182729030429],"hpluv":[127.715012949227386,24.2171200924073027,74.1825262226786464],"hsluv":[127.715012949227386,12.3308304853939106,74.1825262226786464]},"#aabbbb":{"lch":[74.6189593067414734,9.47715438031144153,192.177050630059],"luv":[74.6189593067414734,-9.26392276955498417,-1.99904729008021675],"rgb":[0.66666666666666663,0.733333333333333282,0.733333333333333282],"xyz":[0.43315425340050917,0.476741812492326333,0.539353167827672175],"hpluv":[192.177050630059,16.1164020856357908,74.6189593067414734],"hsluv":[192.177050630059,16.0533177597809029,74.6189593067414734]},"#aabbcc":{"lch":[75.1052899078477623,18.5983929047544514,237.852316168687679],"luv":[75.1052899078477623,-9.89626817417043547,-15.7468757175676597],"rgb":[0.66666666666666663,0.733333333333333282,0.8],"xyz":[0.452446628844230925,0.484458762669815135,0.640959678497942331],"hpluv":[237.852316168687679,31.4227520087917149,75.1052899078477623],"hsluv":[237.852316168687679,25.8004515395991127,75.1052899078477623]},"#aabbdd":{"lch":[75.6416785331857682,31.6798915222297,250.547006926215033],"luv":[75.6416785331857682,-10.5504613433008458,-29.8714461033234144],"rgb":[0.66666666666666663,0.733333333333333282,0.866666666666666696],"xyz":[0.473964954394864413,0.493066092890068641,0.754289526397948329],"hpluv":[250.547006926215033,53.1449318902714438,75.6416785331857682],"hsluv":[250.547006926215033,48.9122949421499484,75.6416785331857682]},"#aabbee":{"lch":[76.2280192594463699,45.6175545861468166,255.761586302643195],"luv":[76.2280192594463699,-11.2199701465387403,-44.2162137267639],"rgb":[0.66666666666666663,0.733333333333333282,0.933333333333333348],"xyz":[0.497777134661039178,0.502590964996538658,0.879700342466471552],"hpluv":[255.761586302643195,76.8288153841444483,76.2280192594463699],"hsluv":[255.761586302643195,73.6249760737912311,76.2280192594463699]},"#aabbff":{"lch":[76.863960378353255,59.8395450787859247,258.530312903596609],"luv":[76.863960378353255,-11.8990616804050067,-58.6445520603744583],"rgb":[0.66666666666666663,0.733333333333333282,1],"xyz":[0.523948183070870543,0.513059384360471382,1.01753453075825329],"hpluv":[258.530312903596609,104.151140840900069,76.863960378353255],"hsluv":[258.530312903596609,99.9999999999969305,76.863960378353255]},"#88cc00":{"lch":[75.0884647575288,93.9986167747887,111.475410134903882],"luv":[75.0884647575288,-34.413070492851,87.4727416674912348],"rgb":[0.533333333333333326,0.8,0],"xyz":[0.317450361967887784,0.484190405488419406,0.0767323399029605363],"hpluv":[111.475410134903882,158.85012628624969,75.0884647575288],"hsluv":[111.475410134903882,100.000000000002288,75.0884647575288]},"#88cc11":{"lch":[75.1138336746799,92.9472917959209752,111.713770271434171],"luv":[75.1138336746799,-34.3877142984514421,86.3520941119794685],"rgb":[0.533333333333333326,0.8,0.0666666666666666657],"xyz":[0.318462027467524889,0.484595071688274259,0.082060444867716173],"hpluv":[111.713770271434171,157.020421425354783,75.1138336746799],"hsluv":[111.713770271434171,98.6248626695712289,75.1138336746799]},"#88cc22":{"lch":[75.1608235532889495,91.0175657840787551,112.166724150973],"luv":[75.1608235532889495,-34.3412008388942667,84.2904455214339805],"rgb":[0.533333333333333326,0.8,0.133333333333333331],"xyz":[0.320337385606001945,0.48534521494366506,0.0919373310636953656],"hpluv":[112.166724150973,153.664310911800271,75.1608235532889495],"hsluv":[112.166724150973,96.0970283406349,75.1608235532889495]},"#88cc33":{"lch":[75.2380863503033908,87.8942550668024865,112.94545296029041],"luv":[75.2380863503033908,-34.2659803117460342,80.9397471396048331],"rgb":[0.533333333333333326,0.8,0.2],"xyz":[0.323425136338459651,0.486580315236648187,0.108199484921306516],"hpluv":[112.94545296029041,148.2388630129999,75.2380863503033908],"hsluv":[112.94545296029041,91.9942509365254324,75.2380863503033908]},"#88cc44":{"lch":[75.3494055810326415,83.5027286146262,114.147802574759467],"luv":[75.3494055810326415,-34.1602904869016655,76.1956707427555244],"rgb":[0.533333333333333326,0.8,0.266666666666666663],"xyz":[0.327883131582678566,0.488363513334335753,0.131678259874193154],"hpluv":[114.147802574759467,140.624231819797672,75.3494055810326415],"hsluv":[114.147802574759467,86.1974134191241177,75.3494055810326415]},"#88cc55":{"lch":[75.4978684165763241,77.8461227965530469,115.917002828128631],"luv":[75.4978684165763241,-34.0241050685150555,70.0169915716368365],"rgb":[0.533333333333333326,0.8,0.333333333333333315],"xyz":[0.333845545622040552,0.490748478950080613,0.16308030714816707],"hpluv":[115.917002828128631,130.840327774204638,75.4978684165763241],"hsluv":[115.917002828128631,78.6694108520956092,75.4978684165763241]},"#88cc66":{"lch":[75.6860396561484663,71.0106875190110287,118.477611184333398],"luv":[75.6860396561484663,-33.8589835890750237,62.4186428259808963],"rgb":[0.533333333333333326,0.8,0.4],"xyz":[0.341430541395548737,0.493782477259483932,0.203027951555311],"hpluv":[118.477611184333398,119.054896833398359,75.6860396561484663],"hsluv":[118.477611184333398,69.4467240035668141,75.6860396561484663]},"#88cc77":{"lch":[75.9160535408259705,63.1826013081171638,122.199343200922883],"luv":[75.9160535408259705,-33.6678964132470924,53.4650713940171656],"rgb":[0.533333333333333326,0.8,0.466666666666666674],"xyz":[0.350744554415750642,0.497508082467564727,0.252081753461708913],"hpluv":[122.199343200922883,105.609553255175555,75.9160535408259705],"hsluv":[122.199343200922883,58.6308874961384063,75.9160535408259705]},"#88cc88":{"lch":[76.1896681333118124,54.6887581458639929,127.715012949238314],"luv":[76.1896681333118124,-33.4549913615237,43.2622678616965288],"rgb":[0.533333333333333326,0.8,0.533333333333333326],"xyz":[0.361884971517694443,0.50196424930834227,0.310754616865281108],"hpluv":[127.715012949238314,91.92606633748386,76.1896681333118124],"hsluv":[127.715012949238314,46.3779062484352878,76.1896681333118124]},"#88cc99":{"lch":[76.5083007543168492,46.0935908553499587,136.122445502284393],"luv":[76.5083007543168492,-33.2253063874269188,31.9483666781575764],"rgb":[0.533333333333333326,0.8,0.6],"xyz":[0.374941935626767142,0.507187034951971483,0.379521294506399],"hpluv":[136.122445502284393,78.7570782006024643,76.5083007543168492],"hsluv":[136.122445502284393,48.1280089891728622,76.5083007543168492]},"#88ccaa":{"lch":[76.8730534179438223,38.4110576559043437,149.173477570542047],"luv":[76.8730534179438223,-32.9844501501569098,19.6833787378341469],"rgb":[0.533333333333333326,0.8,0.66666666666666663],"xyz":[0.389999628592019698,0.513210112138072549,0.458825144123397588],"hpluv":[149.173477570542047,66.8865090410736229,76.8730534179438223],"hsluv":[149.173477570542047,50.0095890879800891,76.8730534179438223]},"#88ccbb":{"lch":[77.2847330465352087,33.404634806871222,168.536638924911273],"luv":[77.2847330465352087,-32.73827895277973,6.638879257104497],"rgb":[0.533333333333333326,0.8,0.733333333333333282],"xyz":[0.407137220699356372,0.520065148981007308,0.54908312922203939],"hpluv":[168.536638924911273,59.444025112992847,77.2847330465352087],"hsluv":[168.536638924911273,51.9915664660802292,77.2847330465352087]},"#88cccc":{"lch":[77.7438691793350074,33.2404934388306,192.177050630060876],"luv":[77.7438691793350074,-32.4925976386916417,-7.01152642061846443],"rgb":[0.533333333333333326,0.8,0.8],"xyz":[0.426429596143078071,0.527782099158496165,0.650689639892309546],"hpluv":[192.177050630060876,60.6231146417445359,77.7438691793350074],"hsluv":[192.177050630060876,54.0427382519684585,77.7438691793350074]},"#88ccdd":{"lch":[78.2507307533704,38.5418325774740964,213.193277164244591],"luv":[78.2507307533704,-32.2529061156020589,-21.1003058159876602],"rgb":[0.533333333333333326,0.8,0.866666666666666696],"xyz":[0.44794792169371167,0.536389429378749671,0.764019487792315544],"hpluv":[213.193277164244591,72.2588367593471759,78.2507307533704],"hsluv":[213.193277164244591,56.1332045791076126,78.2507307533704]},"#88ccee":{"lch":[78.8053428571366368,47.78945312574524,227.924421751618695],"luv":[78.8053428571366368,-32.0242046898233,-35.4722728908382834],"rgb":[0.533333333333333326,0.8,0.933333333333333348],"xyz":[0.47176010195988638,0.545914301485219688,0.889430303860838767],"hpluv":[227.924421751618695,92.3999074491721473,78.8053428571366368],"hsluv":[227.924421751618695,70.4270935368067796,78.8053428571366368]},"#88ccff":{"lch":[79.4075039272108114,59.2521837878726885,237.529017152572294],"luv":[79.4075039272108114,-31.8108626015509195,-49.9889018100727327],"rgb":[0.533333333333333326,0.8,1],"xyz":[0.497931150369717801,0.556382720849152412,1.02726449215262061],"hpluv":[237.529017152572294,118.549697277888072,79.4075039272108114],"hsluv":[237.529017152572294,99.999999999996561,79.4075039272108114]},"#334400":{"lch":[26.2681529832905483,31.0251081485104194,104.276907196552472],"luv":[26.2681529832905483,-7.65105337509169647,30.0669040288198879],"rgb":[0.2,0.266666666666666663,0],"xyz":[0.034322417713353183,0.0483799977885883553,0.00753004776376127276],"hpluv":[104.276907196552472,149.872894059772364,26.2681529832905483],"hsluv":[104.276907196552472,100.000000000002302,26.2681529832905483]},"#334411":{"lch":[26.3856741683463127,27.3886432490873446,106.295788944443402],"luv":[26.3856741683463127,-7.68514827558869662,26.2883296351821087],"rgb":[0.2,0.266666666666666663,0.0666666666666666657],"xyz":[0.0353340832129903082,0.0487846639884432082,0.0128581527285169042],"hpluv":[106.295788944443402,131.716945387015755,26.3856741683463127],"hsluv":[106.295788944443402,86.6296124974134614,26.3856741683463127]},"#334422":{"lch":[26.6018195362025054,21.2226436820006832,111.412237748000109],"luv":[26.6018195362025054,-7.74787020962619799,19.7578114189793403],"rgb":[0.2,0.266666666666666663,0.133333333333333331],"xyz":[0.0372094413514673233,0.0495348072438340295,0.0227350389244961],"hpluv":[111.412237748000109,101.234249163259577,26.6018195362025054],"hsluv":[111.412237748000109,63.7673799144094,26.6018195362025054]},"#334433":{"lch":[26.9529945323855813,12.8320575385027151,127.715012949236225],"luv":[26.9529945323855813,-7.8498102472204323,10.150969399721264],"rgb":[0.2,0.266666666666666663,0.2],"xyz":[0.0402971920839250639,0.0507699075368171424,0.038997192782107247],"hpluv":[127.715012949236225,60.4127494816677171,26.9529945323855813],"hsluv":[127.715012949236225,30.7608572023581708,26.9529945323855813]},"#334444":{"lch":[27.4501004194092673,8.17817622085537721,192.177050630060421],"luv":[27.4501004194092673,-7.99417102070306651,-1.72504956193021397],"rgb":[0.2,0.266666666666666663,0.266666666666666663],"xyz":[0.0447551873281439444,0.0525531056345047154,0.0624759677349938855],"hpluv":[192.177050630060421,37.8052272806132379,27.4501004194092673],"hsluv":[192.177050630060421,37.6572465300637518,27.4501004194092673]},"#334455":{"lch":[28.0976851129048839,16.9879579660521678,241.20654356816641],"luv":[28.0976851129048839,-8.1823109542023289,-14.8875956186718064],"rgb":[0.2,0.266666666666666663,0.333333333333333315],"xyz":[0.0507176013675059364,0.0549380712502495483,0.0938780150089678],"hpluv":[241.20654356816641,76.720241835207986,28.0976851129048839],"hsluv":[241.20654356816641,44.9859363973003568,28.0976851129048839]},"#334466":{"lch":[28.8949601880565652,29.7043747380071501,253.545194757545516],"luv":[28.8949601880565652,-8.41402976058801855,-28.487786536758108],"rgb":[0.2,0.266666666666666663,0.4],"xyz":[0.0583025971410141147,0.0579720695596528598,0.133825659416111742],"hpluv":[253.545194757545516,130.448064952476017,28.8949601880565652],"hsluv":[253.545194757545516,52.1427730716471629,28.8949601880565652]},"#334477":{"lch":[29.8367962202096138,42.8398018741040758,258.299336276781332],"luv":[29.8367962202096138,-8.68785350705267589,-41.9496105590085691],"rgb":[0.2,0.266666666666666663,0.466666666666666674],"xyz":[0.0676166101612160342,0.0616976747677336762,0.182879461322509651],"hpluv":[258.299336276781332,182.19421868795277,29.8367962202096138],"hsluv":[258.299336276781332,58.7347196438674857,29.8367962202096138]},"#334488":{"lch":[30.9147794404111025,55.6960507233291082,260.699324576281469],"luv":[30.9147794404111025,-9.00134255207500189,-54.9638599302837605],"rgb":[0.2,0.266666666666666663,0.533333333333333326],"xyz":[0.0787570272631598622,0.066153841608511274,0.241552324726081818],"hpluv":[260.699324576281469,228.611238042833349,30.9147794404111025],"hsluv":[260.699324576281469,64.5716173949788583,30.9147794404111025]},"#334499":{"lch":[32.1182691124294664,68.0605660836803281,262.102678541403236],"luv":[32.1182691124294664,-9.35140200670356769,-67.4150720250304],"rgb":[0.2,0.266666666666666663,0.6],"xyz":[0.0918139913722325618,0.0713766272521404316,0.310319002367199726],"hpluv":[262.102678541403236,268.895014901030436,32.1182691124294664],"hsluv":[262.102678541403236,69.6097770986353623,32.1182691124294664]},"#3344aa":{"lch":[33.435366318838156,79.8975403264742852,263.001802037450773],"luv":[33.435366318838156,-9.73456660877536528,-79.3023023824649158],"rgb":[0.2,0.266666666666666663,0.66666666666666663],"xyz":[0.106871684337485118,0.07739970443824154,0.389622851984198326],"hpluv":[263.001802037450773,303.226149032408784,33.435366318838156],"hsluv":[263.001802037450773,73.891501645941716,33.435366318838156]},"#3344bb":{"lch":[34.8537252521307721,91.2457354427413492,263.615054402289786],"luv":[34.8537252521307721,-10.1472390443123768,-90.6797539490724773],"rgb":[0.2,0.266666666666666663,0.733333333333333282],"xyz":[0.124009276444821764,0.0842547412811763,0.479880837082840073],"hpluv":[263.615054402289786,332.202349056841342,34.8537252521307721],"hsluv":[263.615054402289786,77.4995146205371412,34.8537252521307721]},"#3344cc":{"lch":[36.3611746115969083,102.170263494902102,264.052905077601281],"luv":[36.3611746115969083,-10.5858721727669973,-101.620382074461631],"rgb":[0.2,0.266666666666666663,0.8],"xyz":[0.143301651888543491,0.0919716914586651,0.581487347753110284],"hpluv":[264.052905077601281,356.55451128807033,36.3611746115969083],"hsluv":[264.052905077601281,80.5286468598271767,36.3611746115969083]},"#3344dd":{"lch":[37.9461503215655611,112.73940211649635,264.376684246138268],"luv":[37.9461503215655611,-11.0470957042534899,-112.196855865421313],"rgb":[0.2,0.266666666666666663,0.866666666666666696],"xyz":[0.164819977439177034,0.100579021678918634,0.694817195653116282],"hpluv":[264.376684246138268,377.005191833442723,37.9461503215655611],"hsluv":[264.376684246138268,84.1625325255073,37.9461503215655611]},"#3344ee":{"lch":[39.5979632159824462,123.014623823289881,264.622878978329823],"luv":[39.5979632159824462,-11.5277944422180187,-122.473293536523641],"rgb":[0.2,0.266666666666666663,0.933333333333333348],"xyz":[0.188632157705351772,0.110103893785388651,0.820228011721639505],"hpluv":[264.622878978329823,394.205992168221826,39.5979632159824462],"hsluv":[264.622878978329823,91.9832832027675664,39.5979632159824462]},"#3344ff":{"lch":[41.3069357297154482,133.047388274610427,264.814390787746049],"luv":[41.3069357297154482,-12.0251481753234213,-132.502842754623401],"rgb":[0.2,0.266666666666666663,1],"xyz":[0.214803206115183165,0.120572313149321361,0.95806220001342135],"hpluv":[264.814390787746049,408.716999433792864,41.3069357297154482],"hsluv":[264.814390787746049,99.9999999999994458,41.3069357297154482]},"#aacc00":{"lch":[77.1199831352121,88.8460909387721,100.173289143969555],"luv":[77.1199831352121,-15.692520471132994,87.4492577233428108],"rgb":[0.66666666666666663,0.8,0],"xyz":[0.381691137978657502,0.517314555618973326,0.0797436262784653],"hpluv":[100.173289143969555,156.730643533439519,77.1199831352121],"hsluv":[100.173289143969555,100.000000000002373,77.1199831352121]},"#aacc11":{"lch":[77.1442576556984676,87.800209961997254,100.311366942902],"luv":[77.1442576556984676,-15.7160097521192821,86.3821967007212237],"rgb":[0.66666666666666663,0.8,0.0666666666666666657],"xyz":[0.382702803478294606,0.517719221818828235,0.085071731243220941],"hpluv":[100.311366942902,155.08420894585916,77.1442576556984676],"hsluv":[100.311366942902,98.7181568051142,77.1442576556984676]},"#aacc22":{"lch":[77.1892227090432641,85.8765024717939411,100.574350259733862],"luv":[77.1892227090432641,-15.7593085348968636,84.4181134075499102],"rgb":[0.66666666666666663,0.8,0.133333333333333331],"xyz":[0.384578161616771663,0.518469365074219,0.0949486174392001336],"hpluv":[100.574350259733862,152.047171814071362,77.1892227090432641],"hsluv":[100.574350259733862,96.3604791744028404,77.1892227090432641]},"#aacc33":{"lch":[77.2631626362465482,82.7513779572315116,101.028364552392574],"luv":[77.2631626362465482,-15.8299191574657527,81.2231753460099668],"rgb":[0.66666666666666663,0.8,0.2],"xyz":[0.387665912349229369,0.519704465367202162,0.111210771296811284],"hpluv":[101.028364552392574,147.088857703341773,77.2631626362465482],"hsluv":[101.028364552392574,92.5301726329619,77.2631626362465482]},"#aacc44":{"lch":[77.3697083481362569,78.3307208035327278,101.734312614214147],"luv":[77.3697083481362569,-15.9304072801298968,76.6937021240348],"rgb":[0.66666666666666663,0.8,0.266666666666666663],"xyz":[0.392123907593448284,0.521487663464889728,0.134689546249697922],"hpluv":[101.734312614214147,140.021584702469511,77.3697083481362569],"hsluv":[101.734312614214147,87.1104907412273377,77.3697083481362569]},"#aacc55":{"lch":[77.5118305539362495,72.5836718124644875,102.784946304826448],"luv":[77.5118305539362495,-16.0622064150904862,70.7841432727597493],"rgb":[0.66666666666666663,0.8,0.333333333333333315],"xyz":[0.398086321632810269,0.523872629080634478,0.16609159352367181],"hpluv":[102.784946304826448,130.736122666873541,77.5118305539362495],"hsluv":[102.784946304826448,80.0585735006639,77.5118305539362495]},"#aacc66":{"lch":[77.6920071630818114,65.5409770618580865,104.333567867024144],"luv":[77.6920071630818114,-16.225762577214013,63.5007425390513731],"rgb":[0.66666666666666663,0.8,0.4],"xyz":[0.405671317406318455,0.526906627390037796,0.2060392379308158],"hpluv":[104.333567867024144,119.198186871977654,77.6920071630818114],"hsluv":[104.333567867024144,71.3979720959128,77.6920071630818114]},"#aacc77":{"lch":[77.912311817127474,57.2990991241466574,106.653185897117098],"luv":[77.912311817127474,-16.4206512214041886,54.8958010589496865],"rgb":[0.66666666666666663,0.8,0.466666666666666674],"xyz":[0.41498533042652036,0.530632232598118647,0.255093039837213709],"hpluv":[106.653185897117098,105.457526508453554,77.912311817127474],"hsluv":[106.653185897117098,61.2114900666368769,77.912311817127474]},"#aacc88":{"lch":[78.1744663257663,48.0371110011961946,110.274462486898784],"luv":[78.1744663257663,-16.6457037997795574,45.0608985524173633],"rgb":[0.66666666666666663,0.8,0.533333333333333326],"xyz":[0.42612574752846416,0.53508839943889619,0.313765903240785848],"hpluv":[110.274462486898784,89.6844859178180513,78.1744663257663],"hsluv":[110.274462486898784,49.6324036967210418,78.1744663257663]},"#aacc99":{"lch":[78.4798746855988583,38.0746183254558517,116.349336294343573],"luv":[78.4798746855988583,-16.8991518201031816,34.1188397866961779],"rgb":[0.66666666666666663,0.8,0.6],"xyz":[0.43918271163753686,0.540311185082525403,0.382532580881903783],"hpluv":[116.349336294343573,72.2917022308792383,78.4798746855988583],"hsluv":[116.349336294343573,36.8338589582570535,78.4798746855988583]},"#aaccaa":{"lch":[78.8296472340984593,28.0820980315160789,127.715012949234293],"luv":[78.8296472340984593,-17.1787837008838338,22.2147163027108476],"rgb":[0.66666666666666663,0.8,0.66666666666666663],"xyz":[0.454240404602789416,0.546334262268626469,0.461836430498902384],"hpluv":[127.715012949234293,54.3703242245777503,78.8296472340984593],"hsluv":[127.715012949234293,23.0170216670413055,78.8296472340984593]},"#aaccbb":{"lch":[79.2246195207133,19.8998018903229301,151.462718702096396],"luv":[79.2246195207133,-17.4821042808439238,9.50674209115818236],"rgb":[0.66666666666666663,0.8,0.733333333333333282],"xyz":[0.47137799671012609,0.553189299111561228,0.55209441559754413],"hpluv":[151.462718702096396,39.3999249764932173,79.2246195207133],"hsluv":[151.462718702096396,25.9022649263565761,79.2246195207133]},"#aacccc":{"lch":[79.665368512397464,18.216345023755192,192.177050630059796],"luv":[79.665368512397464,-17.80648564660072,-3.84243346616347603],"rgb":[0.66666666666666663,0.8,0.8],"xyz":[0.490670372153847789,0.560906249289050085,0.653700926267814286],"hpluv":[192.177050630059796,36.9937893704297878,79.665368512397464],"hsluv":[192.177050630059796,28.9019874878943099,79.665368512397464]},"#aaccdd":{"lch":[80.1522276755556504,25.332665849504842,224.238778454296437],"luv":[80.1522276755556504,-18.1492995031005968,-17.6733382978265112],"rgb":[0.66666666666666663,0.8,0.866666666666666696],"xyz":[0.512188697704481388,0.569513579509303591,0.767030774167820284],"hpluv":[224.238778454296437,52.9363308364733882,80.1522276755556504],"hsluv":[224.238778454296437,37.9969627853472787,80.1522276755556504]},"#aaccee":{"lch":[80.6853018377357216,36.8247992939862954,239.828051209207672],"luv":[80.6853018377357216,-18.5080244281037345,-31.8358112007702587],"rgb":[0.66666666666666663,0.8,0.933333333333333348],"xyz":[0.536000877970656098,0.579038451615773608,0.892441590236343507],"hpluv":[239.828051209207672,79.4490805971393854,80.6853018377357216],"hsluv":[239.828051209207672,67.7857500876551313,80.6853018377357216]},"#aaccff":{"lch":[81.2644823279674284,49.9029399741520834,247.769045833277914],"luv":[81.2644823279674284,-18.8803249793402337,-46.1934708236816434],"rgb":[0.66666666666666663,0.8,1],"xyz":[0.562171926380487519,0.589506870979706332,1.03027577852812535],"hpluv":[247.769045833277914,111.562078640814406,81.2644823279674284],"hsluv":[247.769045833277914,99.9999999999962625,81.2644823279674284]},"#88dd00":{"lch":[80.1491214608994085,103.252993693735874,114.339076779275487],"luv":[80.1491214608994085,-42.5542610136121837,94.0761158653142218],"rgb":[0.533333333333333326,0.866666666666666696,0],"xyz":[0.360084352515062933,0.569458386582770926,0.0909436700853518548],"hpluv":[114.339076779275487,215.722602995807392,80.1491214608994085],"hsluv":[114.339076779275487,100.000000000002288,80.1491214608994085]},"#88dd11":{"lch":[80.1718911006532551,102.308936337717924,114.55620444532569],"luv":[80.1718911006532551,-42.518128048011647,93.0555062414261727],"rgb":[0.533333333333333326,0.866666666666666696,0.0666666666666666657],"xyz":[0.361096018014700038,0.569863052782625834,0.0962717750501074915],"hpluv":[114.55620444532569,214.038948901986089,80.1718911006532551],"hsluv":[114.55620444532569,98.8288322371321186,80.1718911006532551]},"#88dd22":{"lch":[80.2140714473537315,100.574216022873557,114.966813202702411],"luv":[80.2140714473537315,-42.4516967311958453,91.1757992740300125],"rgb":[0.533333333333333326,0.866666666666666696,0.133333333333333331],"xyz":[0.362971376153177094,0.570613196038016635,0.106148661246086684],"hpluv":[114.966813202702411,210.937294411552,80.2140714473537315],"hsluv":[114.966813202702411,96.6732644510524,80.2140714473537315]},"#88dd33":{"lch":[80.283440325316,97.7612202004146695,115.666709499512805],"luv":[80.283440325316,-42.3438510501166832,88.1150069699792908],"rgb":[0.533333333333333326,0.866666666666666696,0.2],"xyz":[0.3660591268856348,0.571848296330999761,0.122410815103697834],"hpluv":[115.666709499512805,205.88559104418357,80.283440325316],"hsluv":[115.666709499512805,93.1672856447162303,80.283440325316]},"#88dd44":{"lch":[80.3834168948860821,93.7943752395521,116.732715571790365],"luv":[80.3834168948860821,-42.1914333437924896,83.7691338081886698],"rgb":[0.533333333333333326,0.866666666666666696,0.266666666666666663],"xyz":[0.370517122129853715,0.573631494428687327,0.145889590056584473],"hpluv":[116.732715571790365,198.714220363605108,80.3834168948860821],"hsluv":[116.732715571790365,88.1979852499996184,80.3834168948860821]},"#88dd55":{"lch":[80.5168087418625475,88.6629430887769,118.270203219525229],"luv":[80.5168087418625475,-41.9934519908601374,78.0875628192801088],"rgb":[0.533333333333333326,0.866666666666666696,0.333333333333333315],"xyz":[0.376479536169215701,0.576016460044432077,0.17729163733055836],"hpluv":[118.270203219525229,189.352414361266369,80.5168087418625475],"hsluv":[118.270203219525229,81.7170886524359474,80.5168087418625475]},"#88dd66":{"lch":[80.6859701106092757,82.4238546620344437,120.433562333743893],"luv":[80.6859701106092757,-41.7508898851674672,71.0672569552589266],"rgb":[0.533333333333333326,0.866666666666666696,0.4],"xyz":[0.384064531942723886,0.579050458353835396,0.21723928173770235],"hpluv":[120.433562333743893,177.835721711884361,80.6859701106092757],"hsluv":[120.433562333743893,73.7344666622195604,80.6859701106092757]},"#88dd77":{"lch":[80.8928858528116734,75.2114908165065827,123.458458278308711],"luv":[80.8928858528116734,-41.4665196955592208,62.7478772165182832],"rgb":[0.533333333333333326,0.866666666666666696,0.466666666666666674],"xyz":[0.393378544962925791,0.582776063561916247,0.266293083644100259],"hpluv":[123.458458278308711,164.332036041008877,80.8928858528116734],"hsluv":[123.458458278308711,64.312379996729149,80.8928858528116734]},"#88dd88":{"lch":[81.1392211885512,67.2590471315356524,127.71501294923884],"luv":[81.1392211885512,-41.1446687958856145,53.2061617739807531],"rgb":[0.533333333333333326,0.866666666666666696,0.533333333333333326],"xyz":[0.404518962064869592,0.587232230402693789,0.324965947047672399],"hpluv":[127.71501294923884,149.199726190229825,81.1392211885512],"hsluv":[127.71501294923884,53.5585775308776633,81.1392211885512]},"#88dd99":{"lch":[81.4263538436063072,58.943488890057,133.791370377408185],"luv":[81.4263538436063072,-40.7909253788266,42.5492102073736831],"rgb":[0.533333333333333326,0.866666666666666696,0.6],"xyz":[0.417575926173942347,0.592455016046323,0.393732624688790334],"hpluv":[133.791370377408185,133.11083868071384,81.4263538436063072],"hsluv":[133.791370377408185,54.8771054313611515,81.4263538436063072]},"#88ddaa":{"lch":[81.7553965772464437,50.8758256364689956,142.591286230634154],"luv":[81.7553965772464437,-40.4117997418374131,30.906893661738728],"rgb":[0.533333333333333326,0.866666666666666696,0.66666666666666663],"xyz":[0.432633619139194847,0.598478093232424069,0.473036474305788934],"hpluv":[142.591286230634154,117.302359569381537,81.7553965772464437],"hsluv":[142.591286230634154,56.3076629138628,81.7553965772464437]},"#88ddbb":{"lch":[82.1272144034785327,44.0521153731503716,155.27715859232552],"luv":[82.1272144034785327,-40.0143654100278567,18.4238820470094566],"rgb":[0.533333333333333326,0.866666666666666696,0.733333333333333282],"xyz":[0.449771211246531522,0.605333130075358827,0.563294459404430681],"hpluv":[155.27715859232552,104.020343594656595,82.1272144034785327],"hsluv":[155.27715859232552,57.829298146967858,82.1272144034785327]},"#88ddcc":{"lch":[82.542438979776648,39.9525966793572422,172.446474622419316],"luv":[82.542438979776648,-39.6059077008678173,5.25186220437346396],"rgb":[0.533333333333333326,0.866666666666666696,0.8],"xyz":[0.469063586690253276,0.613050080252847684,0.664900970074700837],"hpluv":[172.446474622419316,96.9346789585341355,82.542438979776648],"hsluv":[172.446474622419316,59.4202271347422908,82.542438979776648]},"#88dddd":{"lch":[83.0014816422074375,40.0957403917498354,192.177050630060734],"luv":[83.0014816422074375,-39.1936046909777,-8.4575261684472629],"rgb":[0.533333333333333326,0.866666666666666696,0.866666666666666696],"xyz":[0.490581912240886764,0.621657410473101191,0.778230817974706834],"hpluv":[192.177050630060734,100.308679558078737,83.0014816422074375],"hsluv":[192.177050630060734,61.0588228331018783,83.0014816422074375]},"#88ddee":{"lch":[83.5045459788204,44.8677054153188,210.184175125347622],"luv":[83.5045459788204,-38.7842593009493157,-22.5586395802706683],"rgb":[0.533333333333333326,0.866666666666666696,0.933333333333333348],"xyz":[0.514394092507061584,0.631182282579571208,0.903641634043230058],"hpluv":[210.184175125347622,116.175045715242419,83.5045459788204],"hsluv":[210.184175125347622,62.7244468832174746,83.5045459788204]},"#88ddff":{"lch":[84.0516404633952732,53.2556266987753659,223.883407592331508],"luv":[84.0516404633952732,-38.3840933399078779,-36.9164347351224436],"rgb":[0.533333333333333326,0.866666666666666696,1],"xyz":[0.540565140916892894,0.641650701943503932,1.04147582233501179],"hpluv":[223.883407592331508,143.298172182841085,84.0516404633952732],"hsluv":[223.883407592331508,99.9999999999952,84.0516404633952732]},"#335500":{"lch":[32.2593993637483862,41.1235506245754365,113.326494368716226],"luv":[32.2593993637483862,-16.2836990313566261,37.7622504868051223],"rgb":[0.2,0.333333333333333315,0],"xyz":[0.0461356744276991415,0.0720065112172806193,0.0114678000018764836],"hpluv":[113.326494368716226,161.760937136611716,32.2593993637483862],"hsluv":[113.326494368716226,100.000000000002288,32.2593993637483862]},"#335511":{"lch":[32.3496341583576381,38.1897920123001313,115.090818108356473],"luv":[32.3496341583576381,-16.1945453684027605,34.5860797757347456],"rgb":[0.2,0.333333333333333315,0.0666666666666666657],"xyz":[0.0471473399273362598,0.0724111774171354722,0.016795904966632115],"hpluv":[115.090818108356473,149.801873896373706,32.3496341583576381],"hsluv":[115.090818108356473,90.8995446090399923,32.3496341583576381]},"#335522":{"lch":[32.5160201858231659,33.1206139518783189,118.966642902489184],"luv":[32.5160201858231659,-16.0403246718637718,28.9772851207727022],"rgb":[0.2,0.333333333333333315,0.133333333333333331],"xyz":[0.0490226980658132819,0.0731613206725262866,0.0266727911626113111],"hpluv":[118.966642902489184,129.252907346834121,32.5160201858231659],"hsluv":[118.966642902489184,74.935129302234273,32.5160201858231659]},"#335533":{"lch":[32.7875119073456176,25.8516304293262671,127.715012949238741],"luv":[32.7875119073456176,-15.8143300747053051,20.4502753072602665],"rgb":[0.2,0.333333333333333315,0.2],"xyz":[0.0521104487982710224,0.0743964209655094,0.0429349450202224578],"hpluv":[127.715012949238741,100.050394151032577,32.7875119073456176],"hsluv":[127.715012949238741,50.9434831873252207,32.7875119073456176]},"#335544":{"lch":[33.1742322541989836,18.1915220066791647,148.674883917516439],"luv":[33.1742322541989836,-15.539762262897943,9.45765624941535421],"rgb":[0.2,0.333333333333333315,0.266666666666666663],"xyz":[0.0565684440424899,0.0761796190631969794,0.0664137199731090894],"hpluv":[148.674883917516439,69.5836942134034899,33.1742322541989836],"hsluv":[148.674883917516439,54.5088767633859703,33.1742322541989836]},"#335555":{"lch":[33.6821363315134121,15.5994691341387064,192.177050630060819],"luv":[33.6821363315134121,-15.2484882598238034,-3.29044724269541522],"rgb":[0.2,0.333333333333333315,0.333333333333333315],"xyz":[0.0625308580818519,0.0785645846789418123,0.097815767247083],"hpluv":[192.177050630060819,58.7691644617976934,33.6821363315134121],"hsluv":[192.177050630060819,58.539124710901028,33.6821363315134121]},"#335566":{"lch":[34.3136156967701496,22.6822476529859181,228.692277460856218],"luv":[34.3136156967701496,-14.9726179113300351,-17.0383412183435361],"rgb":[0.2,0.333333333333333315,0.4],"xyz":[0.0701158538553600663,0.0815985829883451308,0.137763411654226953],"hpluv":[228.692277460856218,83.8800984368335,34.3136156967701496],"hsluv":[228.692277460856218,62.7386213411417089,34.3136156967701496]},"#335577":{"lch":[35.0679836745485218,34.4527831327976131,244.673076132176305],"luv":[35.0679836745485218,-14.7383029974912176,-31.1412377780608658],"rgb":[0.2,0.333333333333333315,0.466666666666666674],"xyz":[0.0794298668755619858,0.0853241881964259402,0.186817213560624862],"hpluv":[244.673076132176305,124.667382519216758,35.0679836745485218],"hsluv":[244.673076132176305,66.8604241763398335,35.0679836745485218]},"#335588":{"lch":[35.9419713942028523,47.4274747217606318,252.117898483801355],"luv":[35.9419713942028523,-14.5630489263951493,-45.1362710516793229],"rgb":[0.2,0.333333333333333315,0.533333333333333326],"xyz":[0.0905702839775058138,0.089780355037203538,0.245490076964197029],"hpluv":[252.117898483801355,167.443168522882189,35.9419713942028523],"hsluv":[252.117898483801355,70.7327730687023433,35.9419713942028523]},"#335599":{"lch":[36.9302538454711851,60.4953772811161272,256.174865065393647],"luv":[36.9302538454711851,-14.4559426241851021,-58.7427986669927833],"rgb":[0.2,0.333333333333333315,0.6],"xyz":[0.103627248086578527,0.0950031406808327,0.314256754605314936],"hpluv":[256.174865065393647,207.863972679723531,36.9302538454711851],"hsluv":[256.174865065393647,74.2581677802949258,36.9302538454711851]},"#3355aa":{"lch":[38.0259842211890557,73.2582460718320903,258.648348715518409],"luv":[38.0259842211890557,-14.4194259870406505,-71.8251402485603165],"rgb":[0.2,0.333333333333333315,0.66666666666666663],"xyz":[0.118684941051831069,0.101026217866933804,0.393560604222313537],"hpluv":[258.648348715518409,244.464262316607687,38.0259842211890557],"hsluv":[258.648348715518409,77.3978910060545,38.0259842211890557]},"#3355bb":{"lch":[39.2213032744107579,85.5750988898230815,260.277622363739169],"luv":[39.2213032744107579,-14.4514388960387397,-84.3460340729607623],"rgb":[0.2,0.333333333333333315,0.733333333333333282],"xyz":[0.135822533159167702,0.107881254709868563,0.483818589320955283],"hpluv":[260.277622363739169,276.862869377010384,39.2213032744107579],"hsluv":[260.277622363739169,80.1529964351826578,39.2213032744107579]},"#3355cc":{"lch":[40.5077939091134667,97.4185991778777,261.412040351160215],"luv":[40.5077939091134667,-14.5472816309580448,-96.326320717286734],"rgb":[0.2,0.333333333333333315,0.8],"xyz":[0.155114908602889456,0.115598204887357364,0.585425099991225495],"hpluv":[261.412040351160215,305.17054630009352,40.5077939091134667],"hsluv":[261.412040351160215,82.5478264076183734,40.5077939091134667]},"#3355dd":{"lch":[41.8768615158020552,108.813506268261335,262.235450095721887],"luv":[41.8768615158020552,-14.7009821832840935,-107.815862790406285],"rgb":[0.2,0.333333333333333315,0.866666666666666696],"xyz":[0.176633234153523,0.124205535107610898,0.698754947891231493],"hpluv":[262.235450095721887,329.72206067647727,41.8768615158020552],"hsluv":[262.235450095721887,84.6180359154754456,41.8768615158020552]},"#3355ee":{"lch":[43.3200322197542533,119.805986402952101,262.852770803428143],"luv":[43.3200322197542533,-14.9061911990543372,-118.875059797762361],"rgb":[0.2,0.333333333333333315,0.933333333333333348],"xyz":[0.200445414419697737,0.133730407214080915,0.824165763959754716],"hpluv":[262.852770803428143,350.936931775297865,43.3200322197542533],"hsluv":[262.852770803428143,90.8055999978327577,43.3200322197542533]},"#3355ff":{"lch":[44.8291710285026497,130.447860525532377,263.327743444412704],"luv":[44.8291710285026497,-15.1567128937849134,-129.564340657235334],"rgb":[0.2,0.333333333333333315,1],"xyz":[0.226616462829529131,0.144198826578013639,0.961999952251536561],"hpluv":[263.327743444412704,369.245812735261836,44.8291710285026497],"hsluv":[263.327743444412704,99.9999999999993,44.8291710285026497]},"#aadd00":{"lch":[81.9783608763648175,97.3184216433040916,105.014728605041086],"luv":[81.9783608763648175,-25.2120246284188454,93.9958988747909245],"rgb":[0.66666666666666663,0.866666666666666696,0],"xyz":[0.424325128525832707,0.602582536713324846,0.0939549564608566229],"hpluv":[105.014728605041086,227.603505169437568,81.9783608763648175],"hsluv":[105.014728605041086,100.000000000002203,81.9783608763648175]},"#aadd11":{"lch":[82.0002885274849262,96.374791846509865,105.167446282879951],"luv":[82.0002885274849262,-25.2155818179290208,93.017605521973266],"rgb":[0.66666666666666663,0.866666666666666696,0.0666666666666666657],"xyz":[0.425336794025469811,0.602987202913179754,0.0992830614256122596],"hpluv":[105.167446282879951,225.71449396257529,82.0002885274849262],"hsluv":[105.167446282879951,98.8971907906987298,82.0002885274849262]},"#aadd22":{"lch":[82.0409106120811,94.6380623122949345,105.456830413527484],"luv":[82.0409106120811,-25.2222030700150874,91.2151484706391216],"rgb":[0.66666666666666663,0.866666666666666696,0.133333333333333331],"xyz":[0.427212152163946868,0.603737346168570554,0.109159947621591452],"hpluv":[105.456830413527484,222.227322886837186,82.0409106120811],"hsluv":[105.456830413527484,96.86659260915998,82.0409106120811]},"#aadd33":{"lch":[82.1077210543303693,91.8137349028061891,105.951891130476156],"luv":[82.1077210543303693,-25.2331804702422886,88.2782448860360773],"rgb":[0.66666666666666663,0.866666666666666696,0.2],"xyz":[0.430299902896404574,0.604972446461553681,0.125422101479202602],"hpluv":[105.951891130476156,216.526835376233663,82.1077210543303693],"hsluv":[105.951891130476156,93.5615293661406469,82.1077210543303693]},"#aadd44":{"lch":[82.204019596801416,87.812555976334508,106.710442618715334],"luv":[82.204019596801416,-25.2491908313752447,84.1042409718896238],"rgb":[0.66666666666666663,0.866666666666666696,0.266666666666666663],"xyz":[0.434757898140623489,0.606755644559241247,0.148900876432089241],"hpluv":[106.710442618715334,208.386709262610594,82.204019596801416],"hsluv":[106.710442618715334,88.8720213109455415,82.204019596801416]},"#aadd55":{"lch":[82.332521082647844,82.6008871447080537,107.814707884186447],"luv":[82.332521082647844,-25.2708912490316564,78.6402480449573],"rgb":[0.66666666666666663,0.866666666666666696,0.333333333333333315],"xyz":[0.440720312179985474,0.609140610174986,0.180302923706063156],"hpluv":[107.814707884186447,197.666387369374576,82.332521082647844],"hsluv":[107.814707884186447,82.7472331150865,82.332521082647844]},"#aadd66":{"lch":[82.495508489392364,76.2000100439918526,109.390646830849064],"luv":[82.495508489392364,-25.2989483474785786,71.8777068583581666],"rgb":[0.66666666666666663,0.866666666666666696,0.4],"xyz":[0.448305307953493659,0.612174608484389315,0.22025056811320709],"hpluv":[109.390646830849064,184.308617744019813,82.495508489392364],"hsluv":[109.390646830849064,75.1895211365387723,82.495508489392364]},"#aadd77":{"lch":[82.694914273715753,68.6905071379487,111.642517734809914],"luv":[82.694914273715753,-25.3340491820501299,63.8480361711309499],"rgb":[0.66666666666666663,0.866666666666666696,0.466666666666666674],"xyz":[0.457619320973695565,0.615900213692470166,0.269304370019605],"hpluv":[111.642517734809914,168.351618208890358,82.694914273715753],"hsluv":[111.642517734809914,66.2494286969421182,82.694914273715753]},"#aadd88":{"lch":[82.9323686283524921,60.2252781448786436,114.920875432447886],"luv":[82.9323686283524921,-25.3769003534370228,54.6177357282387277],"rgb":[0.66666666666666663,0.866666666666666696,0.533333333333333326],"xyz":[0.468759738075639365,0.620356380533247709,0.327977233423177195],"hpluv":[114.920875432447886,149.967217229555729,82.9323686283524921],"hsluv":[114.920875432447886,56.0198042099318698,82.9323686283524921]},"#aadd99":{"lch":[83.2092305924335,51.0640475908324305,119.865599423026282],"luv":[83.2092305924335,-25.4282188712646082,44.2825320120006438],"rgb":[0.66666666666666663,0.866666666666666696,0.6],"xyz":[0.481816702184712065,0.625579166176876922,0.396743911064295074],"hpluv":[119.865599423026282,129.562195810811914,83.2092305924335],"hsluv":[119.865599423026282,44.6286172342680487,83.2092305924335]},"#aaddaa":{"lch":[83.526609727912188,41.6663179647472717,127.715012949236481],"luv":[83.526609727912188,-25.4887175141036408,32.9606937461220255],"rgb":[0.66666666666666663,0.866666666666666696,0.66666666666666663],"xyz":[0.496874395149964621,0.631602243362978,0.476047760681293675],"hpluv":[127.715012949236481,108.050849780995421,83.526609727912188],"hsluv":[127.715012949236481,32.2306770176982198,83.526609727912188]},"#aaddbb":{"lch":[83.8853825066367449,32.9442078204095523,140.880295511025736],"luv":[83.8853825066367449,-25.5590871805440472,20.7859060762739638],"rgb":[0.66666666666666663,0.866666666666666696,0.733333333333333282],"xyz":[0.514011987257301239,0.638457280205912747,0.566305745779935421],"hpluv":[140.880295511025736,87.605014056209555,83.8853825066367449],"hsluv":[140.880295511025736,34.4766875289621382,83.8853825066367449]},"#aaddcc":{"lch":[84.2862057978904602,26.8294893367150316,162.87488866986746],"luv":[84.2862057978904602,-25.639978502468459,7.90018990036700242],"rgb":[0.66666666666666663,0.866666666666666696,0.8],"xyz":[0.533304362701023,0.646174230383401604,0.667912256450205577],"hpluv":[162.87488866986746,73.4171355960865526,84.2862057978904602],"hsluv":[162.87488866986746,36.8333761539634708,84.2862057978904602]},"#aadddd":{"lch":[84.729528894444158,26.3242685722419552,192.177050630060421],"luv":[84.729528894444158,-25.7319846477226655,-5.55266440124834],"rgb":[0.66666666666666663,0.866666666666666696,0.866666666666666696],"xyz":[0.554822688251656593,0.654781560603655111,0.781242104350211575],"hpluv":[192.177050630060421,74.4077864529294146,84.729528894444158],"hsluv":[192.177050630060421,39.269697519551606,84.729528894444158]},"#aaddee":{"lch":[85.2156049558348769,32.3281965376105802,216.94937298104162],"luv":[85.2156049558348769,-25.8356267715816657,-19.4327733659894548],"rgb":[0.66666666666666663,0.866666666666666696,0.933333333333333348],"xyz":[0.578634868517831302,0.664306432710125128,0.906652920418734798],"hpluv":[216.94937298104162,94.7745998726022094,85.2156049558348769],"hsluv":[216.94937298104162,58.4216362813771397,85.2156049558348769]},"#aaddff":{"lch":[85.744502396509489,42.4619511969095527,232.326067904807843],"luv":[85.744502396509489,-25.9513430438233641,-33.608705623253762],"rgb":[0.66666666666666663,0.866666666666666696,1],"xyz":[0.604805916927662723,0.674774852074057852,1.04448710871051675],"hpluv":[232.326067904807843,129.682154580054771,85.744502396509489],"hsluv":[232.326067904807843,99.9999999999945572,85.744502396509489]},"#88ee00":{"lch":[85.1906878331824515,112.448241602139106,116.535675589642423],"luv":[85.1906878331824515,-50.2368100475369914,100.602534538950536],"rgb":[0.533333333333333326,0.933333333333333348,0],"xyz":[0.40726312885557775,0.663815939263801891,0.106669928865523039],"hpluv":[116.535675589642423,329.03324103323672,85.1906878331824515],"hsluv":[116.535675589642423,100.000000000002416,85.1906878331824515]},"#88ee11":{"lch":[85.2112458075113182,111.594873497969587,116.730132104203335],"luv":[85.2112458075113182,-50.1941202672300193,99.669283541253],"rgb":[0.533333333333333326,0.933333333333333348,0.0666666666666666657],"xyz":[0.408274794355214854,0.664220605463656799,0.111998033830278676],"hpluv":[116.730132104203335,327.047318494663614,85.2112458075113182],"hsluv":[116.730132104203335,98.9939616796445,85.2112458075113182]},"#88ee22":{"lch":[85.2493327369145,110.025246585506409,117.096539077460619],"luv":[85.2493327369145,-50.115524286233132,97.9489107224652429],"rgb":[0.533333333333333326,0.933333333333333348,0.133333333333333331],"xyz":[0.410150152493691911,0.6649707487190476,0.121874920026257869],"hpluv":[117.096539077460619,323.384561507736407,85.2493327369145],"hsluv":[117.096539077460619,97.140453749143191,85.2493327369145]},"#88ee33":{"lch":[85.3119799721786,107.475578977757436,117.717135468026783],"luv":[85.3119799721786,-49.9876247553973769,95.1432469906181097],"rgb":[0.533333333333333326,0.933333333333333348,0.2],"xyz":[0.413237903226149617,0.666205849012030726,0.138137073883869],"hpluv":[117.717135468026783,317.406918528502,85.3119799721786],"hsluv":[117.717135468026783,94.120593299189423,85.3119799721786]},"#88ee44":{"lch":[85.4022915890189864,103.870397610997969,118.652974854946393],"luv":[85.4022915890189864,-49.8062112723248518,91.1504296126099],"rgb":[0.533333333333333326,0.933333333333333348,0.266666666666666663],"xyz":[0.417695898470368532,0.667989047109718292,0.161615848836755643],"hpluv":[118.652974854946393,308.894438519259097,85.4022915890189864],"hsluv":[118.652974854946393,89.8292917088674869,85.4022915890189864]},"#88ee55":{"lch":[85.5228293578601466,99.1885702075232,119.98340282305692],"luv":[85.5228293578601466,-49.5693999595221584,85.9141842041562],"rgb":[0.533333333333333326,0.933333333333333348,0.333333333333333315],"xyz":[0.423658312509730517,0.670374012725463,0.193017896110729559],"hpluv":[119.98340282305692,297.731707367046795,85.5228293578601466],"hsluv":[119.98340282305692,84.2131356884780473,85.5228293578601466]},"#88ee66":{"lch":[85.6757572108422,93.4644574192068234,121.818598205465591],"luv":[85.6757572108422,-49.2774194314266083,79.4187681524083189],"rgb":[0.533333333333333326,0.933333333333333348,0.4],"xyz":[0.431243308283238702,0.673408011034866361,0.232965540517873521],"hpluv":[121.818598205465591,283.912655540997662,85.6757572108422],"hsluv":[121.818598205465591,77.2651144072775082,85.6757572108422]},"#88ee77":{"lch":[85.8629182835971676,86.7937408847250822,124.317503927832064],"luv":[85.8629182835971676,-48.9324360738715,71.6852157466327071],"rgb":[0.533333333333333326,0.933333333333333348,0.466666666666666674],"xyz":[0.440557321303440608,0.677133616242947212,0.282019342424271402],"hpluv":[124.317503927832064,267.563092583833793,85.8629182835971676],"hsluv":[124.317503927832064,69.0205357789205749,85.8629182835971676]},"#88ee88":{"lch":[86.0858807036169793,79.3454652904755164,127.71501294923921],"luv":[86.0858807036169793,-48.5383458294846,62.7672832477191918],"rgb":[0.533333333333333326,0.933333333333333348,0.533333333333333326],"xyz":[0.451697738405384408,0.681589783083724754,0.340692205827843597],"hpluv":[127.71501294923921,248.989760930573482,86.0858807036169793],"hsluv":[127.71501294923921,59.5524101967812,86.0858807036169793]},"#88ee99":{"lch":[86.3459670558122525,71.3853284581525429,132.362204285947513],"luv":[86.3459670558122525,-48.1005130697284287,52.7466184841000825],"rgb":[0.533333333333333326,0.933333333333333348,0.6],"xyz":[0.464754702514457163,0.686812568727354,0.409458883468961532],"hpluv":[132.362204285947513,228.778132650246619,86.3459670558122525],"hsluv":[132.362204285947513,60.5562348819982645,86.3459670558122525]},"#88eeaa":{"lch":[86.6442747471204768,63.319361027400987,138.776693085718904],"luv":[86.6442747471204768,-47.625461320552418,41.7271723811105204],"rgb":[0.533333333333333326,0.933333333333333348,0.66666666666666663],"xyz":[0.479812395479709664,0.692835645913455,0.488762733085960077],"hpluv":[138.776693085718904,207.981038552319745,86.6442747471204768],"hsluv":[138.776693085718904,61.6537348625427342,86.6442747471204768]},"#88eebb":{"lch":[86.9816911545789679,55.7684583245382299,147.664608842749317],"luv":[86.9816911545789679,-47.1205330954276,29.8291184029711189],"rgb":[0.533333333333333326,0.933333333333333348,0.733333333333333282],"xyz":[0.496949987587046338,0.699690682756389792,0.579020718184601879],"hpluv":[147.664608842749317,188.458500832318975,86.9816911545789679],"hsluv":[147.664608842749317,62.830800627143077,86.9816911545789679]},"#88eecc":{"lch":[87.3589058048410294,49.6608679924305463,159.75715297219557],"luv":[87.3589058048410294,-46.5935415809549696,17.182656741768227],"rgb":[0.533333333333333326,0.933333333333333348,0.8],"xyz":[0.516242363030768092,0.70740763293387865,0.680627228854872],"hpluv":[159.75715297219557,173.371642714007834,87.3589058048410294],"hsluv":[159.75715297219557,64.0722902507549179,87.3589058048410294]},"#88eedd":{"lch":[87.7764209496729,46.2191498548509543,175.132102674355139],"luv":[87.7764209496729,-46.0524373199716166,3.92209512827700335],"rgb":[0.533333333333333326,0.933333333333333348,0.866666666666666696],"xyz":[0.53776068858140158,0.716014963154132156,0.793957076754878],"hpluv":[175.132102674355139,167.447502067072264,87.7764209496729],"hsluv":[175.132102674355139,65.3626972838926434,87.7764209496729]},"#88eeee":{"lch":[88.2345613859691866,46.5524177333431339,192.177050630060933],"luv":[88.2345613859691866,-45.5050097647113958,-9.8194543195231],"rgb":[0.533333333333333326,0.933333333333333348,0.933333333333333348],"xyz":[0.56157286884757629,0.725539835260602173,0.919367892823401256],"hpluv":[192.177050630060933,175.887543813927181,88.2345613859691866],"hsluv":[192.177050630060933,66.6867488369664443,88.2345613859691866]},"#88eeff":{"lch":[88.7334840469836763,50.9233073192915242,208.009521596121829],"luv":[88.7334840469836763,-44.9586380478967271,-23.9145163700465169],"rgb":[0.533333333333333326,0.933333333333333348,1],"xyz":[0.587743917257407711,0.736008254624534897,1.05720208111518299],"hpluv":[208.009521596121829,201.749007974481685,88.7334840469836763],"hsluv":[208.009521596121829,99.9999999999925109,88.7334840469836763]},"#336600":{"lch":[38.2101034680229574,51.4017776291135888,118.130952889189317],"luv":[38.2101034680229574,-24.2353400261634,45.3298029694491902],"rgb":[0.2,0.4,0],"xyz":[0.0611637321335456105,0.10206262662897396,0.0164771525704918292],"hpluv":[118.130952889189317,170.702252266418213,38.2101034680229574],"hsluv":[118.130952889189317,100.000000000002288,38.2101034680229574]},"#336611":{"lch":[38.2816545292110959,48.9828222693822468,119.470954908934345],"luv":[38.2816545292110959,-24.0986808399199681,42.6447002480913682],"rgb":[0.2,0.4,0.0666666666666666657],"xyz":[0.0621753976331827357,0.102467292828828813,0.021805257535247459],"hpluv":[119.470954908934345,162.365005406289157,38.2816545292110959],"hsluv":[119.470954908934345,93.5286374368429,38.2816545292110959]},"#336622":{"lch":[38.4137944304132617,44.7307250918699282,122.230818066602779],"luv":[38.4137944304132617,-23.8562978467226365,37.8380076152656173],"rgb":[0.2,0.4,0.133333333333333331],"xyz":[0.0640507557716597509,0.103217436084219627,0.0316821437312266585],"hpluv":[122.230818066602779,147.760399550800031,38.4137944304132617],"hsluv":[122.230818066602779,81.994947572555219,38.4137944304132617]},"#336633":{"lch":[38.6299730126545171,38.3921679396875817,127.715012949239437],"luv":[38.6299730126545171,-23.4858075099586969,30.3706339201924216],"rgb":[0.2,0.4,0.2],"xyz":[0.0671385065041174844,0.10445253637720274,0.0479442975888378],"hpluv":[127.715012949239437,126.112332565807833,38.6299730126545171],"hsluv":[127.715012949239437,64.2136550115152,38.6299730126545171]},"#336644":{"lch":[38.9390987599147635,30.7877900918170191,138.353415806708398],"luv":[38.9390987599147635,-23.0064236741332095,20.4595329483365589],"rgb":[0.2,0.4,0.266666666666666663],"xyz":[0.0715965017483363719,0.10623573447489032,0.0714230725417244472],"hpluv":[138.353415806708398,100.330262339301328,38.9390987599147635],"hsluv":[138.353415806708398,66.1490613915476899,38.9390987599147635]},"#336655":{"lch":[39.3471830293532108,24.0314899024670439,159.111050143656939],"luv":[39.3471830293532108,-22.4519783641565418,8.56861566811244479],"rgb":[0.2,0.4,0.333333333333333315],"xyz":[0.077558915787698357,0.108620700090635153,0.102825119815698349],"hpluv":[159.111050143656939,77.5008343503898089,39.3471830293532108],"hsluv":[159.111050143656939,68.4324421599544337,39.3471830293532108]},"#336666":{"lch":[39.8577781510875653,22.3660784387423632,192.177050630061],"luv":[39.8577781510875653,-21.8628519700770774,-4.71775036033837925],"rgb":[0.2,0.4,0.4],"xyz":[0.0851439115612065422,0.111654698400038471,0.142772764222842297],"hpluv":[192.177050630061,71.205917149352544,39.8577781510875653],"hsluv":[192.177050630061,70.9271962998489727,39.8577781510875653]},"#336677":{"lch":[40.4722660639059,28.403364995264031,221.483563289625266],"luv":[40.4722660639059,-21.2782609928981294,-18.8145356618838697],"rgb":[0.2,0.4,0.466666666666666674],"xyz":[0.0944579245814084478,0.115380303608119281,0.191826566129240206],"hpluv":[221.483563289625266,89.0536244466218534,40.4722660639059],"hsluv":[221.483563289625266,73.4989606489913,40.4722660639059]},"#336688":{"lch":[41.1901179582142731,39.1584560294521253,238.034471274574031],"luv":[41.1901179582142731,-20.7308371309926542,-33.2207325394668516],"rgb":[0.2,0.4,0.533333333333333326],"xyz":[0.105598341683352276,0.119836470448896878,0.250499429532812401],"hpluv":[238.034471274574031,120.634589470818128,41.1901179582142731],"hsluv":[238.034471274574031,76.0346320246428746,41.1901179582142731]},"#336699":{"lch":[42.0091634944821948,51.6886413393569626,246.942440261812],"luv":[42.0091634944821948,-20.2441498032976277,-47.5593318103852951],"rgb":[0.2,0.4,0.6],"xyz":[0.118655305792425,0.12505925609252605,0.31926610717393028],"hpluv":[246.942440261812,156.131455895945,42.0091634944821948],"hsluv":[246.942440261812,78.4511744564818514,42.0091634944821948]},"#3366aa":{"lch":[42.9258754740709847,64.6951641030825,252.148217293940775],"luv":[42.9258754740709847,-19.832670948043944,-61.5802681172418218],"rgb":[0.2,0.4,0.66666666666666663],"xyz":[0.133712998757677531,0.131082333278627144,0.398569956790928881],"hpluv":[252.148217293940775,191.245834212653307,42.9258754740709847],"hsluv":[252.148217293940775,80.6959595489171,42.9258754740709847]},"#3366bb":{"lch":[43.9356615222631106,77.6311657782158164,255.449757662516049],"luv":[43.9356615222631106,-19.5031901130623,-75.1413566253536374],"rgb":[0.2,0.4,0.733333333333333282],"xyz":[0.150850590865014178,0.137937370121561903,0.488827941889570627],"hpluv":[255.449757662516049,224.211696450950683,43.9356615222631106],"hsluv":[255.449757662516049,82.7420790911240402,43.9356615222631106]},"#3366cc":{"lch":[45.0331492258045287,90.2591849706621332,257.681278432902445],"luv":[45.0331492258045287,-19.2567634880452658,-88.1810497302775786],"rgb":[0.2,0.4,0.8],"xyz":[0.170142966308735932,0.145654320299050705,0.590434452559840839],"hpluv":[257.681278432902445,254.330482568364204,45.0331492258045287],"hsluv":[257.681278432902445,84.5818015821218694,45.0331492258045287]},"#3366dd":{"lch":[46.2124513047425367,102.485732700579547,259.264483160570819],"luv":[46.2124513047425367,-19.0906003056708045,-100.691977769551045],"rgb":[0.2,0.4,0.866666666666666696],"xyz":[0.191661291859369476,0.154261650519304239,0.703764300459846837],"hpluv":[259.264483160570819,281.412724566330553,46.2124513047425367],"hsluv":[259.264483160570819,86.2202337385041488,46.2124513047425367]},"#3366ee":{"lch":[47.467400384741687,114.289765210034219,260.43068521754094],"luv":[47.467400384741687,-18.99960653492559,-112.699447129445844],"rgb":[0.2,0.4,0.933333333333333348],"xyz":[0.215473472125544213,0.163786522625774256,0.82917511652837006],"hpluv":[260.43068521754094,305.528142270574733,47.467400384741687],"hsluv":[260.43068521754094,89.4216395109538524,47.467400384741687]},"#3366ff":{"lch":[48.7917470574018068,125.686826272807437,261.315666926990161],"luv":[48.7917470574018068,-18.9775194272026404,-124.245853270525785],"rgb":[0.2,0.4,1],"xyz":[0.241644520535375606,0.17425494198970698,0.967009304820151905],"hpluv":[261.315666926990161,326.875761207371056,48.7917470574018068],"hsluv":[261.315666926990161,99.9999999999992184,48.7917470574018068]},"#aaee00":{"lch":[86.8465682321076713,106.130019137569278,108.773889799394041],"luv":[86.8465682321076713,-34.1562767274136,100.483479847491182],"rgb":[0.66666666666666663,0.933333333333333348,0],"xyz":[0.471503904866347523,0.696940089394355811,0.109681215241027807],"hpluv":[108.773889799394041,354.560190530248747,86.8465682321076713],"hsluv":[108.773889799394041,100.000000000002302,86.8465682321076713]},"#aaee11":{"lch":[86.8664697406872364,105.275413073012288,108.926122010215039],"luv":[86.8664697406872364,-34.1459453835818323,99.5839696515197801],"rgb":[0.66666666666666663,0.933333333333333348,0.0666666666666666657],"xyz":[0.472515570365984627,0.697344755594210719,0.115009320205783444],"hpluv":[108.926122010215039,352.296735211520456,86.8664697406872364],"hsluv":[108.926122010215039,99.0448212343627,86.8664697406872364]},"#aaee22":{"lch":[86.9033414770782286,103.701584155213482,109.21343759479339],"luv":[86.9033414770782286,-34.1269596340241961,97.9253245204656224],"rgb":[0.66666666666666663,0.933333333333333348,0.133333333333333331],"xyz":[0.474390928504461684,0.69809489884960152,0.124886206401762637],"hpluv":[109.21343759479339,348.114419217609168,86.9033414770782286],"hsluv":[109.21343759479339,97.2844700630890742,86.9033414770782286]},"#aaee33":{"lch":[86.9639927659971,101.139559122436452,109.701502859778287],"luv":[86.9639927659971,-34.0961634116812462,95.2190215245081504],"rgb":[0.66666666666666663,0.933333333333333348,0.2],"xyz":[0.47747867923691939,0.699329999142584646,0.141148360259373773],"hpluv":[109.701502859778287,341.266668172598315,86.9639927659971],"hsluv":[109.701502859778287,94.4148698146506,86.9639927659971]},"#aaee44":{"lch":[87.0514332975086091,97.5044422856038864,110.440992284795044],"luv":[87.0514332975086091,-34.052698770047833,91.3648180204122298],"rgb":[0.66666666666666663,0.933333333333333348,0.266666666666666663],"xyz":[0.481936674481138305,0.701113197240272212,0.164627135212260411],"hpluv":[110.440992284795044,331.464832239423686,87.0514332975086091],"hsluv":[110.440992284795044,90.3338544995677353,87.0514332975086091]},"#aaee55":{"lch":[87.1681505263978,92.7597711807761556,111.499860176168639],"luv":[87.1681505263978,-33.9963593100021271,86.3054036730909644],"rgb":[0.66666666666666663,0.933333333333333348,0.333333333333333315],"xyz":[0.48789908852050029,0.703498162856017,0.196029182486234327],"hpluv":[111.499860176168639,318.513853400728863,87.1681505263978],"hsluv":[111.499860176168639,84.9871568734489813,87.1681505263978]},"#aaee66":{"lch":[87.3162499846890086,86.9168013961255923,112.975973936880195],"luv":[87.3162499846890086,-33.9275471197994563,80.0215715377255492],"rgb":[0.66666666666666663,0.933333333333333348,0.4],"xyz":[0.495484084294008476,0.70653216116542028,0.235976826893378289],"hpluv":[112.975973936880195,302.308385752370668,87.3162499846890086],"hsluv":[112.975973936880195,78.3634586897027106,87.3162499846890086]},"#aaee77":{"lch":[87.4975302296396,80.0378594698754853,115.017197938190947],"luv":[87.4975302296396,-33.8472328521792534,72.5287789554594298],"rgb":[0.66666666666666663,0.933333333333333348,0.466666666666666674],"xyz":[0.504798097314210326,0.710257766373501132,0.285030628799776198],"hpluv":[115.017197938190947,282.845349503141222,87.4975302296396],"hsluv":[115.017197938190947,70.4907283307095,87.4975302296396]},"#aaee88":{"lch":[87.7135274362348838,72.2451165326571072,117.856267937731204],"luv":[87.7135274362348838,-33.7569011423620324,63.8735351149597861],"rgb":[0.66666666666666663,0.933333333333333348,0.533333333333333326],"xyz":[0.515938514416154237,0.714713933214278674,0.343703492203348393],"hpluv":[117.856267937731204,260.261444274219798,87.7135274362348838],"hsluv":[117.856267937731204,61.4321883079204412,87.7135274362348838]},"#aaee99":{"lch":[87.9655440812905312,63.7405265694191954,121.874104620002555],"luv":[87.9655440812905312,-33.6584769753751445,54.1291202131068871],"rgb":[0.66666666666666663,0.933333333333333348,0.6],"xyz":[0.528995478525226881,0.719936718857907887,0.412470169844466272],"hpluv":[121.874104620002555,234.922523447188695,87.9655440812905312],"hsluv":[121.874104620002555,51.2814060811362182,87.9655440812905312]},"#aaeeaa":{"lch":[88.2546687059401,54.8509913255605497,127.715012949237604],"luv":[88.2546687059401,-33.5542349686064441,43.3906045713616138],"rgb":[0.66666666666666663,0.933333333333333348,0.66666666666666663],"xyz":[0.544053171490479492,0.725959796044009,0.491774019461464873],"hpluv":[127.715012949237604,207.631017102058365,88.2546687059401],"hsluv":[127.715012949237604,42.8122115000723795,88.2546687059401]},"#aaeebb":{"lch":[88.5817905154621457,46.1299748711590425,136.47329364537066],"luv":[88.5817905154621457,-33.4466969972147226,31.7693726974624511],"rgb":[0.66666666666666663,0.933333333333333348,0.733333333333333282],"xyz":[0.561190763597816056,0.732814832886943712,0.582032004560106619],"hpluv":[136.47329364537066,180.106084736741337,88.5817905154621457],"hsluv":[136.47329364537066,42.5306558804052,88.5817905154621457]},"#aaeecc":{"lch":[88.947610994722524,38.5659339652702471,149.820563383504265],"luv":[88.947610994722524,-33.3385252257337896,19.3874701388989088],"rgb":[0.66666666666666663,0.933333333333333348,0.8],"xyz":[0.58048313904153781,0.740531783064432569,0.683638515230376775],"hpluv":[149.820563383504265,156.025185046421541,88.947610994722524],"hsluv":[149.820563383504265,43.7743007306855176,88.947610994722524]},"#aaeedd":{"lch":[89.3526538659385636,33.8378115459028308,169.14561851222],"luv":[89.3526538659385636,-33.2324178366612202,6.37211856022751721],"rgb":[0.66666666666666663,0.933333333333333348,0.866666666666666696],"xyz":[0.602001464592171409,0.749139113284686076,0.796968363130382773],"hpluv":[169.14561851222,142.575756051086472,89.3526538659385636],"hsluv":[169.14561851222,45.7128350403065866,89.3526538659385636]},"#aaeeee":{"lch":[89.797274219494,33.893604395025335,192.177050630060734],"luv":[89.797274219494,-33.1310138990311174,-7.14928925898844092],"rgb":[0.66666666666666663,0.933333333333333348,0.933333333333333348],"xyz":[0.625813644858346119,0.758663985391156093,0.922379179198906],"hpluv":[192.177050630060734,149.574468983420843,89.797274219494],"hsluv":[192.177050630060734,47.7079369778472326,89.797274219494]},"#aaeeff":{"lch":[90.2816673401601406,39.1749897548907384,212.508271358442045],"luv":[90.2816673401601406,-33.0368122621910558,-21.0534761464356919],"rgb":[0.66666666666666663,0.933333333333333348,1],"xyz":[0.65198469326817754,0.769132404755088817,1.06021336749068773],"hpluv":[212.508271358442045,182.211685385120148,90.2816673401601406],"hsluv":[212.508271358442045,99.9999999999910898,90.2816673401601406]},"#88ff00":{"lch":[90.2073775103659727,121.530167505498795,118.25137340908573],"luv":[90.2073775103659727,-57.5251845782800331,107.053420090856534],"rgb":[0.533333333333333326,1,0],"xyz":[0.459115501285251582,0.767520684123151,0.12395405300874715],"hpluv":[118.25137340908573,560.639311859311,90.2073775103659727],"hsluv":[118.25137340908573,100.00000000000226,90.2073775103659727]},"#88ff11":{"lch":[90.2260397586701828,120.75410845816802,118.424372307304225],"luv":[90.2260397586701828,-57.4787561773275684,106.196738640291272],"rgb":[0.533333333333333326,1,0.0666666666666666657],"xyz":[0.460127166784888686,0.767925350323005906,0.129282157973502787],"hpluv":[118.424372307304225,558.207032378019221,90.2260397586701828],"hsluv":[118.424372307304225,99.9999999999909335,90.2260397586701828]},"#88ff22":{"lch":[90.260617257984066,119.32542599803422,118.749452026898098],"luv":[90.260617257984066,-57.393189210317729,104.616342518179295],"rgb":[0.533333333333333326,1,0.133333333333333331],"xyz":[0.462002524923365743,0.768675493578396707,0.139159044169481966],"hpluv":[118.749452026898098,553.71568515647823,90.260617257984066],"hsluv":[118.749452026898098,99.9999999999907772,90.260617257984066]},"#88ff33":{"lch":[90.3174996442954665,117.001153508636776,119.297411154505227],"luv":[90.3174996442954665,-57.253701051451273,102.035697862378711],"rgb":[0.533333333333333326,1,0.2],"xyz":[0.465090275655823449,0.769910593871379834,0.155421198027093116],"hpluv":[119.297411154505227,546.370637823869743,90.3174996442954665],"hsluv":[119.297411154505227,99.9999999999907914,90.3174996442954665]},"#88ff44":{"lch":[90.399517385893148,113.706822542904789,120.117552028257023],"luv":[90.399517385893148,-57.0553255590242614,98.3561452994036074],"rgb":[0.533333333333333326,1,0.266666666666666663],"xyz":[0.469548270900042364,0.7716937919690674,0.178899972979979754],"hpluv":[120.117552028257023,535.877566613280692,90.399517385893148],"hsluv":[120.117552028257023,99.9999999999907914,90.399517385893148]},"#88ff55":{"lch":[90.5090160073098389,109.413894688598035,121.271093020798972],"luv":[90.5090160073098389,-56.7954345723420317,93.518334901057969],"rgb":[0.533333333333333326,1,0.333333333333333315],"xyz":[0.475510684939404349,0.774078757584812149,0.21030202025395367],"hpluv":[121.271093020798972,522.05545338002139,90.5090160073098389],"hsluv":[121.271093020798972,99.9999999999906493,90.5090160073098389]},"#88ff66":{"lch":[90.6479884721694,104.139810410505333,122.839359042112989],"luv":[90.6479884721694,-56.4735097148607039,87.4976731851854908],"rgb":[0.533333333333333326,1,0.4],"xyz":[0.483095680712912534,0.777112755894215468,0.250249664661097659],"hpluv":[122.839359042112989,504.839052288882328,90.6479884721694],"hsluv":[122.839359042112989,99.9999999999905498,90.6479884721694]},"#88ff77":{"lch":[90.8181461195308515,97.9515013566305441,124.934550835890477],"luv":[90.8181461195308515,-56.0909812525741813,80.3012978733306],"rgb":[0.533333333333333326,1,0.466666666666666674],"xyz":[0.49240969373311444,0.780838361102296319,0.299303466567495513],"hpluv":[124.934550835890477,484.301391198376791,90.8181461195308515],"hsluv":[124.934550835890477,99.9999999999904,90.8181461195308515]},"#88ff88":{"lch":[91.0209609702079803,90.9725812653771,127.715012949239437],"luv":[91.0209609702079803,-55.6510519447396348,71.9650676337452779],"rgb":[0.533333333333333326,1,0.533333333333333326],"xyz":[0.503550110835058295,0.785294527943073861,0.357976329971067708],"hpluv":[127.715012949239437,460.703998076760797,91.0209609702079803],"hsluv":[127.715012949239437,99.9999999999902087,91.0209609702079803]},"#88ff99":{"lch":[91.2576929391802167,83.3964386150156116,131.406800448379954],"luv":[91.2576929391802167,-55.158478848678719,62.5500454417735057],"rgb":[0.533333333333333326,1,0.6],"xyz":[0.51660707494413094,0.790517313586703074,0.426743007612185643],"hpluv":[131.406800448379954,434.595507650037121,91.2576929391802167],"hsluv":[131.406800448379954,99.9999999999900524,91.2576929391802167]},"#88ffaa":{"lch":[91.5294084976530229,75.5094657025462226,136.33125230150921],"luv":[91.5294084976530229,-54.6193101996060264,52.1383770748881048],"rgb":[0.533333333333333326,1,0.66666666666666663],"xyz":[0.531664767909383551,0.796540390772804141,0.506046857229184188],"hpluv":[136.33125230150921,406.99849880976177,91.5294084976530229],"hsluv":[136.33125230150921,99.9999999999897824,91.5294084976530229]},"#88ffbb":{"lch":[91.8369943060547911,67.7301008509963225,142.928263991524119],"luv":[91.8369943060547911,-54.0405872892441,40.8286846067776423],"rgb":[0.533333333333333326,1,0.733333333333333282],"xyz":[0.548802360016720114,0.8033954276157389,0.596304842327826],"hpluv":[142.928263991524119,379.751065707187763,91.8369943060547911],"hsluv":[142.928263991524119,99.9999999999894413,91.8369943060547911]},"#88ffcc":{"lch":[92.1811678623774498,60.665065650155249,151.731515164157571],"luv":[92.1811678623774498,-53.4300279465168941,28.7312078404662543],"rgb":[0.533333333333333326,1,0.8],"xyz":[0.568094735460441869,0.811112377793227757,0.697911352998096146],"hpluv":[151.731515164157571,356.080713038752435,92.1811678623774498],"hsluv":[151.731515164157571,99.9999999999893134,92.1811678623774498]},"#88ffdd":{"lch":[92.5624864174544371,55.1561732277505712,163.177123134509742],"luv":[92.5624864174544371,-52.7957106082625316,15.9629692256241533],"rgb":[0.533333333333333326,1,0.866666666666666696],"xyz":[0.589613061011075468,0.819719708013481263,0.811241200898102144],"hpluv":[163.177123134509742,341.369587308077,92.5624864174544371],"hsluv":[163.177123134509742,99.9999999999887,92.5624864174544371]},"#88ffee":{"lch":[92.9813549493531752,52.2127257219241301,177.098205352907513],"luv":[92.9813549493531752,-52.1457771028834927,2.64322864112605771],"rgb":[0.533333333333333326,1,0.933333333333333348],"xyz":[0.613425241277250177,0.82924458011995128,0.936652016966625367],"hpluv":[177.098205352907513,343.566349205584061,92.9813549493531752],"hsluv":[177.098205352907513,99.9999999999882,92.9813549493531752]},"#88ffff":{"lch":[93.4380337051328524,52.6732939730945162,192.177050630061075],"luv":[93.4380337051328524,-51.4881691068088543,-11.1105508416409933],"rgb":[0.533333333333333326,1,1],"xyz":[0.639596289687081598,0.839712999483884,1.07448620525840721],"hpluv":[192.177050630061075,372.044084252862206,93.4380337051328524],"hsluv":[192.177050630061075,99.9999999999874802,93.4380337051328524]},"#337700":{"lch":[44.0848685544221084,61.4877933810524127,120.932619831412623],"luv":[44.0848685544221084,-31.6065510805688668,52.7425318283298168],"rgb":[0.2,0.466666666666666674,0],"xyz":[0.0796174701869632462,0.138970102735809731,0.0226283985882975332],"hpluv":[120.932619831412623,176.985906279588789,44.0848685544221084],"hsluv":[120.932619831412623,100.000000000002217,44.0848685544221084]},"#337711":{"lch":[44.1431322932100159,59.4532082216814146,121.943929432148849],"luv":[44.1431322932100159,-31.4560442613915434,50.449987584497805],"rgb":[0.2,0.466666666666666674,0.0666666666666666657],"xyz":[0.0806291356866003645,0.139374768935664584,0.0279565035530531664],"hpluv":[121.943929432148849,170.903703930819205,44.1431322932100159],"hsluv":[121.943929432148849,95.223210781581642,44.1431322932100159]},"#337722":{"lch":[44.2508401312458517,55.8308883755444327,123.957293362486936],"luv":[44.2508401312458517,-31.1857277137109214,46.3091619851707605],"rgb":[0.2,0.466666666666666674,0.133333333333333331],"xyz":[0.0825044938250774,0.140124912191055412,0.037833389749032359],"hpluv":[123.957293362486936,160.100373243526178,44.2508401312458517],"hsluv":[123.957293362486936,86.6219708852072,44.2508401312458517]},"#337733":{"lch":[44.4273451577554681,50.2894934834324943,127.715012949239792],"luv":[44.4273451577554681,-30.7638100974309978,39.782171171385329],"rgb":[0.2,0.466666666666666674,0.2],"xyz":[0.0855922445575351271,0.141360012484038511,0.0540955436066435091],"hpluv":[127.715012949239792,143.636966976451419,44.4273451577554681],"hsluv":[127.715012949239792,73.1368174441878409,44.4273451577554681]},"#337744":{"lch":[44.6803728315295743,43.2379901525315873,134.305487238163835],"luv":[44.6803728315295743,-30.2010367205865329,30.9422231494797764],"rgb":[0.2,0.466666666666666674,0.266666666666666663],"xyz":[0.090050239801754,0.143143210581726105,0.0775743185595301477],"hpluv":[134.305487238163835,122.797079037201513,44.6803728315295743],"hsluv":[134.305487238163835,74.2422920898123664,44.6803728315295743]},"#337755":{"lch":[45.0155248592042057,35.7001949681147,145.791078733963843],"luv":[45.0155248592042057,-29.5238129364495734,20.071083439987369],"rgb":[0.2,0.466666666666666674,0.333333333333333315],"xyz":[0.096012653841116,0.145528176197470938,0.108976365833504049],"hpluv":[145.791078733963843,100.634662922797503,45.0155248592042057],"hsluv":[145.791078733963843,75.5860232244433377,45.0155248592042057]},"#337766":{"lch":[45.436632811343884,29.7520619336037022,165.22669317203713],"luv":[45.436632811343884,-28.7685269489331041,7.58663604567268468],"rgb":[0.2,0.466666666666666674,0.4],"xyz":[0.103597649614624171,0.148562174506874228,0.148924010240648025],"hpluv":[165.22669317203713,83.0902864995861847,45.436632811343884],"hsluv":[165.22669317203713,77.1054195363406194,45.436632811343884]},"#337777":{"lch":[45.9459628200325696,28.6191137838588361,192.177050630061018],"luv":[45.9459628200325696,-27.9751968985082726,-6.03672363647301413],"rgb":[0.2,0.466666666666666674,0.466666666666666674],"xyz":[0.11291166263482609,0.152287779714955052,0.197977812147045934],"hpluv":[192.177050630061018,79.0402219352416324,45.9459628200325696],"hsluv":[192.177050630061018,78.7308353184449743,45.9459628200325696]},"#337788":{"lch":[46.5443737533918309,33.948531272854666,216.805091226728479],"luv":[46.5443737533918309,-27.1818468531358306,-20.3383867904182836],"rgb":[0.2,0.466666666666666674,0.533333333333333326],"xyz":[0.124052079736769919,0.156743946555732649,0.256650675550618101],"hpluv":[216.805091226728479,92.5535593562344587,46.5443737533918309],"hsluv":[216.805091226728479,80.3955897349876381,46.5443737533918309]},"#337799":{"lch":[47.2314677007312085,43.7891028043947799,232.889035089769209],"luv":[47.2314677007312085,-26.4206199262946413,-34.9204290798973105],"rgb":[0.2,0.466666666666666674,0.6],"xyz":[0.137109043845842632,0.161966732199361807,0.325417353191736],"hpluv":[232.889035089769209,117.645124104106614,47.2314677007312085],"hsluv":[232.889035089769209,82.0429045074046144,47.2314677007312085]},"#3377aa":{"lch":[48.0057466772197472,55.756363166772573,242.534195481556935],"luv":[48.0057466772197472,-25.7159019754829359,-49.471854818395343],"rgb":[0.2,0.466666666666666674,0.66666666666666663],"xyz":[0.15216673681109516,0.167989809385462902,0.404721202808734581],"hpluv":[242.534195481556935,147.380673097935755,48.0057466772197472],"hsluv":[242.534195481556935,83.6292827510673078,48.0057466772197472]},"#3377bb":{"lch":[48.8647777502949623,68.5281348418467076,248.528316013511841],"luv":[48.8647777502949623,-25.0841318464231762,-63.7721851155626],"rgb":[0.2,0.466666666666666674,0.733333333333333282],"xyz":[0.169304328918431835,0.17484484622839766,0.494979187907376328],"hpluv":[248.528316013511841,177.955866809146045,48.8647777502949623],"hsluv":[248.528316013511841,85.1249045257873,48.8647777502949623]},"#3377cc":{"lch":[49.8053630390326845,81.4640551302433096,252.471981644912631],"luv":[49.8053630390326845,-24.5347040681135518,-77.6816617648812553],"rgb":[0.2,0.466666666666666674,0.8],"xyz":[0.188596704362153561,0.182561796405886462,0.596585698577646539],"hpluv":[252.471981644912631,207.553107999557341,49.8053630390326845],"hsluv":[252.471981644912631,86.5120902950020678,49.8053630390326845]},"#3377dd":{"lch":[50.8237086019957047,94.2508792352234,255.202895611269554],"luv":[50.8237086019957047,-24.0713820337122506,-91.1251710758325],"rgb":[0.2,0.466666666666666674,0.866666666666666696],"xyz":[0.210115029912787105,0.19116912662614,0.709915546477652537],"hpluv":[255.202895611269554,235.319753343529385,50.8237086019957047],"hsluv":[255.202895611269554,87.7828608732328,50.8237086019957047]},"#3377ee":{"lch":[51.9155858415672498,106.73807185779232,257.174602046687482],"luv":[51.9155858415672498,-23.6937959642247655,-104.075069141100855],"rgb":[0.2,0.466666666666666674,0.933333333333333348],"xyz":[0.233927210178961842,0.200693998732610041,0.83532636254617576],"hpluv":[257.174602046687482,260.892095272406607,51.9155858415672498],"hsluv":[257.174602046687482,88.9363454602875692,51.9155858415672498]},"#3377ff":{"lch":[53.0764799083082721,118.861737619173724,258.646767383963777],"luv":[53.0764799083082721,-23.3987809317452253,-116.535873106771263],"rgb":[0.2,0.466666666666666674,1],"xyz":[0.260098258588793207,0.211162418096542737,0.973160550837957605],"hpluv":[258.646767383963777,284.170694785425781,53.0764799083082721],"hsluv":[258.646767383963777,99.9999999999990763,53.0764799083082721]},"#aaff00":{"lch":[91.7137860391432156,115.080534629040301,111.722667154579099],"luv":[91.7137860391432156,-42.5929524944460596,106.908230966149674],"rgb":[0.66666666666666663,1,0],"xyz":[0.523356277296021299,0.800644834253704918,0.126965339384251918],"hpluv":[111.722667154579099,635.020942157405898,91.7137860391432156],"hsluv":[111.722667154579099,100.000000000002359,91.7137860391432156]},"#aaff11":{"lch":[91.7319300755291209,114.302910123776968,111.867287470019974],"luv":[91.7319300755291209,-42.5730312099484394,106.078707931238455],"rgb":[0.66666666666666663,1,0.0666666666666666657],"xyz":[0.524367942795658459,0.801049500453559826,0.132293444349007555],"hpluv":[111.867287470019974,632.205251281199821,91.7319300755291209],"hsluv":[111.867287470019974,99.9999999999902087,91.7319300755291209]},"#aaff22":{"lch":[91.76554812600844,112.870020698142184,112.139393409643191],"luv":[91.76554812600844,-42.5363318976714595,104.548084827461963],"rgb":[0.66666666666666663,1,0.133333333333333331],"xyz":[0.526243300934135405,0.801799643708950627,0.142170330544986734],"hpluv":[112.139393409643191,626.996151229530483,91.76554812600844],"hsluv":[112.139393409643191,99.9999999999901,91.76554812600844]},"#aaff33":{"lch":[91.8208541183991116,110.535111156119868,112.599114759903571],"luv":[91.8208541183991116,-42.4765495373732875,102.047800258971023],"rgb":[0.66666666666666663,1,0.2],"xyz":[0.529331051666593222,0.803034744001933753,0.158432484402597884],"hpluv":[112.599114759903571,618.449193227995465,91.8208541183991116],"hsluv":[112.599114759903571,99.9999999999900808,91.8208541183991116]},"#aaff44":{"lch":[91.9006031807778498,107.217215837920833,113.289723447654],"luv":[91.9006031807778498,-42.3916247074254713,98.4808688360338],"rgb":[0.66666666666666663,1,0.266666666666666663],"xyz":[0.533789046910812082,0.80481794209962132,0.181911259355484523],"hpluv":[113.289723447654,606.175591066234915,91.9006031807778498],"hsluv":[113.289723447654,99.9999999999900808,91.9006031807778498]},"#aaff55":{"lch":[92.0070808640835338,102.877427982590888,114.266397603879824],"luv":[92.0070808640835338,-42.2805422001356135,93.7876374559873796],"rgb":[0.66666666666666663,1,0.333333333333333315],"xyz":[0.539751460950174,0.807202907715366069,0.213313306629458438],"hpluv":[114.266397603879824,589.885725054723707,92.0070808640835338],"hsluv":[114.266397603879824,99.9999999999897,92.0070808640835338]},"#aaff66":{"lch":[92.142232175119787,97.5178938455906,115.604656391492952],"luv":[92.142232175119787,-42.1432392632638226,87.9413839126902559],"rgb":[0.66666666666666663,1,0.4],"xyz":[0.547336456723682252,0.810236906024769388,0.2532609510366024],"hpluv":[115.604656391492952,569.381090837871511,92.142232175119787],"hsluv":[115.604656391492952,99.9999999999898,92.142232175119787]},"#aaff77":{"lch":[92.3077308115560555,91.1840841453542197,117.412488820025033],"luv":[92.3077308115560555,-41.9805406670279666,80.9454841651530899],"rgb":[0.66666666666666663,1,0.466666666666666674],"xyz":[0.556650469743884102,0.813962511232850239,0.302314752943000309],"hpluv":[117.412488820025033,544.56608764574878,92.3077308115560555],"hsluv":[117.412488820025033,99.9999999999895692,92.3077308115560555]},"#aaff88":{"lch":[92.5050204995058749,83.9705472319660657,119.849478645386625],"luv":[92.5050204995058749,-41.7940850853900727,72.8306752289927601],"rgb":[0.66666666666666663,1,0.533333333333333326],"xyz":[0.567790886845828,0.818418678073627781,0.360987616346572504],"hpluv":[119.849478645386625,515.487838204951345,92.5050204995058749],"hsluv":[119.849478645386625,99.9999999999892708,92.5050204995058749]},"#aaff99":{"lch":[92.7353415895377,76.0327408171719,123.158131820453576],"luv":[92.7353415895377,-41.5862309318022625,63.6518897838709137],"rgb":[0.66666666666666663,1,0.6],"xyz":[0.580847850954900657,0.823641463717257,0.429754293987690383],"hpluv":[123.158131820453576,482.430180447041607,92.7353415895377],"hsluv":[123.158131820453576,99.9999999999891145,92.7353415895377]},"#aaffaa":{"lch":[92.9997492696274435,67.6109506527765802,127.715012949238414],"luv":[92.9997492696274435,-41.3599402641421108,53.4845397242865488],"rgb":[0.66666666666666663,1,0.66666666666666663],"xyz":[0.595905543920153269,0.829664540903358061,0.509058143604689],"hpluv":[127.715012949238414,446.121940639593902,92.9997492696274435],"hsluv":[127.715012949238414,99.9999999999887308,92.9997492696274435]},"#aaffbb":{"lch":[93.2991268167713201,59.0781485982363,134.10730048328],"luv":[93.2991268167713201,-41.1186450338129887,42.4203332421914823],"rgb":[0.66666666666666663,1,0.733333333333333282],"xyz":[0.613043136027489832,0.836519577746292819,0.599316128703330731],"hpluv":[134.10730048328,408.190288953842469,93.2991268167713201],"hsluv":[134.10730048328,99.9999999999883613,93.2991268167713201]},"#aaffcc":{"lch":[93.6341958749929404,51.0306218960527929,143.208028901391231],"luv":[93.6341958749929404,-40.8661030238149436,30.5628204644932246],"rgb":[0.66666666666666663,1,0.8],"xyz":[0.632335511471211587,0.844236527923781677,0.700922639373600886],"hpluv":[143.208028901391231,372.11656739719416,93.6341958749929404],"hsluv":[143.208028901391231,99.9999999999879492,93.6341958749929404]},"#aaffdd":{"lch":[94.005524978734,44.4262644213682094,156.066165366624773],"luv":[94.005524978734,-40.6062520520773305,18.0229094410556279],"rgb":[0.66666666666666663,1,0.866666666666666696],"xyz":[0.653853837021845186,0.852843858144035183,0.814252487273606884],"hpluv":[156.066165366624773,345.018188987702331,94.005524978734],"hsluv":[156.066165366624773,99.999999999986926,94.005524978734]},"#aaffee":{"lch":[94.4135370960349576,40.641316399200953,173.054449077896464],"luv":[94.4135370960349576,-40.3430708217409446,4.91459411670529711],"rgb":[0.66666666666666663,1,0.933333333333333348],"xyz":[0.677666017288019895,0.8623687302505052,0.939663303342130107],"hpluv":[173.054449077896464,339.745490646316398,94.4135370960349576],"hsluv":[173.054449077896464,99.9999999999862865,94.4135370960349576]},"#aaffff":{"lch":[94.8585166918378633,41.0030022313427764,192.177050630060705],"luv":[94.8585166918378633,-40.0804535568370639,-8.64889788711415264],"rgb":[0.66666666666666663,1,1],"xyz":[0.703837065697851316,0.872837149614437924,1.07749749163391195],"hpluv":[192.177050630060705,373.711432895013843,94.8585166918378633],"hsluv":[192.177050630060705,99.9999999999852491,94.8585166918378633]},"#338800":{"lch":[49.8717454753508918,71.2965557675853461,122.69380865426514],"luv":[49.8717454753508918,-38.5107906934601871,60.0009821960016509],"rgb":[0.2,0.533333333333333326,0],"xyz":[0.101689839911933699,0.183114842185751275,0.0299858551632874795],"hpluv":[122.69380865426514,181.406693814272955,49.8717454753508918],"hsluv":[122.69380865426514,100.000000000002245,49.8717454753508918]},"#338811":{"lch":[49.9202331837381053,69.5570511040883162,123.47043015419375],"luv":[49.9202331837381053,-38.361169332567485,58.0224443274741475],"rgb":[0.2,0.533333333333333326,0.0666666666666666657],"xyz":[0.102701505411570818,0.183519508385606128,0.0353139601280431092],"hpluv":[123.47043015419375,176.808802540010674,49.9202331837381053],"hsluv":[123.47043015419375,96.3624965314944291,49.9202331837381053]},"#338822":{"lch":[50.0099282713402,66.4316762124597915,124.985970570646856],"luv":[50.0099282713402,-38.0903182709230137,54.426971791721833],"rgb":[0.2,0.533333333333333326,0.133333333333333331],"xyz":[0.104576863550047847,0.184269651640996956,0.0451908463240223088],"hpluv":[124.985970570646856,168.561468288507513,50.0099282713402],"hsluv":[124.985970570646856,89.7672781446156876,50.0099282713402]},"#338833":{"lch":[50.1570811029395429,61.5658815699287487,127.715012949239991],"luv":[50.1570811029395429,-37.6619639194057143,48.7025076070614134],"rgb":[0.2,0.533333333333333326,0.2],"xyz":[0.10766461428250558,0.185504751933980055,0.061453000181633452],"hpluv":[127.715012949239991,155.756856758587162,50.1570811029395429],"hsluv":[127.715012949239991,79.3080015418374416,50.1570811029395429]},"#338844":{"lch":[50.3683877843642165,55.1600753981733334,132.238380805917416],"luv":[50.3683877843642165,-37.0795228857786441,40.8380080377971524],"rgb":[0.2,0.533333333333333326,0.266666666666666663],"xyz":[0.112122609526724454,0.187287950031667649,0.0849317751345200905],"hpluv":[132.238380805917416,138.965222681713072,50.3683877843642165],"hsluv":[132.238380805917416,79.9701630926319922,50.3683877843642165]},"#338855":{"lch":[50.648916869713247,47.7759983149871488,139.558488969535745],"luv":[50.648916869713247,-36.3608093871966886,30.990926990033774],"rgb":[0.2,0.533333333333333326,0.333333333333333315],"xyz":[0.118085023566086453,0.189672915647412482,0.116333822408493992],"hpluv":[139.558488969535745,119.695806374350084,50.648916869713247],"hsluv":[139.558488969535745,80.7922551095087726,50.648916869713247]},"#338866":{"lch":[51.0024095938582747,40.50700493167151,151.3112863122482],"luv":[51.0024095938582747,-35.5343950908498,19.4454162738124445],"rgb":[0.2,0.533333333333333326,0.4],"xyz":[0.125670019339594624,0.192706913956815773,0.156281466815637954],"hpluv":[151.3112863122482,100.78102351571394,51.0024095938582747],"hsluv":[151.3112863122482,81.7453783644028249,51.0024095938582747]},"#338877":{"lch":[51.4314426692160964,35.2513066472794421,169.271441625736571],"luv":[51.4314426692160964,-34.635118433957949,6.56225505495134165],"rgb":[0.2,0.533333333333333326,0.466666666666666674],"xyz":[0.134984032359796557,0.196432519164896596,0.205335268722035863],"hpluv":[169.271441625736571,86.9732781104886499,51.4314426692160964],"hsluv":[169.271441625736571,82.7938072280844182,51.4314426692160964]},"#338888":{"lch":[51.9375397067754818,34.4751674240590873,192.177050630061075],"luv":[51.9375397067754818,-33.6994920276336458,-7.27196025816705482],"rgb":[0.2,0.533333333333333326,0.533333333333333326],"xyz":[0.146124449461740358,0.200888686005674194,0.26400813212560803],"hpluv":[192.177050630061075,84.229522237058,51.9375397067754818],"hsluv":[192.177050630061075,83.8998231764876579,51.9375397067754818]},"#338899":{"lch":[52.5212658253882267,39.2899369869163,213.503984387174484],"luv":[52.5212658253882267,-32.7618132949538179,-21.68784770470414],"rgb":[0.2,0.533333333333333326,0.6],"xyz":[0.159181413570813085,0.206111471649303352,0.332774809766725965],"hpluv":[213.503984387174484,94.9260641143146415,52.5212658253882267],"hsluv":[213.503984387174484,85.0278067813718081,52.5212658253882267]},"#3388aa":{"lch":[53.1823203703714142,48.3403865273999855,228.783963154055925],"luv":[53.1823203703714142,-31.8514822326876157,-36.3631138545534753],"rgb":[0.2,0.533333333333333326,0.66666666666666663],"xyz":[0.174239106536065613,0.212134548835404446,0.412078659383724566],"hpluv":[228.783963154055925,115.340588590435829,53.1823203703714142],"hsluv":[228.783963154055925,86.1470646970195588,53.1823203703714142]},"#3388bb":{"lch":[53.9196335036436238,59.7107302664646866,238.732819450220632],"luv":[53.9196335036436238,-30.9916356267104831,-51.0381213421469],"rgb":[0.2,0.533333333333333326,0.733333333333333282],"xyz":[0.191376698643402288,0.218989585678339205,0.502336644482366257],"hpluv":[238.732819450220632,140.522147305520861,53.9196335036436238],"hsluv":[238.732819450220632,87.2332789223686262,53.9196335036436238]},"#3388cc":{"lch":[54.7314676322995268,72.1439684856409826,245.254262274299492],"luv":[54.7314676322995268,-30.1989009668194051,-65.5192992121664446],"rgb":[0.2,0.533333333333333326,0.8],"xyz":[0.210669074087124014,0.226706535855828,0.603943155152636413],"hpluv":[245.254262274299492,167.263916186866481,54.7314676322995268],"hsluv":[245.254262274299492,88.2687848362996,54.7314676322995268]},"#3388dd":{"lch":[55.6155220749816692,84.9545141717074728,249.692682338977761],"luv":[55.6155220749816692,-29.4839257322198733,-79.6741338300441697],"rgb":[0.2,0.533333333333333326,0.866666666666666696],"xyz":[0.232187399637757558,0.23531386607608154,0.717273003052642411],"hpluv":[249.692682338977761,193.833915517882872,55.6155220749816692],"hsluv":[249.692682338977761,89.2420383366021923,55.6155220749816692]},"#3388ee":{"lch":[56.5690381344568323,97.7754852991564434,252.83721230554255],"luv":[56.5690381344568323,-28.8523290085395629,-93.4215640859675602],"rgb":[0.2,0.533333333333333326,0.933333333333333348],"xyz":[0.255999579903932295,0.244838738182551585,0.842683819121165634],"hpluv":[252.83721230554255,219.32619909500923,56.5690381344568323],"hsluv":[252.83721230554255,90.146641202583325,56.5690381344568323]},"#3388ff":{"lch":[57.5889013880528182,110.410831334845568,255.145344615238457],"luv":[57.5889013880528182,-28.3057941013035759,-106.720821287817699],"rgb":[0.2,0.533333333333333326,1],"xyz":[0.282170628313763716,0.255307157546484254,0.980518007412947479],"hpluv":[255.145344615238457,243.283252172694205,57.5889013880528182],"hsluv":[255.145344615238457,99.9999999999988489,57.5889013880528182]},"#339900":{"lch":[55.5688440832231,80.82821284508357,123.866754715109295],"luv":[55.5688440832231,-45.0426054376311527,67.1145564473163603],"rgb":[0.2,0.6,0],"xyz":[0.127559440364401172,0.23485404309068697,0.0386090553141097345],"hpluv":[123.866754715109295,184.574176757765827,55.5688440832231],"hsluv":[123.866754715109295,100.00000000000226,55.5688440832231]},"#339911":{"lch":[55.6099261578814463,79.3206910999707446,124.475743785225987],"luv":[55.6099261578814463,-44.9000555787807372,65.3892731692238556],"rgb":[0.2,0.6,0.0666666666666666657],"xyz":[0.128571105864038304,0.235258709290541823,0.0439371602788653642],"hpluv":[124.475743785225987,180.997883954149785,55.6099261578814463],"hsluv":[124.475743785225987,97.1571693172972601,55.6099261578814463]},"#339922":{"lch":[55.6859569378682124,76.5942224429011418,125.649114872203555],"luv":[55.6859569378682124,-44.6406262928881503,62.240576763164114],"rgb":[0.2,0.6,0.133333333333333331],"xyz":[0.130446464002515305,0.236008852545932651,0.0538140464748445638],"hpluv":[125.649114872203555,174.537861698610129,55.6859569378682124],"hsluv":[125.649114872203555,91.9778413864117113,55.6859569378682124]},"#339933":{"lch":[55.8107903110879278,72.2971425020977563,127.715012949240148],"luv":[55.8107903110879278,-44.2266447414942618,57.191613973364035],"rgb":[0.2,0.6,0.2],"xyz":[0.133534214734973067,0.23724395283891575,0.070076200332455707],"hpluv":[127.715012949240148,164.377468022308932,55.8107903110879278],"hsluv":[127.715012949240148,83.6974291768240874,55.8107903110879278]},"#339944":{"lch":[55.9902586993563602,66.5149718399310501,131.021169741293448],"luv":[55.9902586993563602,-43.6562926505411042,50.1833597009719128],"rgb":[0.2,0.6,0.266666666666666663],"xyz":[0.137992209979191927,0.239027150936603344,0.0935549752853423455],"hpluv":[131.021169741293448,150.746162046382238,55.9902586993563602],"hsluv":[131.021169741293448,84.1112663411127386,55.9902586993563602]},"#339955":{"lch":[56.2289015921924,59.572114639014508,136.121417864766215],"luv":[56.2289015921924,-42.9401916463123783,41.2913645202220323],"rgb":[0.2,0.6,0.333333333333333315],"xyz":[0.143954624018553912,0.241412116552348177,0.124957022559316261],"hpluv":[136.121417864766215,134.438216783596687,56.2289015921924],"hsluv":[136.121417864766215,84.6329955380286236,56.2289015921924]},"#339966":{"lch":[56.5302268191487514,52.1043875673731947,143.898662284026642],"luv":[56.5302268191487514,-42.0991012865816785,30.700698275986678],"rgb":[0.2,0.6,0.4],"xyz":[0.151539619792062097,0.244446114861751468,0.164904666966460223],"hpluv":[143.898662284026642,116.958797396111564,56.5302268191487514],"hsluv":[143.898662284026642,85.2491724948614689,56.5302268191487514]},"#339977":{"lch":[56.8968484427531678,45.1992705399313124,155.596009487994166],"luv":[56.8968484427531678,-41.1609366004351855,18.6748856895258584],"rgb":[0.2,0.6,0.466666666666666674],"xyz":[0.160853632812264,0.248171720069832291,0.213958468872858132],"hpluv":[155.596009487994166,100.805108459810327,56.8968484427531678],"hsluv":[155.596009487994166,85.9413862611579873,56.8968484427531678]},"#339988":{"lch":[57.330574208667926,40.5351988689668303,172.17134267960472],"luv":[57.330574208667926,-40.1574041849560217,5.52134371985359085],"rgb":[0.2,0.6,0.533333333333333326],"xyz":[0.171994049914207858,0.252627886910609889,0.272631332276430272],"hpluv":[172.17134267960472,89.7191897797317,57.330574208667926],"hsluv":[172.17134267960472,86.6885468018933665,57.330574208667926]},"#339999":{"lch":[57.8324724587931627,40.0212192418936539,192.177050630061103],"luv":[57.8324724587931627,-39.1207602326874735,-8.44180717763071],"rgb":[0.2,0.6,0.6],"xyz":[0.185051014023280558,0.257850672554239047,0.341398009917548206],"hpluv":[192.177050630061103,87.8128114771670312,57.8324724587931627],"hsluv":[192.177050630061103,87.4690863712762194,57.8324724587931627]},"#3399aa":{"lch":[58.4029323329449568,44.4430671798845367,211.035048784986628],"luv":[58.4029323329449568,-38.0811346860811923,-22.913170914918652],"rgb":[0.2,0.6,0.66666666666666663],"xyz":[0.200108706988533114,0.263873749740340169,0.420701859534546807],"hpluv":[211.035048784986628,96.5625435737210154,58.4029323329449568],"hsluv":[211.035048784986628,88.2627766327166,58.4029323329449568]},"#3399bb":{"lch":[59.0417237507550823,52.8166449153409445,225.431517702392057],"luv":[59.0417237507550823,-37.064675814253917,-37.6272213549907448],"rgb":[0.2,0.6,0.733333333333333282],"xyz":[0.217246299095869733,0.270728786583274927,0.510959844633188554],"hpluv":[225.431517702392057,113.514439229551684,59.0417237507550823],"hsluv":[225.431517702392057,89.0519907331041196,59.0417237507550823]},"#3399cc":{"lch":[59.7480598269018373,63.5982744854026194,235.423336237979868],"luv":[59.7480598269018373,-36.0925574956591646,-52.364757336811472],"rgb":[0.2,0.6,0.8],"xyz":[0.236538674539591487,0.278445736760763729,0.612566355303458709],"hpluv":[235.423336237979868,135.070607162709791,59.7480598269018373],"hsluv":[235.423336237979868,89.8223822716188636,59.7480598269018373]},"#3399dd":{"lch":[60.5206621982976856,75.6357863680042186,242.281144195606601],"luv":[60.5206621982976856,-35.1807304699237235,-66.9558689220665286],"rgb":[0.2,0.6,0.866666666666666696],"xyz":[0.25805700009022503,0.287053066981017235,0.725896203203464707],"hpluv":[242.281144195606601,158.58531958905732,60.5206621982976856],"hsluv":[242.281144195606601,90.5630616197976508,60.5206621982976856]},"#3399ee":{"lch":[61.3578284965586818,88.2341933332873083,247.095644636752098],"luv":[61.3578284965586818,-34.3402162860227946,-81.277441019049661],"rgb":[0.2,0.6,0.933333333333333348],"xyz":[0.28186918035639974,0.296577939087487252,0.85130701927198793],"hpluv":[247.095644636752098,182.476215369006297,61.3578284965586818],"hsluv":[247.095644636752098,91.2664056494933504,61.3578284965586818]},"#3399ff":{"lch":[62.2575005434706554,100.992674077385175,250.5808182685887],"luv":[62.2575005434706554,-33.5777301361133595,-95.2473425151972],"rgb":[0.2,0.6,1],"xyz":[0.308040228766231161,0.30704635845142,0.989141207563769775],"hpluv":[250.5808182685887,205.84367033720622,62.2575005434706554],"hsluv":[250.5808182685887,99.9999999999985789,62.2575005434706554]},"#220000":{"lch":[3.07250446727781679,10.3329293192956264,12.1770506300617765],"luv":[3.07250446727781679,10.1004431663672367,2.17955870775360072],"rgb":[0.133333333333333331,0,0],"xyz":[0.00659672420629513,0.00340143591887099878,0.000309221447170077699],"hpluv":[12.1770506300617765,426.746789183125429,3.07250446727781679],"hsluv":[12.1770506300617765,100.000000000002217,3.07250446727781679]},"#220011":{"lch":[3.43803794680403607,8.12070857757986353,344.488545895364155],"luv":[3.43803794680403607,7.82492808895188574,-2.17172931202554675],"rgb":[0.133333333333333331,0,0.0666666666666666657],"xyz":[0.00760838970593225201,0.00380610211872585338,0.00563732641192570948],"hpluv":[344.488545895364155,299.724735916282839,3.43803794680403607],"hsluv":[344.488545895364155,99.9999999999976836,3.43803794680403607]},"#220022":{"lch":[4.11563957101797229,9.37475958111893348,307.715012949243601],"luv":[4.11563957101797229,5.73486236359989565,-7.41602797151862436],"rgb":[0.133333333333333331,0,0.133333333333333331],"xyz":[0.00948374784440927,0.00455624537411667124,0.0155142126079049047],"hpluv":[307.715012949243601,289.042783730483393,4.11563957101797229],"hsluv":[307.715012949243601,99.9999999999988205,4.11563957101797229]},"#220033":{"lch":[5.23130109110515384,14.2535250315243012,286.735013267555587],"luv":[5.23130109110515384,4.10424250296207127,-13.6498413654214126],"rgb":[0.133333333333333331,0,0.2],"xyz":[0.0125714985768670112,0.00579134566709978496,0.0317763664655160497],"hpluv":[286.735013267555587,345.74180296647927,5.23130109110515384],"hsluv":[286.735013267555587,99.9999999999995737,5.23130109110515384]},"#220044":{"lch":[6.84205732813722722,21.3889830656619786,277.641816515271671],"luv":[6.84205732813722722,2.84430225454687724,-21.1990221771654959],"rgb":[0.133333333333333331,0,0.266666666666666663],"xyz":[0.01702949382108589,0.0075745437647873606,0.0552551414184026882],"hpluv":[277.641816515271671,396.682237683346386,6.84205732813722722],"hsluv":[277.641816515271671,100.000000000000085,6.84205732813722722]},"#220055":{"lch":[8.95766614306443,30.4428627575942237,273.263558660643355],"luv":[8.95766614306443,1.73308321478426808,-30.3934913336449455],"rgb":[0.133333333333333331,0,0.333333333333333315],"xyz":[0.0229919078604478855,0.00995950938053219263,0.0866571886923766],"hpluv":[273.263558660643355,431.250830347711485,8.95766614306443],"hsluv":[273.263558660643355,100.000000000000242,8.95766614306443]},"#220066":{"lch":[11.2709410858812937,40.3162667149428913,270.881506896841],"luv":[11.2709410858812937,0.620249265146302853,-40.3114952920317435],"rgb":[0.133333333333333331,0,0.4],"xyz":[0.0305769036339560568,0.0129935076899355059,0.126604833099520558],"hpluv":[270.881506896841,453.899240935372916,11.2709410858812937],"hsluv":[270.881506896841,100.000000000000469,11.2709410858812937]},"#220077":{"lch":[13.6616791408408957,50.492834518379162,269.459540268375122],"luv":[13.6616791408408957,-0.476281836738408071,-50.4905881656414763],"rgb":[0.133333333333333331,0,0.466666666666666674],"xyz":[0.0398909166541579763,0.0167191128980163223,0.175658635005918468],"hpluv":[269.459540268375122,468.991527020998944,13.6616791408408957],"hsluv":[269.459540268375122,100.000000000000711,13.6616791408408957]},"#220088":{"lch":[16.0923146306383913,60.7890037695263104,268.549935621017426],"luv":[16.0923146306383913,-1.53830805749361632,-60.7695366743217278],"rgb":[0.133333333333333331,0,0.533333333333333326],"xyz":[0.0510313337561018043,0.0211752797387939132,0.234331498409490635],"hpluv":[268.549935621017426,479.34239057424071,16.0923146306383913],"hsluv":[268.549935621017426,100.000000000000711,16.0923146306383913]},"#220099":{"lch":[18.5394450926422749,71.1015482986176437,267.936483797094468],"luv":[18.5394450926422749,-2.56017951479828287,-71.0554406876254916],"rgb":[0.133333333333333331,0,0.6],"xyz":[0.0640882978651745178,0.0263980653824230742,0.30309817605060857],"hpluv":[267.936483797094468,486.655519564945394,18.5394450926422749],"hsluv":[267.936483797094468,100.000000000000739,18.5394450926422749]},"#2200aa":{"lch":[20.9885603179873783,81.3727160976321,267.505178931910336],"luv":[20.9885603179873783,-3.54207977840461252,-81.2955878012407851],"rgb":[0.133333333333333331,0,0.66666666666666663],"xyz":[0.0791459908304270598,0.0324211425685241791,0.382402025667607171],"hpluv":[267.505178931910336,491.966452636739518,20.9885603179873783],"hsluv":[267.505178931910336,100.000000000000782,20.9885603179873783]},"#2200bb":{"lch":[23.4306921856835828,91.57073581353,267.191578225858507],"luv":[23.4306921856835828,-4.48665301772878333,-91.4607544366971155],"rgb":[0.133333333333333331,0,0.733333333333333282],"xyz":[0.0962835829377637,0.0392761794114589377,0.472660010766248917],"hpluv":[267.191578225858507,495.919187528698728,23.4306921856835828],"hsluv":[267.191578225858507,100.000000000000909,23.4306921856835828]},"#2200cc":{"lch":[25.860342630381858,101.678845182637474,266.957159441292106],"luv":[25.860342630381858,-5.39738007409318588,-101.535490573545474],"rgb":[0.133333333333333331,0,0.8],"xyz":[0.115575958381485447,0.0469931295889477393,0.574266521436519],"hpluv":[266.957159441292106,498.925449111647538,25.860342630381858],"hsluv":[266.957159441292106,100.000000000000881,25.860342630381858]},"#2200dd":{"lch":[28.2742062228116282,111.689036790699618,266.777814373778199],"luv":[28.2742062228116282,-6.27782958394359714,-111.512464751476173],"rgb":[0.133333333333333331,0,0.866666666666666696],"xyz":[0.137094283932118977,0.0556004598092012733,0.687596369336525],"hpluv":[266.777814373778199,501.255846139694427,28.2742062228116282],"hsluv":[266.777814373778199,100.000000000000838,28.2742062228116282]},"#2200ee":{"lch":[30.6703766456275062,121.598437280905173,266.637867063772376],"luv":[30.6703766456275062,-7.13133722672581882,-121.389142753859758],"rgb":[0.133333333333333331,0,0.933333333333333348],"xyz":[0.160906464198293714,0.0651253319156713,0.813007185405048238],"hpluv":[266.637867063772376,503.092926092128948,30.6703766456275062],"hsluv":[266.637867063772376,100.000000000000838,30.6703766456275062]},"#2200ff":{"lch":[33.0478477502328261,131.407178056457695,266.526788769360394],"luv":[33.0478477502328261,-7.96089030872800674,-131.165813649189772],"rgb":[0.133333333333333331,0,1],"xyz":[0.187077512608125107,0.0755937512796040073,0.950841373696830083],"hpluv":[266.526788769360394,504.562807291912918,33.0478477502328261],"hsluv":[266.526788769360394,100.000000000000824,33.0478477502328261]},"#221100":{"lch":[6.69363913087575835,9.72440836304526535,42.3457761997067053],"luv":[6.69363913087575835,7.18724369375563921,6.55039282011655288],"rgb":[0.133333333333333331,0.0666666666666666657,0],"xyz":[0.00860112446722354,0.00741023644072787233,0.000977354867479528471],"hpluv":[42.3457761997067053,184.348759610596915,6.69363913087575835],"hsluv":[42.3457761997067053,100.000000000002402,6.69363913087575835]},"#221111":{"lch":[7.0591726104019763,6.19439175917428564,12.1770506300621],"luv":[7.0591726104019763,6.05502079617615863,1.30660339200560327],"rgb":[0.133333333333333331,0.0666666666666666657,0.0666666666666666657],"xyz":[0.00961278996686066103,0.00781490264058272606,0.00630545983223516],"hpluv":[12.1770506300621,111.348454543071412,7.0591726104019763],"hsluv":[12.1770506300621,26.092394217240134,7.0591726104019763]},"#221122":{"lch":[7.73677423461591474,7.55259268754738677,307.715012949245249],"luv":[7.73677423461591474,4.62018030186617779,-5.97457866985129],"rgb":[0.133333333333333331,0.0666666666666666657,0.133333333333333331],"xyz":[0.0114881481053376797,0.00856504589597354565,0.0161823460282143547],"hpluv":[307.715012949245249,123.872660774597591,7.73677423461591474],"hsluv":[307.715012949245249,42.856167926372315,7.73677423461591474]},"#221133":{"lch":[8.8238329822443653,14.9761175001236957,282.095598903329574],"luv":[8.8238329822443653,3.13814740657790647,-14.6436377390353236],"rgb":[0.133333333333333331,0.0666666666666666657,0.2],"xyz":[0.0145758988377954202,0.00980014618895665851,0.0324444998858255],"hpluv":[282.095598903329574,215.36805510923017,8.8238329822443653],"hsluv":[282.095598903329574,58.3941618505161273,8.8238329822443653]},"#221144":{"lch":[10.2463738670161,23.9334379374521049,274.255517801158362],"luv":[10.2463738670161,1.77596948547040223,-23.8674544912638211],"rgb":[0.133333333333333331,0.0666666666666666657,0.266666666666666663],"xyz":[0.0190338940820143,0.011583344286644235,0.0559232748387121364],"hpluv":[274.255517801158362,296.397281412249697,10.2463738670161],"hsluv":[274.255517801158362,70.1230959508528287,10.2463738670161]},"#221155":{"lch":[11.9365395500671561,33.3852442414483903,270.945812779521702],"luv":[11.9365395500671561,0.551083463009601,-33.3806956200430349],"rgb":[0.133333333333333331,0.0666666666666666657,0.333333333333333315],"xyz":[0.0249963081213762928,0.0139683099023890662,0.0873253221126860518],"hpluv":[270.945812779521702,354.907717298979946,11.9365395500671561],"hsluv":[270.945812779521702,78.3035236172291,11.9365395500671561]},"#221166":{"lch":[13.8282163263251512,43.1006504094303509,269.247085426223],"luv":[13.8282163263251512,-0.566362377205730683,-43.0969291176716496],"rgb":[0.133333333333333331,0.0666666666666666657,0.4],"xyz":[0.0325813038948844641,0.0170023082117923795,0.12727296651983],"hpluv":[269.247085426223,395.509560036398682,13.8282163263251512],"hsluv":[269.247085426223,83.9084652674952167,13.8282163263251512]},"#221177":{"lch":[15.8647012598499089,52.9790758801604,268.263491631539182],"luv":[15.8647012598499089,-1.60543281970815044,-52.954745458525224],"rgb":[0.133333333333333331,0.0666666666666666657,0.466666666666666674],"xyz":[0.0418953169150863836,0.0207279134198731958,0.176326768426227909],"hpluv":[268.263491631539182,423.75204448359591,15.8647012598499089],"hsluv":[268.263491631539182,87.783734282584831,15.8647012598499089]},"#221188":{"lch":[18.0016522099437424,62.9493123294311872,267.645454528547475],"luv":[18.0016522099437424,-2.58614693443793442,-62.8961665507666297],"rgb":[0.133333333333333331,0.0666666666666666657,0.533333333333333326],"xyz":[0.0530357340170302116,0.0251840802606507867,0.234999631829800076],"hpluv":[267.645454528547475,443.729139668046173,18.0016522099437424],"hsluv":[267.645454528547475,90.5156952975567464,18.0016522099437424]},"#221199":{"lch":[20.2061107483083475,72.9561611588118524,267.23334268313738],"luv":[20.2061107483083475,-3.52148568403582729,-72.8711231531918742],"rgb":[0.133333333333333331,0.0666666666666666657,0.6],"xyz":[0.066092698126102925,0.0304068659042799477,0.303766309470918],"hpluv":[267.23334268313738,458.161478440778865,20.2061107483083475],"hsluv":[267.23334268313738,92.4853336382361704,20.2061107483083475]},"#2211aa":{"lch":[22.4542330055690798,82.9584275230068471,266.945798214496847],"luv":[22.4542330055690798,-4.42007776686241449,-82.8405915576709759],"rgb":[0.133333333333333331,0.0666666666666666657,0.66666666666666663],"xyz":[0.0811503910913554671,0.0364299430903810492,0.383070159087916584],"hpluv":[266.945798214496847,468.815123306781686,22.4542330055690798],"hsluv":[266.945798214496847,93.9373181855700921,22.4542330055690798]},"#2211bb":{"lch":[24.7289983316777295,92.9268656932788701,266.737844101991243],"luv":[24.7289983316777295,-5.28796663316276483,-92.7762888698575097],"rgb":[0.133333333333333331,0.0666666666666666657,0.733333333333333282],"xyz":[0.0982879831986921138,0.0432849799333158078,0.473328144186558331],"hpluv":[266.737844101991243,476.841549380862261,24.7289983316777295],"hsluv":[266.737844101991243,95.0302193246277369,24.7289983316777295]},"#2211cc":{"lch":[27.0183279904475668,102.841627589427389,266.583003116257],"luv":[27.0183279904475668,-6.12961814831514129,-102.658794784462174],"rgb":[0.133333333333333331,0.0666666666666666657,0.8],"xyz":[0.117580358642413854,0.0510019301108046094,0.574934654856828486],"hpluv":[266.583003116257,483.002966655360069,27.0183279904475668],"hsluv":[266.583003116257,95.8686128249461689,27.0183279904475668]},"#2211dd":{"lch":[29.313669578695368,112.689841457512074,266.464886381494523],"luv":[29.313669578695368,-6.94848190374932617,-112.475414944566779],"rgb":[0.133333333333333331,0.0666666666666666657,0.866666666666666696],"xyz":[0.139098684193047384,0.0596092603310581434,0.688264502756834484],"hpluv":[266.464886381494523,487.813602393737767,29.313669578695368],"hsluv":[266.464886381494523,96.5228774582602256,29.313669578695368]},"#2211ee":{"lch":[31.6089746608533417,122.463629630364608,266.372923821556242],"luv":[31.6089746608533417,-7.74731231829930689,-122.21832814306471],"rgb":[0.133333333333333331,0.0666666666666666657,0.933333333333333348],"xyz":[0.162910864459222149,0.0691341324375281813,0.813675318825357707],"hpluv":[266.372923821556242,491.627361233059389,31.6089746608533417],"hsluv":[266.372923821556242,97.0413663214109761,31.6089746608533417]},"#2211ff":{"lch":[33.8999739889387115,132.15860685194221,266.300059947999785],"luv":[33.8999739889387115,-8.52836196764118,-131.883146789857562],"rgb":[0.133333333333333331,0.0666666666666666657,1],"xyz":[0.189081912869053514,0.0796025518014608774,0.951509507117139552],"hpluv":[266.300059947999785,494.692599475339,33.8999739889387115],"hsluv":[266.300059947999785,99.9999999999995737,33.8999739889387115]},"#77aa00":{"lch":[63.8935034159882491,78.4053265973676616,109.262687899665323],"luv":[63.8935034159882491,-25.8658938451783591,74.0158819067222424],"rgb":[0.466666666666666674,0.66666666666666663,0],"xyz":[0.219816749274909073,0.326708497135311,0.0514797056256764834],"hpluv":[109.262687899665323,155.714190603412163,63.8935034159882491],"hsluv":[109.262687899665323,100.000000000002132,63.8935034159882491]},"#77aa11":{"lch":[63.9264755829735662,77.0719876411919,109.595002167467626],"luv":[63.9264755829735662,-25.8475857965541422,72.6084952843247464],"rgb":[0.466666666666666674,0.66666666666666663,0.0666666666666666657],"xyz":[0.220828414774546206,0.32711316333516588,0.0568078105904321132],"hpluv":[109.595002167467626,152.98720995680398,63.9264755829735662],"hsluv":[109.595002167467626,97.9667163347824612,63.9264755829735662]},"#77aa22":{"lch":[63.9875253363426424,74.6349938152274603,110.235118064089221],"luv":[63.9875253363426424,-25.8142561390327501,70.0286118796271],"rgb":[0.466666666666666674,0.66666666666666663,0.133333333333333331],"xyz":[0.222703772913023207,0.32786330659055668,0.0666846967864113127],"hpluv":[110.235118064089221,148.008450888663447,63.9875253363426424],"hsluv":[110.235118064089221,94.2440053809013421,63.9875253363426424]},"#77aa33":{"lch":[64.0878403339217328,70.7199026331045,111.362593229805157],"luv":[64.0878403339217328,-25.7610573917560757,65.8610093340090685],"rgb":[0.466666666666666674,0.66666666666666663,0.2],"xyz":[0.22579152364548094,0.329098406883539807,0.0829468506440224629],"hpluv":[111.362593229805157,140.024923426145421,64.0878403339217328],"hsluv":[111.362593229805157,88.2427941375042,64.0878403339217328]},"#77aa44":{"lch":[64.2322300921174616,65.2796522257345,113.17268826837423],"luv":[64.2322300921174616,-25.6877867579927681,60.0130869576689463],"rgb":[0.466666666666666674,0.66666666666666663,0.266666666666666663],"xyz":[0.230249518889699828,0.330881604981227373,0.106425625596909101],"hpluv":[113.17268826837423,128.962712139229978,64.2322300921174616],"hsluv":[113.17268826837423,79.8488372015295482,64.2322300921174616]},"#77aa55":{"lch":[64.4245377454048338,58.3957340906732298,115.996670283872277],"luv":[64.4245377454048338,-25.5959546947607706,52.487225714952487],"rgb":[0.466666666666666674,0.66666666666666663,0.333333333333333315],"xyz":[0.236211932929061841,0.333266570596972234,0.137827672870883],"hpluv":[115.996670283872277,115.018880896771989,64.4245377454048338],"hsluv":[115.996670283872277,69.0944053471027075,64.4245377454048338]},"#77aa66":{"lch":[64.6678576456364,50.3036055521827663,120.443938093288892],"luv":[64.6678576456364,-25.4885877435648602,43.368013862617552],"rgb":[0.466666666666666674,0.66666666666666663,0.4],"xyz":[0.24379692870257,0.336300568906375552,0.177775317278026979],"hpluv":[120.443938093288892,98.707457943709727,64.6678576456364],"hsluv":[120.443938093288892,56.1391996219007723,64.6678576456364]},"#77aa77":{"lch":[64.964649263009,41.4721527505437351,127.71501294923786],"luv":[64.964649263009,-25.3699399849719889,32.8070967768157118],"rgb":[0.466666666666666674,0.66666666666666663,0.466666666666666674],"xyz":[0.253110941722771932,0.340026174114456348,0.226829119184424888],"hpluv":[127.71501294923786,81.006302212696113,64.964649263009],"hsluv":[127.71501294923786,41.2466460512923874,64.964649263009]},"#77aa88":{"lch":[65.3168057391263375,32.8409027786736161,140.238161573904051],"luv":[65.3168057391263375,-25.2451203613846147,21.004970679758074],"rgb":[0.466666666666666674,0.66666666666666663,0.533333333333333326],"xyz":[0.264251358824715732,0.344482340955233945,0.285501982587997],"hpluv":[140.238161573904051,63.8012923553667,65.3168057391263375],"hsluv":[140.238161573904051,43.6199696205744232,65.3168057391263375]},"#77aa99":{"lch":[65.7257012160132,26.4214783611449491,161.939459903532622],"luv":[65.7257012160132,-25.1196781367095241,8.19123245284666],"rgb":[0.466666666666666674,0.66666666666666663,0.6],"xyz":[0.277308322933788487,0.349705126598863103,0.354268660229114962],"hpluv":[161.939459903532622,51.0106916742292213,65.7257012160132],"hsluv":[161.939459903532622,46.1685656356417766,65.7257012160132]},"#77aaaa":{"lch":[66.1922284915170565,25.5746156232648509,192.177050630060677],"luv":[66.1922284915170565,-24.9991985449953802,-5.39453764336142338],"rgb":[0.466666666666666674,0.66666666666666663,0.66666666666666663],"xyz":[0.292366015899041,0.355728203784964225,0.433572509846113563],"hpluv":[192.177050630060677,49.0276908522131265,66.1922284915170565],"hsluv":[192.177050630060677,48.8357820868943122,66.1922284915170565]},"#77aabb":{"lch":[66.7168329685055568,31.6300901405034409,218.105494045696133],"luv":[66.7168329685055568,-24.8889541052261336,-19.519287021925777],"rgb":[0.466666666666666674,0.66666666666666663,0.733333333333333282],"xyz":[0.309503608006377662,0.362583240627899,0.523830494944755309],"hpluv":[218.105494045696133,60.1595160354738923,66.7168329685055568],"hsluv":[218.105494045696133,51.56699221483656,66.7168329685055568]},"#77aacc":{"lch":[67.2995460165272306,42.0550186755790207,233.874741843371567],"luv":[67.2995460165272306,-24.7936410920562054,-33.9691029790543908],"rgb":[0.466666666666666674,0.66666666666666663,0.8],"xyz":[0.328795983450099416,0.370300190805387786,0.625437005615025465],"hpluv":[233.874741843371567,79.2948573353567099,67.2995460165272306],"hsluv":[233.874741843371567,54.3124963748670382,67.2995460165272306]},"#77aadd":{"lch":[67.9400192524912,54.4863937886276304,243.022531341574677],"luv":[67.9400192524912,-24.7172120267711577,-48.557456046554158],"rgb":[0.466666666666666674,0.66666666666666663,0.866666666666666696],"xyz":[0.350314309000732904,0.378907521025641292,0.738766853515031463],"hpluv":[243.022531341574677,101.765770647841308,67.9400192524912],"hsluv":[243.022531341574677,60.6446157506369659,67.9400192524912]},"#77aaee":{"lch":[68.6375602707836,67.7758398266106781,248.660849953701415],"luv":[68.6375602707836,-24.6627990544268876,-63.1293181256010882],"rgb":[0.466666666666666674,0.66666666666666663,0.933333333333333348],"xyz":[0.374126489266907669,0.388432393132111309,0.864177669583554686],"hpluv":[248.660849953701415,125.300382334337471,68.6375602707836],"hsluv":[248.660849953701415,79.8712566390148453,68.6375602707836]},"#77aaff":{"lch":[69.3911697465266428,81.3794470542267874,252.380781260055755],"luv":[69.3911697465266428,-24.6327125013740549,-77.5618712878715399],"rgb":[0.466666666666666674,0.66666666666666663,1],"xyz":[0.400297537676739035,0.398900812496044033,1.00201185787533653],"hpluv":[252.380781260055755,148.816077288451226,69.3911697465266428],"hsluv":[252.380781260055755,99.9999999999980531,69.3911697465266428]},"#222200":{"lch":[12.5069288045758107,13.787646171799997,85.8743202181747307],"luv":[12.5069288045758107,0.991945128669063814,13.751917387057734],"rgb":[0.133333333333333331,0.133333333333333331,0],"xyz":[0.0123167482019914745,0.014841483910263846,0.002215896112402139],"hpluv":[85.8743202181747307,139.887458074797621,12.5069288045758107],"hsluv":[85.8743202181747307,100.000000000002359,12.5069288045758107]},"#222211":{"lch":[12.7636979604368612,8.34346759842367,85.8743202181729828],"luv":[12.7636979604368612,0.600266494900015157,8.32184665209868513],"rgb":[0.133333333333333331,0.133333333333333331,0.0666666666666666657],"xyz":[0.0133284137016285963,0.0152461501101187,0.00754400107715777046],"hpluv":[85.8743202181729828,82.9486632734846552,12.7636979604368612],"hsluv":[85.8743202181729828,59.2967120963297631,12.7636979604368612]},"#222222":{"lch":[13.2279109842717837,6.86787642036123471e-13,0],"luv":[13.2279109842717837,6.53891093021720259e-13,2.10008818196756883e-13],"rgb":[0.133333333333333331,0.133333333333333331,0.133333333333333331],"xyz":[0.0152037718401056149,0.0159962933655095202,0.0174208872731369674],"hpluv":[0,6.58825703928357502e-12,13.2279109842717837],"hsluv":[0,1.88635445986832e-12,13.2279109842717837]},"#222233":{"lch":[13.9615854376221584,10.5260121123804868,265.874320218180912],"luv":[13.9615854376221584,-0.757288539977712838,-10.4987354027615698],"rgb":[0.133333333333333331,0.133333333333333331,0.2],"xyz":[0.0182915225725633554,0.017231393658492633,0.0336830411307481106],"hpluv":[265.874320218180912,95.6683874279760431,13.9615854376221584],"hsluv":[265.874320218180912,18.6338179823007195,13.9615854376221584]},"#222244":{"lch":[14.9613810506728697,21.7214686924654536,265.874320218179207],"luv":[14.9613810506728697,-1.5627399186581008,-21.6651805001571454],"rgb":[0.133333333333333331,0.133333333333333331,0.266666666666666663],"xyz":[0.0227495178167822359,0.0190145917561802061,0.0571618160836347491],"hpluv":[265.874320218179207,184.228505509793536,14.9613810506728697],"hsluv":[265.874320218179207,35.8831222215914138,14.9613810506728697]},"#222255":{"lch":[16.2052187005970154,32.8139057554865161,265.874320218178639],"luv":[16.2052187005970154,-2.3607796110480268,-32.728873041368395],"rgb":[0.133333333333333331,0.133333333333333331,0.333333333333333315],"xyz":[0.028711931856144228,0.021399557371925039,0.0885638633576086576],"hpluv":[265.874320218178639,256.946292996249099,16.2052187005970154],"hsluv":[265.874320218178639,50.0467352240393097,16.2052187005970154]},"#222266":{"lch":[17.6604729086265309,43.5908485911403716,265.874320218178354],"luv":[17.6604729086265309,-3.13612123314657865,-43.477888915018994],"rgb":[0.133333333333333331,0.133333333333333331,0.4],"xyz":[0.0362969276296524063,0.0244335556813283505,0.128511507764752619],"hpluv":[265.874320218178354,313.207621322876264,17.6604729086265309],"hsluv":[265.874320218178354,61.00504004829466,17.6604729086265309]},"#222277":{"lch":[19.2910482951380544,54.0745009411091573,265.874320218178241],"luv":[19.2910482951380544,-3.89036222175517965,-53.9343743248547867],"rgb":[0.133333333333333331,0.133333333333333331,0.466666666666666674],"xyz":[0.0456109406498543188,0.0281591608894091669,0.177565309671150529],"hpluv":[265.874320218178241,355.693573155256843,19.2910482951380544],"hsluv":[265.874320218178241,69.2802447897283429,19.2910482951380544]},"#222288":{"lch":[21.0622605487373207,64.3390225585563371,265.874320218178184],"luv":[21.0622605487373207,-4.62883796225993471,-64.1722968492601353],"rgb":[0.133333333333333331,0.133333333333333331,0.533333333333333326],"xyz":[0.0567513577517981468,0.0326153277301867578,0.236238173074722696],"hpluv":[265.874320218178184,387.622344883614403,21.0622605487373207],"hsluv":[265.874320218178184,75.4991739133377706,21.0622605487373207]},"#222299":{"lch":[22.9434551626666803,74.4470789880776351,265.874320218178127],"luv":[22.9434551626666803,-5.35605689510984373,-74.2541596437089737],"rgb":[0.133333333333333331,0.133333333333333331,0.6],"xyz":[0.0698083218608708533,0.0378381133738159223,0.305004850715840603],"hpluv":[265.874320218178127,411.744842564929684,22.9434551626666803],"hsluv":[265.874320218178127,80.1976353712613559,22.9434551626666803]},"#2222aa":{"lch":[24.9089307040763188,84.4389391258505526,265.87432021817807],"luv":[24.9089307040763188,-6.07491614537627278,-84.2201272530844705],"rgb":[0.133333333333333331,0.133333333333333331,0.66666666666666663],"xyz":[0.0848660148261234093,0.0438611905599170238,0.384308700332839204],"hpluv":[265.87432021817807,430.157015573344836,24.9089307040763188],"hsluv":[265.87432021817807,83.7838678741945557,24.9089307040763188]},"#2222bb":{"lch":[26.937850813592469,94.3371638934954149,265.87432021817807],"luv":[26.937850813592469,-6.78703884698804139,-94.0927021354881106],"rgb":[0.133333333333333331,0.133333333333333331,0.733333333333333282],"xyz":[0.102003606933460056,0.0507162274028517823,0.47456668543148095],"hpluv":[265.87432021817807,444.384803230596,26.937850813592469],"hsluv":[265.87432021817807,86.5550863782758,26.937850813592469]},"#2222cc":{"lch":[29.0136770200274086,104.153206308830732,265.874320218178],"luv":[29.0136770200274086,-7.49324898143496743,-103.883307629821275],"rgb":[0.133333333333333331,0.133333333333333331,0.8],"xyz":[0.121295982377181782,0.058433177580340584,0.576173196101751106],"hpluv":[265.874320218178,455.521834046362642,29.0136770200274086],"hsluv":[265.874320218178,88.7243024658832695,29.0136770200274086]},"#2222dd":{"lch":[31.1234509916598299,113.892375340460845,265.874320218178],"luv":[31.1234509916598299,-8.19392849973896809,-113.597238947227837],"rgb":[0.133333333333333331,0.133333333333333331,0.866666666666666696],"xyz":[0.142814307927815326,0.067040507800594118,0.689503044001757104],"hpluv":[265.874320218178,464.350835522916555,31.1234509916598299],"hsluv":[265.874320218178,90.4439719502614565,31.1234509916598299]},"#2222ee":{"lch":[33.2570959032629503,123.556928623667645,265.874320218178],"luv":[33.2570959032629503,-8.88923982631188103,-123.236747872639071],"rgb":[0.133333333333333331,0.133333333333333331,0.933333333333333348],"xyz":[0.166626488193990063,0.0765653799070641489,0.814913860070280327],"hpluv":[265.874320218178,471.435310205520636,33.2570959032629503],"hsluv":[265.874320218178,93.8546607467714296,33.2570959032629503]},"#2222ff":{"lch":[35.4068078244889,133.147814572056944,265.874320218177957],"luv":[35.4068078244889,-9.57925119428392335,-132.802780361977625],"rgb":[0.133333333333333331,0.133333333333333331,1],"xyz":[0.192797536603821457,0.0870337992709968589,0.952748048362062172],"hpluv":[265.874320218177957,477.184793215987838,35.4068078244889],"hsluv":[265.874320218177957,99.999999999999531,35.4068078244889]},"#77bb00":{"lch":[69.0844312744863629,87.8096536524333544,113.037133893102563],"luv":[69.0844312744863629,-34.3623439699837476,80.8069588058406225],"rgb":[0.466666666666666674,0.733333333333333282,0],"xyz":[0.253771247183507853,0.394617492952509585,0.0627978715952091093],"hpluv":[113.037133893102563,161.287757631366873,69.0844312744863629],"hsluv":[113.037133893102563,100.000000000002331,69.0844312744863629]},"#77bb11":{"lch":[69.1135050244688216,86.6316159473835654,113.342165034517933],"luv":[69.1135050244688216,-34.3252912529264051,79.5412550948043275],"rgb":[0.466666666666666674,0.733333333333333282,0.0666666666666666657],"xyz":[0.254782912683144958,0.395022159152364438,0.068125976559964746],"hpluv":[113.342165034517933,159.057013433643618,69.1135050244688216],"hsluv":[113.342165034517933,98.3127503818399,69.1135050244688216]},"#77bb22":{"lch":[69.1673475306790664,84.4748154027895595,113.924619678029501],"luv":[69.1673475306790664,-34.2574435126740582,77.2167209955934197],"rgb":[0.466666666666666674,0.733333333333333282,0.133333333333333331],"xyz":[0.256658270821622,0.395772302407755239,0.0780028627559439386],"hpluv":[113.924619678029501,154.976360107776344,69.1673475306790664],"hsluv":[113.924619678029501,95.2170715716625438,69.1673475306790664]},"#77bb33":{"lch":[69.2558504240405313,80.9996568929936132,114.934551128374181],"luv":[69.2558504240405313,-34.1480550559542593,73.4496749664571666],"rgb":[0.466666666666666674,0.733333333333333282,0.2],"xyz":[0.25974602155407972,0.397007402700738365,0.0942650166135550749],"hpluv":[114.934551128374181,148.410982175614635,69.2558504240405313],"hsluv":[114.934551128374181,90.2088459481891363,69.2558504240405313]},"#77bb44":{"lch":[69.3833048234310752,76.148419012573342,116.514961433737128],"luv":[69.3833048234310752,-33.9950520676451049,68.1389620777462426],"rgb":[0.466666666666666674,0.733333333333333282,0.266666666666666663],"xyz":[0.264204016798298635,0.398790600798425932,0.117743791566441713],"hpluv":[116.514961433737128,139.266042804817573,69.3833048234310752],"hsluv":[116.514961433737128,83.166634884803841,69.3833048234310752]},"#77bb55":{"lch":[69.5531781358710788,69.9670725739878918,118.886197685461212],"luv":[69.5531781358710788,-33.7990968432466516,61.2618339356121666],"rgb":[0.466666666666666674,0.733333333333333282,0.333333333333333315],"xyz":[0.270166430837660621,0.401175566414170792,0.149145838840415629],"hpluv":[118.886197685461212,127.648598426560824,69.5531781358710788],"hsluv":[118.886197685461212,74.0801666731923092,69.5531781358710788]},"#77bb66":{"lch":[69.7683097004737647,62.6192143930699672,122.411113057511386],"luv":[69.7683097004737647,-33.5633071802414804,52.8646424591145],"rgb":[0.466666666666666674,0.733333333333333282,0.4],"xyz":[0.277751426611168806,0.404209564723574111,0.189093483247559591],"hpluv":[122.411113057511386,113.8908252780179,69.7683097004737647],"hsluv":[122.411113057511386,63.0377921091212627,69.7683097004737647]},"#77bb77":{"lch":[70.0310134677453391,54.4237865803123384,127.71501294923867],"luv":[70.0310134677453391,-33.2928991557924476,43.0526585885427053],"rgb":[0.466666666666666674,0.733333333333333282,0.466666666666666674],"xyz":[0.287065439631370711,0.407935169931654906,0.2381472851539575],"hpluv":[127.71501294923867,98.6137944921033522,70.0310134677453391],"hsluv":[127.71501294923867,50.2119979074062357,70.0310134677453391]},"#77bb88":{"lch":[70.3431390634792422,45.948041729110173,135.896820739423845],"luv":[70.3431390634792422,-32.9947227526694,31.9776610966863863],"rgb":[0.466666666666666674,0.733333333333333282,0.533333333333333326],"xyz":[0.298205856733314512,0.412391336772432504,0.296820148557529695],"hpluv":[135.896820739423845,82.8866502392756246,70.3431390634792422],"hsluv":[135.896820739423845,51.9268484553617711,70.3431390634792422]},"#77bb99":{"lch":[70.7061124793432612,38.2197788608509725,148.75629343317604],"luv":[70.7061124793432612,-32.6767203094589,19.8238100775241328],"rgb":[0.466666666666666674,0.733333333333333282,0.6],"xyz":[0.311262820842387211,0.417614122416061662,0.365586826198647574],"hpluv":[148.75629343317604,68.5915373148405,70.7061124793432612],"hsluv":[148.75629343317604,53.7921873551213565,70.7061124793432612]},"#77bbaa":{"lch":[71.1209666334754615,33.0529501718716148,168.140026251468868],"luv":[71.1209666334754615,-32.3473621836046874,6.79306078486928744],"rgb":[0.466666666666666674,0.733333333333333282,0.66666666666666663],"xyz":[0.326320513807639767,0.423637199602162784,0.444890675815646175],"hpluv":[168.140026251468868,58.9728212370576585,71.1209666334754615],"hsluv":[168.140026251468868,55.7713219876506372,71.1209666334754615]},"#77bbbb":{"lch":[71.5883672123020744,32.7520226121926044,192.177050630060876],"luv":[71.5883672123020744,-32.0151171807858432,-6.90849166534396097],"rgb":[0.466666666666666674,0.733333333333333282,0.733333333333333282],"xyz":[0.343458105914976441,0.430492236445097542,0.535148660914287921],"hpluv":[192.177050630060876,58.0543804308889762,71.5883672123020744],"hsluv":[192.177050630060876,57.8271385543864938,71.5883672123020744]},"#77bbcc":{"lch":[72.1086367753872111,38.0603267014846267,213.636027248927832],"luv":[72.1086367753872111,-31.6880044447458609,-21.0821925551758049],"rgb":[0.466666666666666674,0.733333333333333282,0.8],"xyz":[0.36275048135869814,0.438209186622586344,0.636755171584558077],"hpluv":[213.636027248927832,66.97682452789428,72.1086367753872111],"hsluv":[213.636027248927832,59.9241419588218278,72.1086367753872111]},"#77bbdd":{"lch":[72.6817787487410101,47.4106862821029651,228.567760630430627],"luv":[72.6817787487410101,-31.3732552756954277,-35.5456330249727728],"rgb":[0.466666666666666674,0.733333333333333282,0.866666666666666696],"xyz":[0.384268806909331739,0.44681651684283985,0.750085019484564075],"hpluv":[228.567760630430627,82.7732525696479371,72.6817787487410101],"hsluv":[228.567760630430627,62.0300015657167449,72.6817787487410101]},"#77bbee":{"lch":[73.3075021126589803,58.9885691422652769,238.208313348868131],"luv":[73.3075021126589803,-31.0770938488335098,-50.1384635520735316],"rgb":[0.466666666666666674,0.733333333333333282,0.933333333333333348],"xyz":[0.408080987175506449,0.456341388949309867,0.875495835553087298],"hpluv":[238.208313348868131,102.107764199280055,73.3075021126589803],"hsluv":[238.208313348868131,76.3238953534044,73.3075021126589803]},"#77bbff":{"lch":[73.9852470697490219,71.6819577745528846,244.548916872628638],"luv":[73.9852470697490219,-30.8046295043453391,-64.7254036023940102],"rgb":[0.466666666666666674,0.733333333333333282,1],"xyz":[0.43425203558533787,0.466809808313242591,1.01333002384486903],"hpluv":[244.548916872628638,122.943070755930805,73.9852470697490219],"hsluv":[244.548916872628638,99.9999999999974,73.9852470697490219]},"#223300":{"lch":[18.8330192465532917,22.9063411551717806,108.204985820955727],"luv":[18.8330192465532917,-7.15634373768739707,21.7597612446731326],"rgb":[0.133333333333333331,0.2,0],"xyz":[0.0184344702910022862,0.0270769280882856428,0.00425513680873902],"hpluv":[108.204985820955727,154.338793470845559,18.8330192465532917],"hsluv":[108.204985820955727,100.000000000002331,18.8330192465532917]},"#223311":{"lch":[19.0056890338669575,18.4529510656336271,112.754551304246377],"luv":[19.0056890338669575,-7.13731020483261602,17.0167625026225657],"rgb":[0.133333333333333331,0.2,0.0666666666666666657],"xyz":[0.0194461357906394079,0.0274815942881404957,0.0095832417734946513],"hpluv":[112.754551304246377,123.203072156705915,19.0056890338669575],"hsluv":[112.754551304246377,76.6034511576994248,19.0056890338669575]},"#223322":{"lch":[19.3213416797184507,11.6344605438365232,127.71501294923759],"luv":[19.3213416797184507,-7.11719904028337247,9.20359440474635],"rgb":[0.133333333333333331,0.2,0.133333333333333331],"xyz":[0.0213214939291164265,0.028231737543531317,0.0194601279694738491],"hpluv":[127.71501294923759,76.4096652359405084,19.3213416797184507],"hsluv":[127.71501294923759,38.9061385447444366,19.3213416797184507]},"#223333":{"lch":[19.8290945906418372,7.27996715422488894,192.177050630060677],"luv":[19.8290945906418372,-7.11617124458192585,-1.53558737438758408],"rgb":[0.133333333333333331,0.2,0.2],"xyz":[0.0244092446615741671,0.0294668378365144298,0.0357222818270849923],"hpluv":[192.177050630060677,46.5871198449043149,19.8290945906418372],"hsluv":[192.177050630060677,46.4047641905018935,19.8290945906418372]},"#223344":{"lch":[20.5377244517829496,15.5714684077650816,242.621028364370432],"luv":[20.5377244517829496,-7.16091210703038339,-13.8272183091687548],"rgb":[0.133333333333333331,0.2,0.266666666666666663],"xyz":[0.0288672399057930476,0.031250035934202,0.0592010567799716309],"hpluv":[242.621028364370432,96.2091932027738181,20.5377244517829496],"hsluv":[242.621028364370432,54.472556800898019,20.5377244517829496]},"#223355":{"lch":[21.4445377167678828,27.4997828393463344,254.670418676715883],"luv":[21.4445377167678828,-7.27014529691604761,-26.5213695644274097],"rgb":[0.133333333333333331,0.2,0.333333333333333315],"xyz":[0.0348296539451550397,0.0336350015499468358,0.0906031040539455323],"hpluv":[254.670418676715883,162.72410902482622,21.4445377167678828],"hsluv":[254.670418676715883,62.1025047738862597,21.4445377167678828]},"#223366":{"lch":[22.538163137523668,39.6650934211933617,259.172698399253136],"luv":[22.538163137523668,-7.45106225263504562,-38.9589695374422647],"rgb":[0.133333333333333331,0.2,0.4],"xyz":[0.042414649718663211,0.0366689998593501473,0.130550748461089494],"hpluv":[259.172698399253136,223.320859110196579,22.538163137523668],"hsluv":[259.172698399253136,68.7622962285398103,22.538163137523668]},"#223377":{"lch":[23.8014699151847751,51.4679604591091,261.393782909523054],"luv":[23.8014699151847751,-7.70180102721624227,-50.8884389105972517],"rgb":[0.133333333333333331,0.2,0.466666666666666674],"xyz":[0.0517286627388651304,0.0403946050674309637,0.179604550367487403],"hpluv":[261.393782909523054,274.392670476726266,23.8014699151847751],"hsluv":[261.393782909523054,74.3066649079193837,23.8014699151847751]},"#223388":{"lch":[25.214303338898695,62.8010579136007649,262.667168962641028],"luv":[25.214303338898695,-8.01548446335257658,-62.2874376089207189],"rgb":[0.133333333333333331,0.2,0.533333333333333326],"xyz":[0.0628690798408089585,0.0448507719082085615,0.238277413771059571],"hpluv":[262.667168962641028,316.052560368409843,25.214303338898695],"hsluv":[262.667168962641028,78.8060188103052184,25.214303338898695]},"#223399":{"lch":[26.7557115473943199,73.7050787305795723,263.468936800572067],"luv":[26.7557115473943199,-8.38335327394953111,-73.2267575314180732],"rgb":[0.133333333333333331,0.2,0.6],"xyz":[0.0759260439498816719,0.0500735575518377191,0.307044091412177478],"hpluv":[263.468936800572067,349.558796760350788,26.7557115473943199],"hsluv":[263.468936800572067,82.4151943494814105,26.7557115473943199]},"#2233aa":{"lch":[28.4055164492709622,84.2578478733767184,264.007358934798901],"luv":[28.4055164492709622,-8.79658068794244485,-83.7974050699281],"rgb":[0.133333333333333331,0.2,0.66666666666666663],"xyz":[0.090983736915134214,0.0560966347379388205,0.386347941029176078],"hpluv":[264.007358934798901,376.397732872534505,28.4055164492709622],"hsluv":[264.007358934798901,85.301735461295209,28.4055164492709622]},"#2233bb":{"lch":[30.1452579578322855,94.5340435151979506,264.386468786418391],"luv":[30.1452579578322855,-9.24712484322681583,-94.0806891209195868],"rgb":[0.133333333333333331,0.2,0.733333333333333282],"xyz":[0.108121329022470861,0.0629516715808735861,0.476605926127817825],"hpluv":[264.386468786418391,397.931717533943186,30.1452579578322855],"hsluv":[264.386468786418391,87.6154589527103553,30.1452579578322855]},"#2233cc":{"lch":[31.9586404471462444,104.593501952517812,264.663323368501551],"luv":[31.9586404471462444,-9.72802821613955615,-104.140127317558722],"rgb":[0.133333333333333331,0.2,0.8],"xyz":[0.127413704466192601,0.0706686217583623877,0.578212436798088],"hpluv":[264.663323368501551,415.294074833826699,31.9586404471462444],"hsluv":[264.663323368501551,89.4797268300864,31.9586404471462444]},"#2233dd":{"lch":[33.8316358854510284,114.480561125644712,264.87147297862515],"luv":[33.8316358854510284,-10.233440845943651,-114.022259072932982],"rgb":[0.133333333333333331,0.2,0.866666666666666696],"xyz":[0.148932030016826145,0.0792759519786159217,0.691542284698094],"hpluv":[264.87147297862515,429.386195390892226,33.8316358854510284],"hsluv":[264.87147297862515,90.9921469937159,33.8316358854510284]},"#2233ee":{"lch":[35.7523793143002209,124.226868169083772,265.031742065807748],"luv":[35.7523793143002209,-10.7585230682670669,-123.760126682580946],"rgb":[0.133333333333333331,0.2,0.933333333333333348],"xyz":[0.172744210283000882,0.0888008240850859387,0.816953100766617202],"hpluv":[265.031742065807748,440.909964314972513,35.7523793143002209],"hsluv":[265.031742065807748,93.1343838757889557,35.7523793143002209]},"#2233ff":{"lch":[37.7109573358094536,133.854664271403067,265.157628752861342],"luv":[37.7109573358094536,-11.2993072928814158,-133.376897556927247],"rgb":[0.133333333333333331,0.2,1],"xyz":[0.198915258692832275,0.0992692434490186487,0.954787289058399],"hpluv":[265.157628752861342,450.407151983715153,37.7109573358094536],"hsluv":[265.157628752861342,99.9999999999994884,37.7109573358094536]},"#77cc00":{"lch":[74.2578384949046892,97.2071675743180776,115.806356387580706],"luv":[74.2578384949046892,-42.3172913249353897,87.5127435448238202],"rgb":[0.466666666666666674,0.8,0],"xyz":[0.291994990493124773,0.47106497957174448,0.0755391193650810505],"hpluv":[115.806356387580706,166.109821583261578,74.2578384949046892],"hsluv":[115.806356387580706,100.000000000002331,74.2578384949046892]},"#77cc11":{"lch":[74.283676291108776,96.1575231653334441,116.077287726142885],"luv":[74.283676291108776,-42.2692272766684525,86.3688698937585144],"rgb":[0.466666666666666674,0.8,0.0666666666666666657],"xyz":[0.293006655992761877,0.471469645771599333,0.0808672243298366872],"hpluv":[116.077287726142885,164.2590118749402,74.283676291108776],"hsluv":[116.077287726142885,98.5840266713216522,74.283676291108776]},"#77cc22":{"lch":[74.3315335987815331,94.2328042547367914,116.591431825394338],"luv":[74.3315335987815331,-42.1809937248656581,84.2649699821603519],"rgb":[0.466666666666666674,0.8,0.133333333333333331],"xyz":[0.294882014131238934,0.472219789026990133,0.0907441105258158798],"hpluv":[116.591431825394338,160.867513369155,74.3315335987815331],"hsluv":[116.591431825394338,95.9817736999432611,74.3315335987815331]},"#77cc33":{"lch":[74.410219680569412,91.1231466477069176,117.473161926834081],"luv":[74.410219680569412,-42.0381214847294515,80.8469182901527148],"rgb":[0.466666666666666674,0.8,0.2],"xyz":[0.29796976486369664,0.47345488931997326,0.10700626438342703],"hpluv":[117.473161926834081,155.394430123968846,74.410219680569412],"hsluv":[117.473161926834081,91.7599970515073551,74.410219680569412]},"#77cc44":{"lch":[74.5235830687713445,86.7634188586395,118.828926444460791],"luv":[74.5235830687713445,-41.8369758074171045,76.0102513305232748],"rgb":[0.466666666666666674,0.8,0.266666666666666663],"xyz":[0.302427760107915555,0.475238087417660826,0.130485039336313668],"hpluv":[118.828926444460791,147.734611978654129,74.5235830687713445],"hsluv":[118.828926444460791,85.7987877580492153,74.5235830687713445]},"#77cc55":{"lch":[74.6747602628398,81.1723246922669688,120.810965560633605],"luv":[74.6747602628398,-41.5770530159641396,69.7158156981220571],"rgb":[0.466666666666666674,0.8,0.333333333333333315],"xyz":[0.30839017414727754,0.477623053033405687,0.161887086610287556],"hpluv":[120.810965560633605,137.934680546119694,74.6747602628398],"hsluv":[120.810965560633605,78.0638956664307671,74.6747602628398]},"#77cc66":{"lch":[74.866352492363319,74.4599116278811692,123.651008617564372],"luv":[74.866352492363319,-41.2606832822808798,61.982533464768764],"rgb":[0.466666666666666674,0.8,0.4],"xyz":[0.315975169920785726,0.480657051342809,0.201834731017431546],"hpluv":[123.651008617564372,126.204595224585091,74.866352492363319],"hsluv":[123.651008617564372,68.5978490432360388,74.866352492363319]},"#77cc77":{"lch":[75.1005189251371519,66.8471540376336719,127.715012949239053],"luv":[75.1005189251371519,-40.8926996459993219,52.8803282761483189],"rgb":[0.466666666666666674,0.8,0.466666666666666674],"xyz":[0.325289182940987631,0.484382656550889801,0.250888532923829455],"hpluv":[127.715012949239053,112.948199149412858,75.1005189251371519],"hsluv":[127.715012949239053,57.5107647824030153,75.1005189251371519]},"#77cc88":{"lch":[75.3790318815133,58.7087525381891311,133.590980823477452],"luv":[75.3790318815133,-40.4800101313413947,42.5215992685696946],"rgb":[0.466666666666666674,0.8,0.533333333333333326],"xyz":[0.336429600042931432,0.488838823391667399,0.309561396327401595],"hpluv":[133.590980823477452,98.8306436104363542,75.3790318815133],"hsluv":[133.590980823477452,58.7660231359317748,75.3790318815133]},"#77cc99":{"lch":[75.7033128937519848,50.6622606125816759,142.200076129410462],"luv":[75.7033128937519848,-40.0310804193600305,31.0512036938324556],"rgb":[0.466666666666666674,0.8,0.6],"xyz":[0.349486564152004187,0.494061609035296556,0.378328073968519529],"hpluv":[142.200076129410462,84.9198084445103802,75.7033128937519848],"hsluv":[142.200076129410462,60.1459848784672815,75.7033128937519848]},"#77ccaa":{"lch":[76.0744587192654,43.7254195479873289,154.773618890386814],"luv":[76.0744587192654,-39.5553661600219684,18.6355928962322395],"rgb":[0.466666666666666674,0.8,0.66666666666666663],"xyz":[0.364544257117256687,0.500084686221397678,0.45763192358551813],"hpluv":[154.773618890386814,73.067319501552376,76.0744587192654],"hsluv":[154.773618890386814,61.6269813218812459,76.0744587192654]},"#77ccbb":{"lch":[76.4932621718819235,39.4413790272598561,172.054536865796422],"luv":[76.4932621718819235,-39.0627454070693716,5.45199970968949721],"rgb":[0.466666666666666674,0.8,0.733333333333333282],"xyz":[0.381681849224593361,0.506939723064332437,0.547889908684159876],"hpluv":[172.054536865796422,67.3385729198675733,76.4932621718819235],"hsluv":[172.054536865796422,63.1840553036415713,76.4932621718819235]},"#77cccc":{"lch":[76.9602305249106,39.4506200876857847,192.177050630060961],"luv":[76.9602305249106,-38.5629992967744357,-8.32144882456723778],"rgb":[0.466666666666666674,0.8,0.8],"xyz":[0.400974224668315116,0.514656673241821183,0.64949641935443],"hpluv":[192.177050630060961,69.0111626451701312,76.9602305249106],"hsluv":[192.177050630060961,64.792316690459316,76.9602305249106]},"#77ccdd":{"lch":[77.4756030772436475,44.2250390945155942,210.602473757279853],"luv":[77.4756030772436475,-38.0653777824919359,-22.5140200139291444],"rgb":[0.466666666666666674,0.8,0.866666666666666696],"xyz":[0.422492550218948604,0.5232640034620748,0.762826267254436],"hpluv":[210.602473757279853,79.5030322309331439,77.4756030772436475],"hsluv":[210.602473757279853,66.4280770246703156,77.4756030772436475]},"#77ccee":{"lch":[78.0393687787239116,52.7144148097026246,224.531483635923479],"luv":[78.0393687787239116,-37.5782716813780482,-36.9686762837126182],"rgb":[0.466666666666666674,0.8,0.933333333333333348],"xyz":[0.446304730485123369,0.532788875568544817,0.888237083322959253],"hpluv":[224.531483635923479,97.6926138158747648,78.0393687787239116],"hsluv":[224.531483635923479,71.3781641956177282,78.0393687787239116]},"#77ccff":{"lch":[78.6512843692400736,63.5145451324089052,234.249283216901347],"luv":[78.6512843692400736,-37.1089966152940249,-51.5462880679385549],"rgb":[0.466666666666666674,0.8,1],"xyz":[0.472475778894954734,0.54325729493247743,1.0260712716147411],"hpluv":[234.249283216901347,121.749546403725816,78.6512843692400736],"hsluv":[234.249283216901347,99.9999999999968168,78.6512843692400736]},"#224400":{"lch":[25.1809799681870601,33.4179584834008523,116.999863609689683],"luv":[25.1809799681870601,-15.1713647924420147,29.7756551486773162],"rgb":[0.133333333333333331,0.266666666666666663,0],"xyz":[0.0272670407739683193,0.0447420690542179589,0.00719932696972761486],"hpluv":[116.999863609689683,168.401755360818214,25.1809799681870601],"hsluv":[116.999863609689683,100.000000000002217,25.1809799681870601]},"#224411":{"lch":[25.304760275593587,29.8643723317269938,120.153298663054528],"luv":[25.304760275593587,-15.0013316265206242,25.8232605261065515],"rgb":[0.133333333333333331,0.266666666666666663,0.0666666666666666657],"xyz":[0.0282787062736054411,0.0451467352540728117,0.0125274319344832463],"hpluv":[120.153298663054528,149.758158325470362,25.304760275593587],"hsluv":[120.153298663054528,85.5029145399767287,25.304760275593587]},"#224422":{"lch":[25.5322735505540379,24.0578500603585184,127.715012949239281],"luv":[25.5322735505540379,-14.7170130248608242,19.0312815425753499],"rgb":[0.133333333333333331,0.266666666666666663,0.133333333333333331],"xyz":[0.0301540644120824597,0.0458968785094636331,0.0224043181304624424],"hpluv":[127.715012949239281,119.565711231297882,25.5322735505540379],"hsluv":[127.715012949239281,60.8802579098014363,25.5322735505540379]},"#224433":{"lch":[25.9015299317797343,16.981905402382786,147.498859327993841],"luv":[25.9015299317797343,-14.3222120947549634,9.12465625699578098],"rgb":[0.133333333333333331,0.266666666666666663,0.2],"xyz":[0.0332418151445402,0.0471319788024467459,0.0386664719880735891],"hpluv":[147.498859327993841,83.1955939146196357,25.9015299317797343],"hsluv":[147.498859327993841,64.09678513773909,25.9015299317797343]},"#224444":{"lch":[26.423438440277998,14.1959776348833024,192.177050630061],"luv":[26.423438440277998,-13.8765746732054378,-2.99440417262938974],"rgb":[0.133333333333333331,0.266666666666666663,0.266666666666666663],"xyz":[0.0376998103887590807,0.048915176900134319,0.0621452469409602276],"hpluv":[192.177050630061,68.1734546180548762,26.423438440277998],"hsluv":[192.177050630061,67.9066037165366367,26.423438440277998]},"#224455":{"lch":[27.1020089847707979,21.1158760403194243,230.453768193421723],"luv":[27.1020089847707979,-13.4444916811297333,-16.2826860310628518],"rgb":[0.133333333333333331,0.266666666666666663,0.333333333333333315],"xyz":[0.0436622244281210728,0.0513001425158791519,0.0935472942149341291],"hpluv":[230.453768193421723,98.865995891455,27.1020089847707979],"hsluv":[230.453768193421723,71.8953118433392717,27.1020089847707979]},"#224466":{"lch":[27.935501760142138,32.6185654266362306,246.366656325875056],"luv":[27.935501760142138,-13.0762038460066634,-29.8828329224226863],"rgb":[0.133333333333333331,0.266666666666666663,0.4],"xyz":[0.0512472202016292511,0.0543341408252824634,0.133494938622078091],"hpluv":[246.366656325875056,148.165710166053657,27.935501760142138],"hsluv":[246.366656325875056,75.7322080769735351,27.935501760142138]},"#224477":{"lch":[28.9175817086007072,45.1016041758277453,253.511262930840303],"luv":[28.9175817086007072,-12.8010466495854338,-43.2468253621948548],"rgb":[0.133333333333333331,0.266666666666666663,0.466666666666666674],"xyz":[0.0605612332218311636,0.0580597460333632798,0.182548740528476],"hpluv":[253.511262930840303,197.910731630760921,28.9175817086007072],"hsluv":[253.511262930840303,79.2164102145581381,28.9175817086007072]},"#224488":{"lch":[30.0385370730522183,57.5093846577101502,257.31357801273],"luv":[30.0385370730522183,-12.6299243743950456,-56.1053859625395432],"rgb":[0.133333333333333331,0.266666666666666663,0.533333333333333326],"xyz":[0.0717016503237749847,0.0625159128741408776,0.241221603932048168],"hpluv":[257.31357801273,242.94013543841632,30.0385370730522183],"hsluv":[257.31357801273,82.2624245727818106,30.0385370730522183]},"#224499":{"lch":[31.2864747985506213,69.5224780150470139,259.59064804278853],"luv":[31.2864747985506213,-12.5612993437317204,-68.3782765807230675],"rgb":[0.133333333333333331,0.266666666666666663,0.6],"xyz":[0.084758614432847712,0.0677386985177700351,0.309988281573166102],"hpluv":[259.59064804278853,281.973268281811727,31.2864747985506213],"hsluv":[259.59064804278853,84.8626039888072796,31.2864747985506213]},"#2244aa":{"lch":[32.6483868166792277,81.0719578322086676,261.068394107427196],"luv":[32.6483868166792277,-12.5868550230291323,-80.0889095154670372],"rgb":[0.133333333333333331,0.266666666666666663,0.66666666666666663],"xyz":[0.0998163073981002402,0.0737617757038711297,0.389292131190164703],"hpluv":[261.068394107427196,315.099896322028769,32.6483868166792277],"hsluv":[261.068394107427196,87.0515845849570695,32.6483868166792277]},"#2244bb":{"lch":[34.1110146972578292,92.183713113584,262.084105297610279],"luv":[34.1110146972578292,-12.6954785449376448,-91.3053217940914266],"rgb":[0.133333333333333331,0.266666666666666663,0.733333333333333282],"xyz":[0.116953899505436887,0.0806168125468058883,0.479550116288806449],"hpluv":[262.084105297610279,342.924793116778346,34.1110146972578292],"hsluv":[262.084105297610279,88.8814901896574128,34.1110146972578292]},"#2244cc":{"lch":[35.6614866183058439,102.915147630289923,262.812952152813068],"luv":[35.6614866183058439,-12.875606592693158,-102.106544191029045],"rgb":[0.133333333333333331,0.266666666666666663,0.8],"xyz":[0.136246274949158641,0.0883337627242946899,0.58115662695907655],"hpluv":[262.812952152813068,366.200711918304478,35.6614866183058439],"hsluv":[262.812952152813068,90.4075680541016453,35.6614866183058439]},"#2244dd":{"lch":[37.2877389569632456,113.32806156453313,263.353781276912969],"luv":[37.2877389569632456,-13.1164125913708496,-112.566465959927598],"rgb":[0.133333333333333331,0.266666666666666663,0.866666666666666696],"xyz":[0.157764600499792185,0.0969410929445482239,0.694486474859082548],"hpluv":[263.353781276912969,385.665452845521429,37.2877389569632456],"hsluv":[263.353781276912969,91.6811227311716408,37.2877389569632456]},"#2244ee":{"lch":[38.9787575249373575,123.477944203962494,263.76603971616106],"luv":[38.9787575249373575,-13.4082956886680194,-122.74779147325674],"rgb":[0.133333333333333331,0.266666666666666663,0.933333333333333348],"xyz":[0.181576780765966922,0.106465965051018269,0.819897290927605771],"hpluv":[263.76603971616106,401.976556214066079,38.9787575249373575],"hsluv":[263.76603971616106,92.7467647141115208,38.9787575249373575]},"#2244ff":{"lch":[40.7246816385265333,133.410810959437413,264.087324287658078],"luv":[40.7246816385265333,-13.7429938745542355,-132.701072340123574],"rgb":[0.133333333333333331,0.266666666666666663,1],"xyz":[0.207747829175798315,0.116934384414950965,0.957731479219387616],"hpluv":[264.087324287658078,415.692943868353552,40.7246816385265333],"hsluv":[264.087324287658078,99.9999999999994174,40.7246816385265333]},"#77dd00":{"lch":[79.4046595803128525,106.500737968556749,117.886764510297155],"luv":[79.4046595803128525,-49.8131268255250319,94.1332012826045457],"rgb":[0.466666666666666674,0.866666666666666696,0],"xyz":[0.3346289810403,0.556332960666096,0.089750449547472369],"hpluv":[117.886764510297155,213.048114553231642,79.4046595803128525],"hsluv":[117.886764510297155,100.000000000002288,79.4046595803128525]},"#77dd11":{"lch":[79.427785829561941,105.558219679332908,118.124490997004173],"luv":[79.427785829561941,-49.7589732732473422,93.0944806133132801],"rgb":[0.466666666666666674,0.866666666666666696,0.0666666666666666657],"xyz":[0.335640646539937082,0.556737626865951,0.095078554512228],"hpluv":[118.124490997004173,211.44368721760469,79.427785829561941],"hsluv":[118.124490997004173,98.7993418471683498,79.427785829561941]},"#77dd22":{"lch":[79.4706261070012658,103.827566318990023,118.57359388187615],"luv":[79.4706261070012658,-49.6593926395600249,91.1817319993116],"rgb":[0.466666666666666674,0.866666666666666696,0.133333333333333331],"xyz":[0.337516004678414139,0.557487770121341764,0.104955440708207198],"hpluv":[118.57359388187615,208.49071074424171,79.4706261070012658],"hsluv":[118.57359388187615,96.5898934808467,79.4706261070012658]},"#77dd33":{"lch":[79.5410783702752582,101.02472031386101,119.337697767432388],"luv":[79.5410783702752582,-49.4976803830995067,88.0680063995226874],"rgb":[0.466666666666666674,0.866666666666666696,0.2],"xyz":[0.340603755410871845,0.55872287041432489,0.121217594565818348],"hpluv":[119.337697767432388,203.689012727245881,79.5410783702752582],"hsluv":[119.337697767432388,92.9973786049096276,79.5410783702752582]},"#77dd44":{"lch":[79.6426121547728485,97.0801788178617073,120.498016398630853],"luv":[79.6426121547728485,-49.2690191092090188,83.6488187323909642],"rgb":[0.466666666666666674,0.866666666666666696,0.266666666666666663],"xyz":[0.34506175065509076,0.560506068512012456,0.144696369518705],"hpluv":[120.498016398630853,196.890303230407255,79.6426121547728485],"hsluv":[120.498016398630853,87.9077551580221126,79.6426121547728485]},"#77dd55":{"lch":[79.7780740091910729,91.9929116678805912,122.163902680224],"luv":[79.7780740091910729,-48.9717875622404577,77.8746417012192325],"rgb":[0.466666666666666674,0.866666666666666696,0.333333333333333315],"xyz":[0.351024164694452745,0.562891034127757206,0.176098416792678902],"hpluv":[122.163902680224,188.049297266091,79.7780740091910729],"hsluv":[122.163902680224,81.2740392578912889,79.7780740091910729]},"#77dd66":{"lch":[79.9498479155991788,85.8342168020908645,124.492086237753256],"luv":[79.9498479155991788,-48.6072648253697466,70.7449403153661],"rgb":[0.466666666666666674,0.866666666666666696,0.4],"xyz":[0.35860916046796093,0.565925032437160525,0.216046061199822836],"hpluv":[124.492086237753256,177.233761467474238,79.9498479155991788],"hsluv":[124.492086237753256,73.1095665987697174,79.9498479155991788]},"#77dd77":{"lch":[80.1599403321921,78.7586110849663896,127.715012949239352],"luv":[80.1599403321921,-48.1793469594900188,62.3030444407821093],"rgb":[0.466666666666666674,0.866666666666666696,0.466666666666666674],"xyz":[0.367923173488162836,0.569650637645241376,0.265099863106220746],"hpluv":[127.715012949239352,164.652954432832814,80.1599403321921],"hsluv":[127.715012949239352,63.4818861677236654,80.1599403321921]},"#77dd88":{"lch":[80.4100305893493754,71.0258644695610855,132.183293417803185],"luv":[80.4100305893493754,-47.69419139775556,52.6301959958607597],"rgb":[0.466666666666666674,0.866666666666666696,0.533333333333333326],"xyz":[0.379063590590106636,0.574106804486018918,0.323772726509792941],"hpluv":[132.183293417803185,150.716476916292407,80.4100305893493754],"hsluv":[132.183293417803185,64.4129914780986184,80.4100305893493754]},"#77dd99":{"lch":[80.7015034668449829,63.0436351039456042,138.421724913218469],"luv":[80.7015034668449829,-47.1597772740100254,41.838443261971527],"rgb":[0.466666666666666674,0.866666666666666696,0.6],"xyz":[0.392120554699179391,0.579329590129648131,0.39253940415091082],"hpluv":[138.421724913218469,136.149613262507529,80.7015034668449829],"hsluv":[138.421724913218469,65.4455974050235909,80.7015034668449829]},"#77ddaa":{"lch":[81.0354720941451916,55.4433276111880673,147.164903113494319],"luv":[81.0354720941451916,-46.5854032558204594,30.0626475895607292],"rgb":[0.466666666666666674,0.866666666666666696,0.66666666666666663],"xyz":[0.407178247664431892,0.585352667315749198,0.471843253767909421],"hpluv":[147.164903113494319,122.204418643173668,81.0354720941451916],"hsluv":[147.164903113494319,66.5644374268903505,81.0354720941451916]},"#77ddbb":{"lch":[81.4127955433910415,49.1817473647014651,159.215751775487576],"luv":[81.4127955433910415,-45.9811599326092804,17.452140415923953],"rgb":[0.466666666666666674,0.866666666666666696,0.733333333333333282],"xyz":[0.424315839771768566,0.592207704158684,0.562101238866551167],"hpluv":[159.215751775487576,110.971854928909636,81.4127955433910415],"hsluv":[159.215751775487576,67.7527973989238461,81.4127955433910415]},"#77ddcc":{"lch":[81.8340936239464298,45.5480287935550479,174.756411210455894],"luv":[81.8340936239464298,-45.3574175840417197,4.16264304083146897],"rgb":[0.466666666666666674,0.866666666666666696,0.8],"xyz":[0.44360821521549032,0.599924654336172813,0.663707749536821323],"hpluv":[174.756411210455894,105.54602277980743,81.8340936239464298],"hsluv":[174.756411210455894,68.9933910523739371,81.8340936239464298]},"#77dddd":{"lch":[82.299760373596115,45.7538051586653296,192.177050630060847],"luv":[82.299760373596115,-44.7243656053231931,-9.65100034703627],"rgb":[0.466666666666666674,0.866666666666666696,0.866666666666666696],"xyz":[0.465126540766123808,0.60853198455642632,0.777037597436827321],"hpluv":[192.177050630060847,109.256318691998032,82.299760373596115],"hsluv":[192.177050630060847,70.2691471280789557,82.299760373596115]},"#77ddee":{"lch":[82.8099771424448221,50.1244355238275574,208.400620203695752],"luv":[82.8099771424448221,-44.0916301090396274,-23.8408722766172367],"rgb":[0.466666666666666674,0.866666666666666696,0.933333333333333348],"xyz":[0.488938721032298573,0.618056856662896337,0.902448413505350544],"hpluv":[208.400620203695752,123.794681382199428,82.8099771424448221],"hsluv":[208.400620203695752,71.5638635335918,82.8099771424448221]},"#77ddff":{"lch":[83.364725787715372,57.9146258331384161,221.361714592462022],"luv":[83.364725787715372,-43.4679842885535521,-38.2705921992655504],"rgb":[0.466666666666666674,0.866666666666666696,1],"xyz":[0.515109769442129939,0.628525276026829061,1.0402826017971325],"hpluv":[221.361714592462022,148.517135389694232,83.364725787715372],"hsluv":[221.361714592462022,99.9999999999953531,83.364725787715372]},"#225500":{"lch":[31.4325909084541877,43.9203091385023825,121.065637009975248],"luv":[31.4325909084541877,-22.6637443991712324,37.6211143459447541],"rgb":[0.133333333333333331,0.333333333333333315,0],"xyz":[0.0390802974883142848,0.0683685824829102229,0.0111370792078428239],"hpluv":[121.065637009975248,177.306450001223254,31.4325909084541877],"hsluv":[121.065637009975248,100.000000000002373,31.4325909084541877]},"#225511":{"lch":[31.5259896590935043,41.027632513747335,123.178290947815412],"luv":[31.5259896590935043,-22.452213479362328,34.3389682366875704],"rgb":[0.133333333333333331,0.333333333333333315,0.0666666666666666657],"xyz":[0.04009196298795141,0.0687732486827650757,0.0164651841725984571],"hpluv":[123.178290947815412,165.138012967735222,31.5259896590935043],"hsluv":[123.178290947815412,90.3912533003173877,31.5259896590935043]},"#225522":{"lch":[31.6981615382414716,36.1013694166085486,127.715012949239792],"luv":[31.6981615382414716,-22.0844473877159331,28.5584673491706482],"rgb":[0.133333333333333331,0.333333333333333315,0.133333333333333331],"xyz":[0.0419673211264284252,0.0695233919381558901,0.0263420703685776497],"hpluv":[127.715012949239792,144.520324593974209,31.6981615382414716],"hsluv":[127.715012949239792,73.5866039174798345,31.6981615382414716]},"#225533":{"lch":[31.9789617713411829,29.2625646618711706,137.400330584271074],"luv":[31.9789617713411829,-21.5402028917408828,19.8070025489176231],"rgb":[0.133333333333333331,0.333333333333333315,0.2],"xyz":[0.0450550718588861657,0.070758492231139,0.0426042242261888],"hpluv":[137.400330584271074,116.114739730974975,31.9789617713411829],"hsluv":[137.400330584271074,75.0932106461487,31.9789617713411829]},"#225544":{"lch":[32.3786649626227785,22.5648709259736577,157.632626155133437],"luv":[32.3786649626227785,-20.8671549807805796,8.58692278490586247],"rgb":[0.133333333333333331,0.333333333333333315,0.266666666666666663],"xyz":[0.0495130671031050462,0.072541690328826583,0.0660829991790754384],"hpluv":[157.632626155133437,88.4327727432137465,32.3786649626227785],"hsluv":[157.632626155133437,76.9882679005547459,32.3786649626227785]},"#225555":{"lch":[32.9031430542149863,20.5945867127178737,192.177050630061132],"luv":[32.9031430542149863,-20.1312179923833199,-4.34408379417313384],"rgb":[0.133333333333333331,0.333333333333333315,0.333333333333333315],"xyz":[0.0554754811424670383,0.0749266559445714159,0.0974850464530493399],"hpluv":[192.177050630061132,79.4245973683706268,32.9031430542149863],"hsluv":[192.177050630061132,79.1137061933639245,32.9031430542149863]},"#225566":{"lch":[33.5545056011551,26.6006796322727546,223.177731373198952],"luv":[33.5545056011551,-19.398136743372234,-18.2018803364993715],"rgb":[0.133333333333333331,0.333333333333333315,0.4],"xyz":[0.0630604769159752165,0.0779606542539747344,0.137432690860193302],"hpluv":[223.177731373198952,100.596116474312993,33.5545056011551],"hsluv":[223.177731373198952,81.3097794801720113,33.5545056011551]},"#225577":{"lch":[34.3316296590174,37.3644949384619807,239.932022094073261],"luv":[34.3316296590174,-18.7206257951117045,-32.3364137134245127],"rgb":[0.133333333333333331,0.333333333333333315,0.466666666666666674],"xyz":[0.0723744899361771221,0.0816862594620555438,0.186486492766591211],"hpluv":[239.932022094073261,138.103289638438355,34.3316296590174],"hsluv":[239.932022094073261,83.4469752602442298,34.3316296590174]},"#225588":{"lch":[35.230707776085,49.7211482448765594,248.610781811292384],"luv":[35.230707776085,-18.1333810040152876,-46.2965773697387775],"rgb":[0.133333333333333331,0.333333333333333315,0.533333333333333326],"xyz":[0.0835149070381209502,0.0861424263028331416,0.245159356170163378],"hpluv":[248.610781811292384,179.084957393431893,35.230707776085],"hsluv":[248.610781811292384,85.4385601139613158,35.230707776085]},"#225599":{"lch":[36.2458273864096512,62.3718238545276336,253.557833057747018],"luv":[36.2458273864096512,-17.6541819100499602,-59.8211858126123],"rgb":[0.133333333333333331,0.333333333333333315,0.6],"xyz":[0.0965718711471936775,0.0913652119464623,0.313926033811281313],"hpluv":[253.557833057747018,218.35832406203005,36.2458273864096512],"hsluv":[253.557833057747018,87.2381583586425791,36.2458273864096512]},"#2255aa":{"lch":[37.3695533294905928,74.8190204360075,256.640324292617947],"luv":[37.3695533294905928,-17.2879233745104131,-72.7943234352841841],"rgb":[0.133333333333333331,0.333333333333333315,0.66666666666666663],"xyz":[0.111629564112446206,0.0973882891325634,0.393229883428279914],"hpluv":[256.640324292617947,254.058329165629146,37.3695533294905928],"hsluv":[256.640324292617947,88.8301308270208807,37.3695533294905928]},"#2255bb":{"lch":[38.5934754222231291,86.8805221786483,258.695157685582501],"luv":[38.5934754222231291,-17.0311035792378,-85.1948745225196831],"rgb":[0.133333333333333331,0.333333333333333315,0.733333333333333282],"xyz":[0.128767156219782852,0.104243325975498152,0.48348786852692166],"hpluv":[258.695157685582501,285.658965815982469,38.5934754222231291],"hsluv":[258.695157685582501,90.2188193496234874,38.5934754222231291]},"#2255cc":{"lch":[39.9086891196534097,98.5112685419302,260.136263381096],"luv":[39.9086891196534097,-16.8755295039118458,-97.0550695930042],"rgb":[0.133333333333333331,0.333333333333333315,0.8],"xyz":[0.148059531663504607,0.111960276152986954,0.585094379197191761],"hpluv":[260.136263381096,313.22597901471056,39.9086891196534097],"hsluv":[260.136263381096,91.4196885710314433,39.9086891196534097]},"#2255dd":{"lch":[41.3061900239028503,109.727240919989157,261.187210775965298],"luv":[41.3061900239028503,-16.8109176424286737,-108.431823962952976],"rgb":[0.133333333333333331,0.333333333333333315,0.866666666666666696],"xyz":[0.16957785721413815,0.120567606373240488,0.698424227097197758],"hpluv":[261.187210775965298,337.084394380702577,41.3061900239028503],"hsluv":[261.187210775965298,92.4531471705562353,41.3061900239028503]},"#2255ee":{"lch":[42.7771763125841602,120.569176865205208,261.977669343247612],"luv":[42.7771763125841602,-16.8265186863462972,-119.389256965822398],"rgb":[0.133333333333333331,0.333333333333333315,0.933333333333333348],"xyz":[0.193390037480312887,0.130092478479710533,0.823835043165721],"hpluv":[261.977669343247612,357.654347674158601,42.7771763125841602],"hsluv":[261.977669343247612,93.3407272081067,42.7771763125841602]},"#2255ff":{"lch":[44.3132637322964129,131.084767922007643,262.587267096581058],"luv":[44.3132637322964129,-16.9120289519133,-129.989229007238322],"rgb":[0.133333333333333331,0.333333333333333315,1],"xyz":[0.219561085890144281,0.140560897843643229,0.961669231457502827],"hpluv":[262.587267096581058,375.368494421854962,44.3132637322964129],"hsluv":[262.587267096581058,99.9999999999993463,44.3132637322964129]},"#77ee00":{"lch":[84.5193058633960703,115.647601499010833,119.483871035599748],"luv":[84.5193058633960703,-56.9192667804191,100.670575649757225],"rgb":[0.466666666666666674,0.933333333333333348,0],"xyz":[0.381807757380814794,0.650690513347127,0.105476708327643554],"hpluv":[119.483871035599748,321.869538605652735,84.5193058633960703],"hsluv":[119.483871035599748,100.000000000002359,84.5193058633960703]},"#77ee11":{"lch":[84.5401392884337355,114.795422022346642,119.691827475064969],"luv":[84.5401392884337355,-56.862163274863434,99.7230329712822083],"rgb":[0.466666666666666674,0.933333333333333348,0.0666666666666666657],"xyz":[0.382819422880451898,0.651095179546981928,0.11080481329239919],"hpluv":[119.691827475064969,319.985367790437692,84.5401392884337355],"hsluv":[119.691827475064969,98.9722780394741477,84.5401392884337355]},"#77ee22":{"lch":[84.5787360835130499,113.228793274865538,120.083373039169615],"luv":[84.5787360835130499,-56.7570256545281637,97.9765260934141651],"rgb":[0.466666666666666674,0.933333333333333348,0.133333333333333331],"xyz":[0.384694781018928955,0.651845322802372729,0.120681699488378383],"hpluv":[120.083373039169615,316.512949618186383,84.5787360835130499],"hsluv":[120.083373039169615,97.0790709390529,84.5787360835130499]},"#77ee33":{"lch":[84.6422206992536275,110.686316006337648,120.745647293955486],"luv":[84.6422206992536275,-56.585921413754825,95.1288286946244313],"rgb":[0.466666666666666674,0.933333333333333348,0.2],"xyz":[0.387782531751386661,0.653080423095355855,0.136943853345989519],"hpluv":[120.745647293955486,310.853610471304819,84.6422206992536275],"hsluv":[120.745647293955486,93.9952250088888093,84.6422206992536275]},"#77ee44":{"lch":[84.7337366993681513,107.096480548503891,121.742158736883837],"luv":[84.7337366993681513,-56.3431952848259598,91.0774422728923412],"rgb":[0.466666666666666674,0.933333333333333348,0.266666666666666663],"xyz":[0.392240526995605576,0.654863621193043421,0.160422628298876158],"hpluv":[121.742158736883837,302.811644310583176,84.7337366993681513],"hsluv":[121.742158736883837,89.6144795711786628,84.7337366993681513]},"#77ee55":{"lch":[84.8558768548969766,102.444399932600575,123.154228511336783],"luv":[84.8558768548969766,-56.0262879596216621,85.7666026785261266],"rgb":[0.466666666666666674,0.933333333333333348,0.333333333333333315],"xyz":[0.398202941034967561,0.657248586808788171,0.191824675572850073],"hpluv":[123.154228511336783,292.298881153811294,84.8558768548969766],"hsluv":[123.154228511336783,83.883891015311761,84.8558768548969766]},"#77ee66":{"lch":[85.0108293450033159,96.7735040486586,125.092887734820366],"luv":[85.0108293450033159,-55.6354444449268186,79.1821217654036],"rgb":[0.466666666666666674,0.933333333333333348,0.4],"xyz":[0.405787936808475747,0.66028258511819149,0.231772319979994035],"hpluv":[125.092887734820366,279.341716913636219,85.0108293450033159],"hsluv":[125.092887734820366,76.7984153057879411,85.0108293450033159]},"#77ee77":{"lch":[85.2004556710930814,90.1918871908529667,127.71501294923965],"luv":[85.2004556710930814,-55.1734745704367882,71.3474892261312306],"rgb":[0.466666666666666674,0.933333333333333348,0.466666666666666674],"xyz":[0.415101949828677652,0.664008190326272341,0.280826121886391944],"hpluv":[127.71501294923965,264.105357222364148,85.2004556710930814],"hsluv":[127.71501294923965,68.3966317942099522,85.2004556710930814]},"#77ee88":{"lch":[85.4263369442757323,82.8846309918514521,131.246169999264879],"luv":[85.4263369442757323,-54.6454688778224167,62.3196179848555],"rgb":[0.466666666666666674,0.933333333333333348,0.533333333333333326],"xyz":[0.426242366930621452,0.668464357167049883,0.339498985289964139],"hpluv":[131.246169999264879,246.94310788397641,85.4263369442757323],"hsluv":[131.246169999264879,69.0963798671032379,85.4263369442757323]},"#77ee99":{"lch":[85.6898036798217,75.1362836057233,136.010896750223054],"luv":[85.6898036798217,-54.0584447513185395,52.1837682153016473],"rgb":[0.466666666666666674,0.933333333333333348,0.6],"xyz":[0.439299331039694207,0.673687142810679096,0.408265662931082],"hpluv":[136.010896750223054,228.489214549916312,85.6898036798217],"hsluv":[136.010896750223054,69.8780652000076827,85.6898036798217]},"#77eeaa":{"lch":[85.9919564191548602,67.3699388554866232,142.461966648640384],"luv":[85.9919564191548602,-53.4209300451477489,41.0476904892764551],"rgb":[0.466666666666666674,0.933333333333333348,0.66666666666666663],"xyz":[0.454357024004946708,0.679710219996780163,0.487569512548080619],"hpluv":[142.461966648640384,209.826142071523691,85.9919564191548602],"hsluv":[142.461966648640384,70.7318226594993575,85.9919564191548602]},"#77eebb":{"lch":[86.3336811163097337,60.2064759054885243,151.166773543866697],"luv":[86.3336811163097337,-52.7425080063862524,29.0352818163428843],"rgb":[0.466666666666666674,0.933333333333333348,0.733333333333333282],"xyz":[0.471494616112283382,0.686565256839714921,0.577827497646722366],"hpluv":[151.166773543866697,192.758378827545073,86.3336811163097337],"hsluv":[151.166773543866697,71.6464628016145895,86.3336811163097337]},"#77eecc":{"lch":[86.7156615657761449,54.5207620102438284,162.626180625161169],"luv":[86.7156615657761449,-52.0333543078463094,16.2801575438255028],"rgb":[0.466666666666666674,0.933333333333333348,0.8],"xyz":[0.490786991556005137,0.694282207017203778,0.679434008316992522],"hpluv":[162.626180625161169,180.150974339718545,86.7156615657761449],"hsluv":[162.626180625161169,72.6100300694190111,86.7156615657761449]},"#77eedd":{"lch":[87.1383902516757445,51.3868015721907483,176.742975614533037],"luv":[87.1383902516757445,-51.3037971188162771,2.91955082350760353],"rgb":[0.466666666666666674,0.933333333333333348,0.866666666666666696],"xyz":[0.512305317106638625,0.702889537237457285,0.792763856216998519],"hpluv":[176.742975614533037,175.997429168902841,87.1383902516757445],"hsluv":[176.742975614533037,73.6103328445444305,87.1383902516757445]},"#77eeee":{"lch":[87.6021784736708327,51.7277775307036,192.177050630061075],"luv":[87.6021784736708327,-50.5639263491039941,-10.9111099540033418],"rgb":[0.466666666666666674,0.933333333333333348,0.933333333333333348],"xyz":[0.536117497372813334,0.712414409343927302,0.918174672285521742],"hpluv":[192.177050630061075,184.503896016801804,87.6021784736708327],"hsluv":[192.177050630061075,74.6354143053272594,87.6021784736708327]},"#77eeff":{"lch":[88.107166277409533,55.7808213308350673,206.722210113893169],"luv":[88.107166277409533,-49.8232704905303336,-25.0826981397535107],"rgb":[0.466666666666666674,0.933333333333333348,1],"xyz":[0.562288545782644755,0.72288282870786,1.05600886057730348],"hpluv":[206.722210113893169,208.278116369071,88.107166277409533],"hsluv":[206.722210113893169,99.9999999999928804,88.107166277409533]},"#226600":{"lch":[37.5582057574881532,54.1200869321592961,123.236537452327113],"luv":[37.5582057574881532,-29.6630419039077431,45.2668505040000824],"rgb":[0.133333333333333331,0.4,0],"xyz":[0.0541083551941607538,0.0984246978946035633,0.0161464317764581713],"hpluv":[123.236537452327113,182.849162381267462,37.5582057574881532],"hsluv":[123.236537452327113,100.000000000002288,37.5582057574881532]},"#226611":{"lch":[37.6315056544729529,51.7196180195473119,124.710513292064419],"luv":[37.6315056544729529,-29.4507212427394194,42.5155725160833242],"rgb":[0.133333333333333331,0.4,0.0666666666666666657],"xyz":[0.0551200206937978721,0.0988293640944584162,0.0214745367412138],"hpluv":[124.710513292064419,174.398618448608886,37.6315056544729529],"hsluv":[124.710513292064419,93.2756924270169918,37.6315056544729529]},"#226622":{"lch":[37.7668566222969062,47.5272711912458519,127.715012949240034],"luv":[37.7668566222969062,-29.0740638670039928,37.5970785719263176],"rgb":[0.133333333333333331,0.4,0.133333333333333331],"xyz":[0.0569953788322748942,0.0995795073498492306,0.031351422937193],"hpluv":[127.715012949240034,159.687663587322874,37.7668566222969062],"hsluv":[127.715012949240034,81.309482828258183,37.7668566222969062]},"#226633":{"lch":[37.9882367851431084,41.3581300307957349,133.555287588173542],"luv":[37.9882367851431084,-28.497993426715972,29.9726423642471254],"rgb":[0.133333333333333331,0.4,0.2],"xyz":[0.0600831295647326347,0.100814607642832343,0.0476135767948041438],"hpluv":[133.555287588173542,138.150062101989391,37.9882367851431084],"hsluv":[133.555287588173542,82.0766642375396742,37.9882367851431084]},"#226644":{"lch":[38.3046909892153806,34.1393686276432291,144.379277801066621],"luv":[38.3046909892153806,-27.7515572052733894,19.8833488873617412],"rgb":[0.133333333333333331,0.4,0.266666666666666663],"xyz":[0.0645411248089515083,0.102597805740519923,0.0710923517476907824],"hpluv":[144.379277801066621,113.094855071532635,38.3046909892153806],"hsluv":[144.379277801066621,83.0794073538424414,38.3046909892153806]},"#226655":{"lch":[38.7222568592555234,28.0005039743963025,163.778220785970291],"luv":[38.7222568592555234,-26.8857357715149732,7.82211191715276755],"rgb":[0.133333333333333331,0.4,0.333333333333333315],"xyz":[0.0705035388483135073,0.104982771356264756,0.102494399021664684],"hpluv":[163.778220785970291,91.7581213405574516,38.7222568592555234],"hsluv":[163.778220785970291,84.2573678500350809,38.7222568592555234]},"#226666":{"lch":[39.2444156655659739,26.5583838540848376,192.177050630061103],"luv":[39.2444156655659739,-25.9608324434988,-5.60204710632589631],"rgb":[0.133333333333333331,0.4,0.4],"xyz":[0.0780885346218216786,0.108016769665668075,0.142442043428808646],"hpluv":[192.177050630061103,85.8742788705857691,39.2444156655659739],"hsluv":[192.177050630061103,85.5381417500271652,39.2444156655659739]},"#226677":{"lch":[39.8723950361637449,31.9118423017057466,218.325872967111877],"luv":[39.8723950361637449,-25.034725973132506,-19.7895976345933065],"rgb":[0.133333333333333331,0.4,0.466666666666666674],"xyz":[0.0874025476420236,0.111742374873748884,0.191495845335206555],"hpluv":[218.325872967111877,101.559108573692257,39.8723950361637449],"hsluv":[218.325872967111877,86.8516914397336137,39.8723950361637449]},"#226688":{"lch":[40.6054458094686836,41.8995680003496318,234.7955790683381],"luv":[40.6054458094686836,-24.1549067561574908,-34.2361545477476241],"rgb":[0.133333333333333331,0.4,0.533333333333333326],"xyz":[0.0985429647439674261,0.116198541714526482,0.250168708738778722],"hpluv":[234.7955790683381,130.937664052949941,40.6054458094686836],"hsluv":[234.7955790683381,88.1401386465251733,40.6054458094686836]},"#226699":{"lch":[41.4411308461218226,53.8933488408681782,244.319142730286046],"luv":[41.4411308461218226,-23.3551142576285748,-48.5698639826860301],"rgb":[0.133333333333333331,0.4,0.6],"xyz":[0.11159992885304014,0.12142132735815564,0.318935386379896657],"hpluv":[244.319142730286046,165.022400136876769,41.4411308461218226],"hsluv":[244.319142730286046,89.3619383181549267,41.4411308461218226]},"#2266aa":{"lch":[42.3756299296545578,66.5269840788925251,250.089735516440328],"luv":[42.3756299296545578,-22.655631138578233,-62.5504755245386193],"rgb":[0.133333333333333331,0.4,0.66666666666666663],"xyz":[0.126657621818292682,0.127444404544256734,0.398239235996895258],"hpluv":[250.089735516440328,199.214522587526545,42.3756299296545578],"hsluv":[250.089735516440328,90.4915899210210597,42.3756299296545578]},"#2266bb":{"lch":[43.404050412459263,79.1834510223872599,253.819475134999237],"luv":[43.404050412459263,-22.0656311263342282,-76.0468726432017803],"rgb":[0.133333333333333331,0.4,0.733333333333333282],"xyz":[0.143795213925629328,0.134299441387191493,0.488497221095537],"hpluv":[253.819475134999237,231.496000814517572,43.404050412459263],"hsluv":[253.819475134999237,91.5168425909476895,43.404050412459263]},"#2266cc":{"lch":[44.520728505208055,91.5877705166709,256.367788484306971],"luv":[44.520728505208055,-21.5861851194902563,-89.0076194502553193],"rgb":[0.133333333333333331,0.4,0.8],"xyz":[0.163087589369351083,0.142016391564680294,0.590103731765807105],"hpluv":[256.367788484306971,261.044502527732277,44.520728505208055],"hsluv":[256.367788484306971,92.43509558526695,44.520728505208055]},"#2266dd":{"lch":[45.7195068588792211,103.627896901795907,258.1878164043369],"luv":[45.7195068588792211,-21.2130654589597789,-101.433460308337743],"rgb":[0.133333333333333331,0.4,0.866666666666666696],"xyz":[0.184605914919984626,0.150623721784933828,0.703433579665813102],"hpluv":[258.1878164043369,287.616948003961852,45.7195068588792211],"hsluv":[258.1878164043369,93.2500413525610696,45.7195068588792211]},"#2266ee":{"lch":[46.9939777237187144,115.273293340910215,259.534328145616598],"luv":[46.9939777237187144,-20.9389771714321675,-113.35559709460216],"rgb":[0.133333333333333331,0.4,0.933333333333333348],"xyz":[0.208418095186159336,0.160148593891403873,0.828844395734336326],"hpluv":[259.534328145616598,311.261797341727515,46.9939777237187144],"hsluv":[259.534328145616598,93.969002023907521,46.9939777237187144]},"#2266ff":{"lch":[48.3376856243364728,126.534150990995641,260.559220542156197],"luv":[48.3376856243364728,-20.75515631493003,-124.820330288598825],"rgb":[0.133333333333333331,0.4,1],"xyz":[0.234589143595990757,0.170617013255336569,0.966678584026118171],"hpluv":[260.559220542156197,332.170629177470857,48.3376856243364728],"hsluv":[260.559220542156197,99.9999999999992184,48.3376856243364728]},"#77ff00":{"lch":[89.5984732569245921,124.632639236881928,120.733702851753719],"luv":[89.5984732569245921,-63.6933378884713406,107.128210438594465],"rgb":[0.466666666666666674,1,0],"xyz":[0.433660129810488626,0.754395258206476127,0.122760832470867665],"hpluv":[120.733702851753719,538.628162219261071,89.5984732569245921],"hsluv":[120.733702851753719,100.000000000002359,89.5984732569245921]},"#77ff11":{"lch":[89.6173512893739144,123.857431845856226,120.915842858481739],"luv":[89.6173512893739144,-63.635285050623331,106.260123846986147],"rgb":[0.466666666666666674,1,0.0666666666666666657],"xyz":[0.43467179531012573,0.754799924406331,0.128088937435623301],"hpluv":[120.915842858481739,536.333532616984598,89.6173512893739144],"hsluv":[120.915842858481739,99.9999999999912461,89.6173512893739144]},"#77ff22":{"lch":[89.6523282897647107,122.430860002153082,121.257903913559275],"luv":[89.6523282897647107,-63.5282943614823736,104.658832863679763],"rgb":[0.466666666666666674,1,0.133333333333333331],"xyz":[0.436547153448602787,0.755550067661721836,0.13796582363160248],"hpluv":[121.257903913559275,532.099457877515,89.6523282897647107],"hsluv":[121.257903913559275,99.9999999999912319,89.6523282897647107]},"#77ff33":{"lch":[89.7098670229763684,120.111567958755899,121.833904144252088],"luv":[89.7098670229763684,-63.3538816193187557,102.044472860004433],"rgb":[0.466666666666666674,1,0.2],"xyz":[0.439634904181060493,0.756785167954705,0.15422797748921363],"hpluv":[121.833904144252088,525.184015431200237,89.7098670229763684],"hsluv":[121.833904144252088,99.9999999999911893,89.7098670229763684]},"#77ff44":{"lch":[89.7928292607091834,116.827732221897932,122.694629127971339],"luv":[89.7928292607091834,-63.1058355300939766,98.317712230097257],"rgb":[0.466666666666666674,1,0.266666666666666663],"xyz":[0.444092899425279408,0.758568366052392529,0.177706752442100269],"hpluv":[122.694629127971339,515.324540814372313,89.7928292607091834],"hsluv":[122.694629127971339,99.9999999999912319,89.7928292607091834]},"#77ff55":{"lch":[89.9035853929870683,112.554947355203538,123.902387884937639],"luv":[89.9035853929870683,-62.7808648215699492,93.4193726503684161],"rgb":[0.466666666666666674,1,0.333333333333333315],"xyz":[0.450055313464641393,0.760953331668137278,0.209108799716074184],"hpluv":[123.902387884937639,502.374863630046946,89.9035853929870683],"hsluv":[123.902387884937639,99.9999999999911466,89.9035853929870683]},"#77ff66":{"lch":[90.0441481999633169,107.316590618570714,125.538864396596409],"luv":[90.0441481999633169,-62.3783098318914213,87.3258099562234662],"rgb":[0.466666666666666674,1,0.4],"xyz":[0.457640309238149579,0.763987329977540597,0.249056444123218146],"hpluv":[125.538864396596409,486.310350268178581,90.0441481999633169],"hsluv":[125.538864396596409,99.9999999999909193,90.0441481999633169]},"#77ff77":{"lch":[90.2162444924982,101.18761180958829,127.715012949239778],"luv":[90.2162444924982,-61.8999369112410065,80.0458031011764746],"rgb":[0.466666666666666674,1,0.466666666666666674],"xyz":[0.466954322258351484,0.767712935185621448,0.298110246029616055],"hpluv":[127.715012949239778,467.252180695244249,90.2162444924982],"hsluv":[127.715012949239778,99.9999999999908908,90.2162444924982]},"#77ff88":{"lch":[90.4213578195287084,94.3018691223763312,130.584388318929172],"luv":[90.4213578195287084,-61.3497133683486666,71.6174223886566352],"rgb":[0.466666666666666674,1,0.533333333333333326],"xyz":[0.478094739360295284,0.772169102026399,0.35678310943318825],"hpluv":[130.584388318929172,445.517691352744919,90.4213578195287084],"hsluv":[130.584388318929172,99.999999999990834,90.4213578195287084]},"#77ff99":{"lch":[90.660755936805927,86.8649116623181,134.360625617567337],"luv":[90.660755936805927,-60.7335297134313734,62.1043577106315],"rgb":[0.466666666666666674,1,0.6],"xyz":[0.491151703469368,0.777391887670028203,0.425549787074306129],"hpluv":[134.360625617567337,421.714412879972315,90.660755936805927],"hsluv":[134.360625617567337,99.9999999999904645,90.660755936805927]},"#77ffaa":{"lch":[90.9355096576679927,79.1755179707932513,139.336843070371486],"luv":[90.9355096576679927,-60.0588662825700368,51.5916197341755947],"rgb":[0.466666666666666674,1,0.66666666666666663],"xyz":[0.506209396434620595,0.78341496485612927,0.504853636691304786],"hpluv":[139.336843070371486,396.909453229520182,90.9355096576679927],"hsluv":[139.336843070371486,99.9999999999902371,90.9355096576679927]},"#77ffbb":{"lch":[91.2465066485729466,71.6593730134265599,145.894485367843032],"luv":[91.2465066485729466,-59.3344173347434776,40.1807498713488229],"rgb":[0.466666666666666674,1,0.733333333333333282],"xyz":[0.523346988541957159,0.790270001699064,0.595111621789946477],"hpluv":[145.894485367843032,372.920765055848051,91.2465066485729466],"hsluv":[145.894485367843032,99.9999999999901803,91.2465066485729466]},"#77ffcc":{"lch":[91.5944622372901591,64.9119206982031329,154.461378490718602],"luv":[91.5944622372901591,-58.5696939322881676,27.9847887504604707],"rgb":[0.466666666666666674,1,0.8],"xyz":[0.542639363985678913,0.797986951876552886,0.696718132460216633],"hpluv":[154.461378490718602,352.767904832744364,91.5944622372901591],"hsluv":[154.461378490718602,99.999999999989825,91.5944622372901591]},"#77ffdd":{"lch":[91.9799284987297,59.7212008687906604,165.331177548206284],"luv":[91.9799284987297,-57.7746296637575298,15.1232933062250314],"rgb":[0.466666666666666674,1,0.866666666666666696],"xyz":[0.564157689536312512,0.806594282096806392,0.81004798036022263],"hpluv":[165.331177548206284,341.200809564626638,91.9799284987297],"hsluv":[165.331177548206284,99.9999999999894698,91.9799284987297]},"#77ffee":{"lch":[92.4033024177180238,56.9851054432815545,178.272694676027839],"luv":[92.4033024177180238,-56.9592119034112,1.71767916801026743],"rgb":[0.466666666666666674,1,0.933333333333333348],"xyz":[0.587969869802487222,0.816119154203276409,0.935458796428745853],"hpluv":[178.272694676027839,344.865805035808421,92.4033024177180238],"hsluv":[178.272694676027839,99.9999999999889582,92.4033024177180238]},"#77ffff":{"lch":[92.8648336399367196,57.4251975820971623,192.177050630061018],"luv":[92.8648336399367196,-56.1331570721439945,-12.112885471963672],"rgb":[0.466666666666666674,1,1],"xyz":[0.614140918212318643,0.826587573567209133,1.0732929847205277],"hpluv":[192.177050630061018,371.354821198433683,92.8648336399367196],"hsluv":[192.177050630061018,99.9999999999883187,92.8648336399367196]},"#227700":{"lch":[43.5559297152692295,63.9882214930525208,124.519604676885976],"luv":[43.5559297152692295,-36.2613695379953711,52.7219647687080268],"rgb":[0.133333333333333331,0.466666666666666674,0],"xyz":[0.0725620932475783825,0.13533217400143932,0.0222976777942638753],"hpluv":[124.519604676885976,186.419817132403381,43.5559297152692295],"hsluv":[124.519604676885976,100.000000000002331,43.5559297152692295]},"#227711":{"lch":[43.6152314308602769,61.9621092027414093,125.591738779589861],"luv":[43.6152314308602769,-36.0623023987336282,50.3866383335378174],"rgb":[0.133333333333333331,0.466666666666666674,0.0666666666666666657],"xyz":[0.0735737587472155,0.135736840201294173,0.0276257827590195085],"hpluv":[125.591738779589861,180.271610265320959,43.6152314308602769],"hsluv":[125.591738779589861,95.0867888092805345,43.6152314308602769]},"#227722":{"lch":[43.7248500006056062,58.3665782213362476,127.715012949240148],"luv":[43.7248500006056062,-35.7048401974777292,46.1716562377823081],"rgb":[0.133333333333333331,0.466666666666666674,0.133333333333333331],"xyz":[0.0754491168856925298,0.136486983456685,0.0375026689549987],"hpluv":[127.715012949240148,169.385110384242353,43.7248500006056062],"hsluv":[127.715012949240148,86.2472116803111248,43.7248500006056062]},"#227733":{"lch":[43.9044636679785,52.8998675233047422,131.63685913347058],"luv":[43.9044636679785,-35.1470498804547518,39.5358175416168365],"rgb":[0.133333333333333331,0.466666666666666674,0.2],"xyz":[0.0785368676181502634,0.137722083749668101,0.0537648228126098443],"hpluv":[131.63685913347058,152.892166506547881,43.9044636679785],"hsluv":[131.63685913347058,86.6671370230467204,43.9044636679785]},"#227744":{"lch":[44.1618994548856207,46.0187725021067919,138.382113458020484],"luv":[44.1618994548856207,-34.403210499316,30.5638107889119937],"rgb":[0.133333333333333331,0.466666666666666674,0.266666666666666663],"xyz":[0.082994862862369137,0.139505281847355694,0.0772435977654964828],"hpluv":[138.382113458020484,132.228969104156789,44.1618994548856207],"hsluv":[138.382113458020484,87.230083060842972,44.1618994548856207]},"#227755":{"lch":[44.5028042963196171,38.7961505601339098,149.7341572603126],"luv":[44.5028042963196171,-33.5080868304533865,19.5537570621958743],"rgb":[0.133333333333333331,0.466666666666666674,0.333333333333333315],"xyz":[0.088957276901731136,0.141890247463100527,0.108645645039470398],"hpluv":[149.7341572603126,110.621765171639552,44.5028042963196171],"hsluv":[149.7341572603126,87.9126674499387235,44.5028042963196171]},"#227766":{"lch":[44.9310046324235657,33.2418513983527504,167.948858330193701],"luv":[44.9310046324235657,-32.5092552143098246,6.94038974417402166],"rgb":[0.133333333333333331,0.466666666666666674,0.4],"xyz":[0.0965422726752393073,0.144924245772503818,0.148593289446614346],"hpluv":[167.948858330193701,93.8811500215461,44.9310046324235657],"hsluv":[167.948858330193701,88.6822605795820778,44.9310046324235657]},"#227777":{"lch":[45.4487163896678652,32.1827345016432886,192.177050630061217],"luv":[45.4487163896678652,-31.4586377906525136,-6.7884098550242733],"rgb":[0.133333333333333331,0.466666666666666674,0.466666666666666674],"xyz":[0.105856285695441227,0.148649850980584641,0.197647091353012255],"hpluv":[192.177050630061217,89.8546686552558,45.4487163896678652],"hsluv":[192.177050630061217,89.5029511213474,45.4487163896678652]},"#227788":{"lch":[46.0567093690380389,37.0457871068229778,214.840569513336618],"luv":[46.0567093690380389,-30.4051407329018595,-21.1640676472289648],"rgb":[0.133333333333333331,0.466666666666666674,0.533333333333333326],"xyz":[0.116996702797385055,0.153106017821362239,0.256319954756584423],"hpluv":[214.840569513336618,102.066975938242322,46.0567093690380389],"hsluv":[214.840569513336618,90.3407286635711415,46.0567093690380389]},"#227799":{"lch":[46.7544651468991219,46.3079141704010908,230.605362437026685],"luv":[46.7544651468991219,-29.3896969252833173,-35.7864308006991223],"rgb":[0.133333333333333331,0.466666666666666674,0.6],"xyz":[0.130053666906457754,0.158328803464991397,0.325086632397702358],"hpluv":[230.605362437026685,125.681528260779189,46.7544651468991219],"hsluv":[230.605362437026685,91.1669787694701,46.7544651468991219]},"#2277aa":{"lch":[47.5403420753171133,57.8256716053654429,240.536105931551504],"luv":[47.5403420753171133,-28.4430017925967782,-50.3468365007961935],"rgb":[0.133333333333333331,0.466666666666666674,0.66666666666666663],"xyz":[0.14511135987171031,0.164351880651092491,0.404390482014700958],"hpluv":[240.536105931551504,154.346828351852139,47.5403420753171133],"hsluv":[240.536105931551504,91.9600907928071365,47.5403420753171133]},"#2277bb":{"lch":[48.4117490016133161,70.2708193466387172,246.886175208709233],"luv":[48.4117490016133161,-27.5854458877112236,-64.6299561103370337],"rgb":[0.133333333333333331,0.466666666666666674,0.733333333333333282],"xyz":[0.162248951979046957,0.17120691749402725,0.494648467113342705],"hpluv":[246.886175208709233,184.188949495161438,48.4117490016133161],"hsluv":[246.886175208709233,92.7055270960754427,48.4117490016133161]},"#2277cc":{"lch":[49.3653235224945348,82.9601291275659634,251.131977113837081],"luv":[49.3653235224945348,-26.8284223951791141,-78.5023488607078],"rgb":[0.133333333333333331,0.466666666666666674,0.8],"xyz":[0.181541327422768684,0.178923867671516051,0.596254977783612805],"hpluv":[251.131977113837081,213.248879712122147,49.3653235224945348],"hsluv":[251.131977113837081,93.3949294454883301,49.3653235224945348]},"#2277dd":{"lch":[50.3971082370692898,95.5506012475210156,254.100456017762497],"luv":[50.3971082370692898,-26.1762366694964186,-91.8951687118820928],"rgb":[0.133333333333333331,0.466666666666666674,0.866666666666666696],"xyz":[0.203059652973402227,0.187531197891769585,0.709584825683618803],"hpluv":[254.100456017762497,240.584217083197558,50.3971082370692898],"hsluv":[254.100456017762497,94.0248036114472399,50.3971082370692898]},"#2277ee":{"lch":[51.5027182397596448,107.874744495734575,256.256689112315712],"luv":[51.5027182397596448,-25.6280715933506258,-104.786270314512635],"rgb":[0.133333333333333331,0.466666666666666674,0.933333333333333348],"xyz":[0.226871833239577,0.19705606999823963,0.834995641752142],"hpluv":[256.256689112315712,265.784074864026707,51.5027182397596448],"hsluv":[256.256689112315712,94.5951642228933594,51.5027182397596448]},"#2277ff":{"lch":[52.6774941409559432,119.859275592882611,257.873120264558906],"luv":[52.6774941409559432,-25.1797078347732324,-117.18459053564186],"rgb":[0.133333333333333331,0.466666666666666674,1],"xyz":[0.253042881649408358,0.207524489362172326,0.972829830043923871],"hpluv":[257.873120264558906,288.725982332353851,52.6774941409559432],"hsluv":[257.873120264558906,99.9999999999990195,52.6774941409559432]},"#228800":{"lch":[49.4326013626652951,73.5543249838887903,125.335546592141156],"luv":[49.4326013626652951,-42.5411625112882845,60.0040683289365475],"rgb":[0.133333333333333331,0.533333333333333326,0],"xyz":[0.0946344629725488357,0.179476913451380865,0.0296551343692538216],"hpluv":[125.335546592141156,188.81394887832684,49.4326013626652951],"hsluv":[125.335546592141156,100.000000000002359,49.4326013626652951]},"#228811":{"lch":[49.4817413630627669,71.8188220709608,126.143293588176633],"luv":[49.4817413630627669,-42.3592238010278379,57.9968909738682825],"rgb":[0.133333333333333331,0.533333333333333326,0.0666666666666666657],"xyz":[0.0956461284721859539,0.179881579651235718,0.0349832393340094513],"hpluv":[126.143293588176633,184.175827324420425,49.4817413630627669],"hsluv":[126.143293588176633,96.2839239867753776,49.4817413630627669]},"#228822":{"lch":[49.5726392440562904,68.7061860444130161,127.715012949240233],"luv":[49.5726392440562904,-42.0299333634258545,54.3509402148249521],"rgb":[0.133333333333333331,0.533333333333333326,0.133333333333333331],"xyz":[0.097521486610662983,0.180631722906626546,0.0448601255299886509],"hpluv":[127.715012949240233,175.870551812838869,49.5726392440562904],"hsluv":[127.715012949240233,89.549457305464,49.5726392440562904]},"#228833":{"lch":[49.7217546026668913,63.8760413965615115,130.529662443073192],"luv":[49.7217546026668913,-41.5093107949551552,48.5502397710151357],"rgb":[0.133333333333333331,0.533333333333333326,0.2],"xyz":[0.100609237343120717,0.181866823199609645,0.0611222793875997941],"hpluv":[130.529662443073192,163.016240956960957,49.7217546026668913],"hsluv":[130.529662443073192,89.7937238944362122,49.7217546026668913]},"#228844":{"lch":[49.9358562328630171,57.5522088774297558,135.149605574971361],"luv":[49.9358562328630171,-40.8016788905052792,40.5891579906186308],"rgb":[0.133333333333333331,0.533333333333333326,0.266666666666666663],"xyz":[0.10506723258733959,0.183650021297297239,0.0846010543404864257],"hpluv":[135.149605574971361,146.247625060139768,49.9358562328630171],"hsluv":[135.149605574971361,90.1269016918236616,49.9358562328630171]},"#228855":{"lch":[50.2200542052193697,50.3265642713731509,142.503880569306347],"luv":[50.2200542052193697,-39.9288227743001443,30.6341669254964764],"rgb":[0.133333333333333331,0.533333333333333326,0.333333333333333315],"xyz":[0.111029646626701589,0.186034986913042072,0.116003101614460341],"hpluv":[142.503880569306347,127.162609675202816,50.2200542052193697],"hsluv":[142.503880569306347,90.5399352865824341,50.2200542052193697]},"#228866":{"lch":[50.5781035519961648,43.3062651916131074,154.006170397495453],"luv":[50.5781035519961648,-38.9254575775356315,18.9800252166796355],"rgb":[0.133333333333333331,0.533333333333333326,0.4],"xyz":[0.11861464240020976,0.189068985222445363,0.155950746021604303],"hpluv":[154.006170397495453,108.649446020320369,50.5781035519961648],"hsluv":[154.006170397495453,91.0179493017372607,50.5781035519961648]},"#228877":{"lch":[51.0125694858746357,38.3061120533697519,170.992189866461246],"luv":[51.0125694858746357,-37.8336830583721451,5.997553408179356],"rgb":[0.133333333333333331,0.533333333333333326,0.466666666666666674],"xyz":[0.12792865542041168,0.192794590430526186,0.205004547928002212],"hpluv":[170.992189866461246,95.2862426106229634,51.0125694858746357],"hsluv":[170.992189866461246,91.5427076584867621,51.0125694858746357]},"#228888":{"lch":[51.5249413470067594,37.5420496271247259,192.177050630061103],"luv":[51.5249413470067594,-36.6973707929670923,-7.91886779085127834],"rgb":[0.133333333333333331,0.533333333333333326,0.533333333333333326],"xyz":[0.139069072522355508,0.197250757271303784,0.263677411331574407],"hpluv":[192.177050630061103,92.4570004995607775,51.5249413470067594],"hsluv":[192.177050630061103,92.0950966753639761,51.5249413470067594]},"#228899":{"lch":[52.1157302062907064,42.0223592343639183,212.203992327233067],"luv":[52.1157302062907064,-35.5574728144251,-22.3951959730954577],"rgb":[0.133333333333333331,0.533333333333333326,0.6],"xyz":[0.152126036631428208,0.202473542914932941,0.332444088972692287],"hpluv":[212.203992327233067,102.317738016510475,52.1157302062907064],"hsluv":[212.203992327233067,92.6571999954113465,52.1157302062907064]},"#2288aa":{"lch":[52.784565077464336,50.6329849579481888,227.127925237574203],"luv":[52.784565077464336,-34.4488478228089221,-37.1076279143892478],"rgb":[0.133333333333333331,0.533333333333333326,0.66666666666666663],"xyz":[0.167183729596680763,0.208496620101034036,0.411747938589690887],"hpluv":[227.127925237574203,121.72111165959474,52.784565077464336],"hsluv":[227.127925237574203,93.213704377986,52.784565077464336]},"#2288bb":{"lch":[53.5302933631107294,61.6316847476891141,237.186375672219185],"luv":[53.5302933631107294,-33.3987075035381409,-51.7975955226846381],"rgb":[0.133333333333333331,0.533333333333333326,0.733333333333333282],"xyz":[0.18432132170401741,0.215351656943968794,0.502005923688332634],"hpluv":[237.186375672219185,146.097822373379188,53.5302933631107294],"hsluv":[237.186375672219185,93.7525919029994,53.5302933631107294]},"#2288cc":{"lch":[54.351086283976727,73.7818378825302261,243.928624140525301],"luv":[54.351086283976727,-32.4264148607849876,-66.274333045306733],"rgb":[0.133333333333333331,0.533333333333333326,0.8],"xyz":[0.203613697147739137,0.223068607121457596,0.60361243435860279],"hpluv":[243.928624140525301,172.258462735913952,54.351086283976727],"hsluv":[243.928624140525301,94.2652369190112864,54.351086283976727]},"#2288dd":{"lch":[55.2445474530087779,86.375042864399532,248.580085361336785],"luv":[55.2445474530087779,-31.544198041281593,-80.4090268549449831],"rgb":[0.133333333333333331,0.533333333333333326,0.866666666666666696],"xyz":[0.22513202269837268,0.23167593734171113,0.716942282258608787],"hpluv":[248.580085361336785,198.39840761978212,55.2445474530087779],"hsluv":[248.580085361336785,94.7460999996689566,55.2445474530087779]},"#2288ee":{"lch":[56.2078215466105604,99.0227420546019772,251.903461744910402],"luv":[56.2078215466105604,-30.7583451142169402,-94.1245326673496265],"rgb":[0.133333333333333331,0.533333333333333326,0.933333333333333348],"xyz":[0.248944202964547445,0.241200809448181175,0.842353098327132],"hpluv":[251.903461744910402,223.551465466634539,56.2078215466105604],"hsluv":[251.903461744910402,95.1922101623356838,56.2078215466105604]},"#2288ff":{"lch":[57.2376997180489866,111.514610807296222,254.356224713070389],"luv":[57.2376997180489866,-30.0705415498761575,-107.383755542446536],"rgb":[0.133333333333333331,0.533333333333333326,1],"xyz":[0.275115251374378811,0.251669228812113843,0.980187286618913856],"hpluv":[254.356224713070389,247.223031548482197,57.2376997180489866],"hsluv":[254.356224713070389,99.9999999999988773,57.2376997180489866]},"#229900":{"lch":[55.1973816023000694,82.8565734474734086,125.883775052172936],"luv":[55.1973816023000694,-48.5657961090338617,67.1310301704979508],"rgb":[0.133333333333333331,0.6,0],"xyz":[0.120504063425016322,0.23121611435631656,0.0382783345200760766],"hpluv":[125.883775052172936,190.479314261094402,55.1973816023000694],"hsluv":[125.883775052172936,100.000000000002331,55.1973816023000694]},"#229911":{"lch":[55.2388931006948951,81.3509781714907376,126.510168490119042],"luv":[55.2388931006948951,-48.4010205856972817,65.3859530459048273],"rgb":[0.133333333333333331,0.6,0.0666666666666666657],"xyz":[0.121515728924653441,0.231620780556171413,0.0436064394848317063],"hpluv":[126.510168490119042,186.877552842351321,55.2388931006948951],"hsluv":[126.510168490119042,97.109403045153627,55.2388931006948951]},"#229922":{"lch":[55.3157166450500739,78.6308396618125869,127.715012949240275],"luv":[55.3157166450500739,-48.1011847922964293,62.2019691609440102],"rgb":[0.133333333333333331,0.6,0.133333333333333331],"xyz":[0.12339108706313047,0.232370923811562241,0.0534833256808109059],"hpluv":[127.715012949240275,180.378053709807,55.3157166450500739],"hsluv":[127.715012949240275,91.8445791693357592,55.3157166450500739]},"#229933":{"lch":[55.4418461137647,74.3518111171957656,129.829614369777261],"luv":[55.4418461137647,-47.6228343175573201,57.0986643273697],"rgb":[0.133333333333333331,0.6,0.2],"xyz":[0.126478837795588217,0.23360602410454534,0.0697454795384220561],"hpluv":[129.829614369777261,170.173995330187722,55.4418461137647],"hsluv":[129.829614369777261,91.9941043082508827,55.4418461137647]},"#229944":{"lch":[55.6231658975890042,68.6117263626113925,133.195472742568398],"luv":[55.6231658975890042,-46.964006542137362,50.0195070344354846],"rgb":[0.133333333333333331,0.6,0.266666666666666663],"xyz":[0.130936833039807077,0.235389222202232934,0.0932242544913087],"hpluv":[133.195472742568398,156.524371813771666,55.6231658975890042],"hsluv":[133.195472742568398,92.2005608183228844,55.6231658975890042]},"#229955":{"lch":[55.8642490130281715,61.7521412094073696,138.342726405552],"luv":[55.8642490130281715,-46.1371272258517706,41.0450049980768625],"rgb":[0.133333333333333331,0.6,0.333333333333333315],"xyz":[0.136899247079169062,0.237774187817977767,0.124626301765282596],"hpluv":[138.342726405552,140.267605312348593,55.8642490130281715],"hsluv":[138.342726405552,92.4605995247666357,55.8642490130281715]},"#229966":{"lch":[56.1686206396836383,54.4254646973719787,146.085824005346524],"luv":[56.1686206396836383,-45.1662924386951516,30.3667126121210664],"rgb":[0.133333333333333331,0.6,0.4],"xyz":[0.144484242852677247,0.240808186127381058,0.164573946172426544],"hpluv":[146.085824005346524,122.955430161041207,56.1686206396836383],"hsluv":[146.085824005346524,92.7673635780271,56.1686206396836383]},"#229977":{"lch":[56.5388973522399,47.7139826201784629,157.505617321427167],"luv":[56.5388973522399,-44.0837619060267798,18.2550287233801534],"rgb":[0.133333333333333331,0.6,0.466666666666666674],"xyz":[0.153798255872879153,0.244533791335461881,0.213627748078824453],"hpluv":[157.505617321427167,107.087223886255089,56.5388973522399],"hsluv":[157.505617321427167,93.1115325865156,56.5388973522399]},"#229988":{"lch":[56.9768757530356,43.2189787336254057,173.325138204180888],"luv":[56.9768757530356,-42.9260293704251126,5.02355703331473169],"rgb":[0.133333333333333331,0.6,0.533333333333333326],"xyz":[0.164938672974823,0.248989958176239479,0.272300611482396648],"hpluv":[173.325138204180888,96.2532040641867,56.9768757530356],"hsluv":[173.325138204180888,93.4824878896153706,56.9768757530356]},"#229999":{"lch":[57.4836007022547477,42.6905833214490045,192.177050630061103],"luv":[57.4836007022547477,-41.7300648492924537,-9.00486490733903366],"rgb":[0.133333333333333331,0.6,0.6],"xyz":[0.177995637083895708,0.254212743819868636,0.341067289123514528],"hpluv":[192.177050630061103,94.2383018299879467,57.4836007022547477],"hsluv":[192.177050630061103,93.8694254698009587,57.4836007022547477]},"#2299aa":{"lch":[58.0594270662980563,46.8633307325653,210.133219640519371],"luv":[58.0594270662980563,-40.5302437993065823,-23.5259666096543114],"rgb":[0.133333333333333331,0.6,0.66666666666666663],"xyz":[0.193053330049148264,0.260235821005969759,0.420371138740513128],"hpluv":[210.133219640519371,102.423528384682896,58.0594270662980563],"hsluv":[210.133219640519371,94.2622655036202701,58.0594270662980563]},"#2299bb":{"lch":[58.704081470592044,54.8976329577059445,224.200669016044458],"luv":[58.704081470592044,-39.3562485070025474,-38.2731734745639],"rgb":[0.133333333333333331,0.6,0.733333333333333282],"xyz":[0.210190922156484883,0.267090857848904517,0.51062912383915493],"hpluv":[224.200669016044458,118.665547847191604,58.704081470592044],"hsluv":[224.200669016044458,94.6522748426748279,58.704081470592044]},"#2299cc":{"lch":[59.4167266489170771,65.3729917945351247,234.209137470411804],"luv":[59.4167266489170771,-38.231976961148348,-53.0277662532618663],"rgb":[0.133333333333333331,0.6,0.8],"xyz":[0.229483297600206637,0.274807808026393319,0.612235634509425086],"hpluv":[234.209137470411804,139.613998456385502,59.4167266489170771],"hsluv":[234.209137470411804,95.032392249276171,59.4167266489170771]},"#2299dd":{"lch":[60.1960287785942114,77.1664383037622201,241.199920521286145],"luv":[60.1960287785942114,-37.1753089722913614,-67.6214137925481],"rgb":[0.133333333333333331,0.6,0.866666666666666696],"xyz":[0.251001623150840181,0.283415138246646825,0.725565482409431084],"hpluv":[241.199920521286145,162.667181112599422,60.1960287785942114],"hsluv":[241.199920521286145,95.397300800485425,60.1960287785942114]},"#2299ee":{"lch":[61.0402269370523243,89.5733454479413211,246.163931095701571],"luv":[61.0402269370523243,-36.1984881015500051,-81.9332269222821],"rgb":[0.133333333333333331,0.6,0.933333333333333348],"xyz":[0.27481380341701489,0.292940010353116842,0.850976298477954307],"hpluv":[246.163931095701571,186.209563381880429,61.0402269370523243],"hsluv":[246.163931095701571,95.74331870201,61.0402269370523243]},"#2299ff":{"lch":[61.9472031658153384,102.178145565387652,249.783903318571561],"luv":[61.9472031658153384,-35.3088685699608078,-95.8835607989752532],"rgb":[0.133333333333333331,0.6,1],"xyz":[0.300984851826846311,0.303408429717049566,0.988810486769736152],"hpluv":[249.783903318571561,209.303089797111312,61.9472031658153384],"hsluv":[249.783903318571561,99.9999999999986,61.9472031658153384]},"#110000":{"lch":[1.07666134976862637,3.62084603829176643,12.1770506300617818],"luv":[1.07666134976862637,3.53937866928378497,0.763756943295526236],"rgb":[0.0666666666666666657,0,0],"xyz":[0.00231161193210362246,0.00119192490249095569,0.000108356809317355026],"hpluv":[12.1770506300617818,426.746789183125145,1.07666134976862637],"hsluv":[12.1770506300617818,100.000000000002203,1.07666134976862637]},"#110011":{"lch":[1.44219482929484544,3.28508596549136378,307.715012949243601],"luv":[1.44219482929484544,2.00959989444743092,-2.59871084672866193],"rgb":[0.0666666666666666657,0,0.0666666666666666657],"xyz":[0.0033232774317407442,0.00159659110234581,0.00543646177407298634],"hpluv":[307.715012949243601,289.042783730483393,1.44219482929484544],"hsluv":[307.715012949243601,99.9999999999988347,1.44219482929484544]},"#110022":{"lch":[2.1197964535087821,6.27745605271938789,280.884754167684719],"luv":[2.1197964535087821,1.18539805862553327,-6.16451830530416167],"rgb":[0.0666666666666666657,0,0.133333333333333331],"xyz":[0.00519863557021776369,0.00234673435773662814,0.0153133479700521824],"hpluv":[280.884754167684719,375.775833064690062,2.1197964535087821],"hsluv":[280.884754167684719,99.9999999999998721,2.1197964535087821]},"#110033":{"lch":[3.23545797359596321,11.0622687483975319,272.972319481398301],"luv":[3.23545797359596321,0.57361730895702967,-11.0473867065762477],"rgb":[0.0666666666666666657,0,0.2],"xyz":[0.00828638630267550247,0.00358183465071974143,0.0315755018276633256],"hpluv":[272.972319481398301,433.858158519435221,3.23545797359596321],"hsluv":[272.972319481398301,100.000000000000355,3.23545797359596321]},"#110044":{"lch":[4.84621421062803659,17.7312810137515946,269.891014646828467],"luv":[4.84621421062803659,-0.0337275934556249754,-17.7312489362161827],"rgb":[0.0666666666666666657,0,0.266666666666666663],"xyz":[0.012744381546894383,0.0053650327484073175,0.0550542767805499642],"hpluv":[269.891014646828467,464.276639746945534,4.84621421062803659],"hsluv":[269.891014646828467,100.000000000000711,4.84621421062803659]},"#110055":{"lch":[7.00054481789469563,26.532890242342738,268.413820694361107],"luv":[7.00054481789469563,-0.734444075336115332,-26.5227233992365541],"rgb":[0.0666666666666666657,0,0.333333333333333315],"xyz":[0.0187067955862563751,0.00774999836415214954,0.0864563240545238726],"hpluv":[268.413820694361107,480.941270902403687,7.00054481789469563],"hsluv":[268.413820694361107,100.000000000000682,7.00054481789469563]},"#110066":{"lch":[9.62818818466394,37.2351477319955,267.604082628906383],"luv":[9.62818818466394,-1.55659527409507947,-37.20259719127408],"rgb":[0.0666666666666666657,0,0.4],"xyz":[0.0262917913597645499,0.010783996673555462,0.126403968461667848],"hpluv":[267.604082628906383,490.735908571457742,9.62818818466394],"hsluv":[267.604082628906383,100.000000000000753,9.62818818466394]},"#110077":{"lch":[12.2928363787590555,48.1341065988899643,267.117295446388],"luv":[12.2928363787590555,-2.42073458662620622,-48.0731969202633138],"rgb":[0.0666666666666666657,0,0.466666666666666674],"xyz":[0.0356058043799664659,0.0145096018816362783,0.175457770368065757],"hpluv":[267.117295446388,496.866985521105335,12.2928363787590555],"hsluv":[267.117295446388,100.000000000000739,12.2928363787590555]},"#110088":{"lch":[14.9348588897968106,58.9551979191609803,266.804247897724281],"luv":[14.9348588897968106,-3.28660375460643372,-58.8635166928348781],"rgb":[0.0666666666666666657,0,0.533333333333333326],"xyz":[0.0467462214819102939,0.0189657687224138727,0.234130633771637925],"hpluv":[266.804247897724281,500.910695182750828,14.9348588897968106],"hsluv":[266.804247897724281,100.000000000000753,14.9348588897968106]},"#110099":{"lch":[17.5475874535139624,69.6538923837914297,266.59230255326986],"luv":[17.5475874535139624,-4.14026096141065292,-69.5307339482636],"rgb":[0.0666666666666666657,0,0.6],"xyz":[0.0598031855909830073,0.0241885543660430302,0.302897311412755832],"hpluv":[266.59230255326986,503.694607743992833,17.5475874535139624],"hsluv":[266.59230255326986,100.000000000000796,17.5475874535139624]},"#1100aa":{"lch":[20.1284543895036734,80.2134478690449,266.442863009455],"luv":[20.1284543895036734,-4.97675334080985809,-80.0589104673847203],"rgb":[0.0666666666666666657,0,0.66666666666666663],"xyz":[0.0748608785562355494,0.0302116315521441317,0.382201161029754433],"hpluv":[266.442863009455,505.680355905096519,20.1284543895036734],"hsluv":[266.442863009455,100.000000000000782,20.1284543895036734]},"#1100bb":{"lch":[22.6769756305364183,90.6302333913987894,266.3339747285724],"luv":[22.6769756305364183,-5.79494806122388795,-90.444777525002138],"rgb":[0.0666666666666666657,0,0.733333333333333282],"xyz":[0.0919984706635722,0.0370666683950788903,0.472459146128396179],"hpluv":[266.3339747285724,507.139328846885462,22.6769756305364183],"hsluv":[266.3339747285724,100.000000000001,22.6769756305364183]},"#1100cc":{"lch":[25.1937235339869332,100.906819147977927,266.252448568601267],"luv":[25.1937235339869332,-6.59531864805210422,-100.691051849175651],"rgb":[0.0666666666666666657,0,0.8],"xyz":[0.111290846107293936,0.0447836185725676919,0.574065656798666279],"hpluv":[266.252448568601267,508.238409831726415,25.1937235339869332],"hsluv":[266.252448568601267,100.000000000000824,25.1937235339869332]},"#1100dd":{"lch":[27.6797893663012289,111.048607057141055,266.189998210144608],"luv":[27.6797893663012289,-7.37896669992084409,-110.803176758488192],"rgb":[0.0666666666666666657,0,0.866666666666666696],"xyz":[0.132809171657927494,0.0533909487928212259,0.687395504698672277],"hpluv":[266.189998210144608,509.084249760461944,27.6797893663012289],"hsluv":[266.189998210144608,100.000000000000938,27.6797893663012289]},"#1100ee":{"lch":[30.1364964584496846,121.062148077250455,266.141219022825339],"luv":[30.1364964584496846,-8.14718371295858823,-120.787694301304626],"rgb":[0.0666666666666666657,0,0.933333333333333348],"xyz":[0.156621351924102231,0.0629158208992912638,0.8128063207671955],"hpluv":[266.141219022825339,509.74730741907581,30.1364964584496846],"hsluv":[266.141219022825339,100.000000000000952,30.1364964584496846]},"#1100ff":{"lch":[32.5652456752648263,130.954293728553409,266.102472093749839],"luv":[32.5652456752648263,-8.90125725083502495,-130.651424275813781],"rgb":[0.0666666666666666657,0,1],"xyz":[0.182792400333933625,0.0733842402632239599,0.950640509058977345],"hpluv":[266.102472093749839,510.275492181060656,32.5652456752648263],"hsluv":[266.102472093749839,100.000000000001108,32.5652456752648263]},"#111100":{"lch":[4.69779601336656771,5.17885327658484673,85.8743202181747307],"luv":[4.69779601336656771,0.372589941443898953,5.16543299210515716],"rgb":[0.0666666666666666657,0.0666666666666666657,0],"xyz":[0.00431601219303203148,0.00520072542434782924,0.000776490229626805866],"hpluv":[85.8743202181747307,139.887458074797621,4.69779601336656771],"hsluv":[85.8743202181747307,100.000000000002359,4.69779601336656771]},"#111111":{"lch":[5.06332949289278655,2.68159353999537178e-13,0],"luv":[5.06332949289278655,2.52120910544652531e-13,9.13481559944393266e-14],"rgb":[0.0666666666666666657,0.0666666666666666657,0.0666666666666666657],"xyz":[0.00532767769266915322,0.00560539162420268383,0.00610459519438243722],"hpluv":[0,6.72041492281092e-12,5.06332949289278655],"hsluv":[0,1.92419399944792277e-12,5.06332949289278655]},"#111122":{"lch":[5.74093111710672321,6.60006851394265048,265.874320218179719],"luv":[5.74093111710672321,-0.474838542395297381,-6.58296534605743222],"rgb":[0.0666666666666666657,0.0666666666666666657,0.133333333333333331],"xyz":[0.00720303583114617271,0.00635553487959350169,0.0159814813903616341],"hpluv":[265.874320218179719,145.883251481840432,5.74093111710672321],"hsluv":[265.874320218179719,28.41442223352254,5.74093111710672321]},"#111133":{"lch":[6.85659263719390388,14.212336546779186,265.874320218178582],"luv":[6.85659263719390388,-1.02249925976518052,-14.1755072354640976],"rgb":[0.0666666666666666657,0.0666666666666666657,0.2],"xyz":[0.0102907865636039132,0.00759063517257661455,0.0322436352479727809],"hpluv":[265.874320218178582,263.024656142887807,6.85659263719390388],"hsluv":[265.874320218178582,51.2306489028398957,6.85659263719390388]},"#111144":{"lch":[8.45853257854777141,22.7927945223118087,265.874320218178241],"luv":[8.45853257854777141,-1.63981590573345759,-22.7337301367732181],"rgb":[0.0666666666666666657,0.0666666666666666657,0.266666666666666663],"xyz":[0.0147487818078227903,0.00937383327026419105,0.0557224102008594194],"hpluv":[265.874320218178241,341.933676209697239,8.45853257854777141],"hsluv":[265.874320218178241,66.600159737267461,8.45853257854777141]},"#111155":{"lch":[10.3782295585045325,32.1242805487719707,265.874320218178127],"luv":[10.3782295585045325,-2.31116487943396587,-32.0410349033279545],"rgb":[0.0666666666666666657,0.0666666666666666657,0.333333333333333315],"xyz":[0.0207111958471847858,0.011758798886009024,0.0871244574748333278],"hpluv":[265.874320218178127,392.780088665713265,10.3782295585045325],"hsluv":[265.874320218178127,76.5037738801481453,10.3782295585045325]},"#111166":{"lch":[12.4757228248048477,41.8651930040424887,265.87432021817807],"luv":[12.4757228248048477,-3.01196982745712916,-41.7567051265328644],"rgb":[0.0666666666666666657,0.0666666666666666657,0.4],"xyz":[0.0282961916206929606,0.0147927971954123355,0.12707210188197729],"hpluv":[265.87432021817807,425.820638501567,12.4757228248048477],"hsluv":[265.87432021817807,82.9392496755345263,12.4757228248048477]},"#111177":{"lch":[14.6896895275036599,51.8467212520223697,265.874320218178],"luv":[14.6896895275036599,-3.73008575521422614,-51.7123676197837199],"rgb":[0.0666666666666666657,0.0666666666666666657,0.466666666666666674],"xyz":[0.0376102046408948731,0.0185184024034931519,0.176125903788375199],"hpluv":[265.874320218178,447.865910041391658,14.6896895275036599],"hsluv":[265.874320218178,87.2331192419333235,14.6896895275036599]},"#111188":{"lch":[16.9766940539391484,61.9476661879793511,265.874320218178],"luv":[16.9766940539391484,-4.45679305530888747,-61.7871373491236469],"rgb":[0.0666666666666666657,0.0666666666666666657,0.533333333333333326],"xyz":[0.0487506217428387,0.0229745692442707428,0.234798767191947366],"hpluv":[265.874320218178,463.03215765547759,16.9766940539391484],"hsluv":[265.874320218178,90.1871263608273495,16.9766940539391484]},"#111199":{"lch":[19.3069968916820471,72.0861980616198537,265.874320218178],"luv":[19.3069968916820471,-5.18620452834737478,-71.8993966147786],"rgb":[0.0666666666666666657,0.0666666666666666657,0.6],"xyz":[0.0618075858519114146,0.0281973548878999072,0.303565444833065246],"hpluv":[265.874320218178,473.779996738615694,19.3069968916820471],"hsluv":[265.874320218178,92.280537596895428,19.3069968916820471]},"#1111aa":{"lch":[21.6605350192491244,82.2093341223612839,265.874320218177957],"luv":[21.6605350192491244,-5.91450835752722703,-81.9962999636616274],"rgb":[0.0666666666666666657,0.0666666666666666657,0.66666666666666663],"xyz":[0.0768652788171639567,0.0342204320740010087,0.382869294450063846],"hpluv":[265.874320218177957,481.605322004481,21.6605350192491244],"hsluv":[265.874320218177957,93.8047159652847569,21.6605350192491244]},"#1111bb":{"lch":[24.0238472654082429,92.2838634174554215,265.874320218177957],"luv":[24.0238472654082429,-6.63931519789526092,-92.0447225046312241],"rgb":[0.0666666666666666657,0.0666666666666666657,0.733333333333333282],"xyz":[0.0940028709245006,0.0410754689169357673,0.473127279548705593],"hpluv":[265.874320218177957,487.441538809997496,24.0238472654082429],"hsluv":[265.874320218177957,94.9414655706975736,24.0238472654082429]},"#1111cc":{"lch":[26.3879200105999,102.289669569688542,265.874320218177957],"luv":[26.3879200105999,-7.35917778701558589,-102.024599989292597],"rgb":[0.0666666666666666657,0.0666666666666666657,0.8],"xyz":[0.113295246368222344,0.0487924190944245689,0.574733790218975749],"hpluv":[265.874320218177957,491.887677819884516,26.3879200105999],"hsluv":[265.874320218177957,95.8074626598259727,26.3879200105999]},"#1111dd":{"lch":[28.7467318202544035,112.215160110792439,265.874320218177957],"luv":[28.7467318202544035,-8.07326211070735766,-111.924369989661315],"rgb":[0.0666666666666666657,0.0666666666666666657,0.866666666666666696],"xyz":[0.134813571918855901,0.0573997493146781,0.688063638118981746],"hpluv":[265.874320218177957,495.338839734480189,28.7467318202544035],"hsluv":[265.874320218177957,96.479663003878315,28.7467318202544035]},"#1111ee":{"lch":[31.096282761883856,122.054240127147821,265.874320218177957],"luv":[31.096282761883856,-8.78112967353786367,-121.737953386246701],"rgb":[0.0666666666666666657,0.0666666666666666657,0.933333333333333348],"xyz":[0.158625752185030638,0.0669246214211481338,0.813474454187505],"hpluv":[265.874320218177957,498.062358817216193,31.096282761883856],"hsluv":[265.874320218177957,97.0101366558694451,31.096282761883856]},"#1111ff":{"lch":[33.4339475813396589,131.804336466263976,265.874320218177957],"luv":[33.4339475813396589,-9.48259535137154863,-131.462783694528071],"rgb":[0.0666666666666666657,0.0666666666666666657,1],"xyz":[0.184796800594862032,0.07739304078508083,0.951308642479286815],"hpluv":[265.874320218177957,500.243401112503761,33.4339475813396589],"hsluv":[265.874320218177957,99.9999999999995168,33.4339475813396589]},"#66aa00":{"lch":[62.9888010115071921,81.5107592316300185,114.758667910078074],"luv":[62.9888010115071921,-34.136471206054587,74.0182761493062884],"rgb":[0.4,0.66666666666666663,0],"xyz":[0.198534632170994735,0.315734905503604946,0.0504821063864305253],"hpluv":[114.758667910078074,164.206718875588678,62.9888010115071921],"hsluv":[114.758667910078074,100.000000000002245,62.9888010115071921]},"#66aa11":{"lch":[63.0225323172591345,80.1801511939703744,115.156040801232848],"luv":[63.0225323172591345,-34.0833758310267285,72.5753411114886262],"rgb":[0.4,0.66666666666666663,0.0666666666666666657],"xyz":[0.199546297670631867,0.316139571703459799,0.055810211351186155],"hpluv":[115.156040801232848,161.439702186697787,63.0225323172591345],"hsluv":[115.156040801232848,97.8915472494395,63.0225323172591345]},"#66aa22":{"lch":[63.0849851082382287,77.7526522520100372,115.919582231606014],"luv":[63.0849851082382287,-33.9864002990590066,69.9313915701248],"rgb":[0.4,0.66666666666666663,0.133333333333333331],"xyz":[0.201421655809108868,0.316889714958850599,0.0656870975471653545],"hpluv":[115.919582231606014,156.397041701241,63.0849851082382287],"hsluv":[115.919582231606014,94.0329763727763748,63.0849851082382287]},"#66aa33":{"lch":[63.1875983682703577,73.8659889058236416,117.258215410479664],"luv":[63.1875983682703577,-33.8307250746429062,65.6632801340230827],"rgb":[0.4,0.66666666666666663,0.2],"xyz":[0.20450940654156663,0.318124815251833726,0.0819492514047764908],"hpluv":[117.258215410479664,148.337854737344315,63.1875983682703577],"hsluv":[117.258215410479664,87.8175568215645228,63.1875983682703577]},"#66aa44":{"lch":[63.3352806074861121,68.495891054581449,119.389904478135335],"luv":[63.3352806074861121,-33.6143748396710436,59.6804900742209057],"rgb":[0.4,0.66666666666666663,0.266666666666666663],"xyz":[0.208967401785785489,0.319908013349521292,0.105428026357663129],"hpluv":[119.389904478135335,137.232870385557277,63.3352806074861121],"hsluv":[119.389904478135335,79.1339200396795093,63.3352806074861121]},"#66aa55":{"lch":[63.5319451116367162,61.7628687774086131,122.670093374403834],"luv":[63.5319451116367162,-33.3396585938880747,51.9915293529473],"rgb":[0.4,0.66666666666666663,0.333333333333333315],"xyz":[0.214929815825147474,0.322292978965266153,0.136830073631637045],"hpluv":[122.670093374403834,123.360077774302084,63.5319451116367162],"hsluv":[122.670093374403834,68.0252461175988401,63.5319451116367162]},"#66aa66":{"lch":[63.7807317293932101,53.9656100581627314,127.715012949238869],"luv":[63.7807317293932101,-33.0126168434810836,42.6902119706049703],"rgb":[0.4,0.66666666666666663,0.4],"xyz":[0.22251481159865566,0.325326977274669471,0.176777718038781],"hpluv":[127.715012949238869,107.366036241042551,63.7807317293932101],"hsluv":[127.715012949238869,54.6684489206366493,63.7807317293932101]},"#66aa77":{"lch":[64.0841229578331308,45.668717811445795,135.623736827110406],"luv":[64.0841229578331308,-32.6422859505805931,31.9392071670853355],"rgb":[0.4,0.66666666666666663,0.466666666666666674],"xyz":[0.231828824618857565,0.329052582482750267,0.225831519945178916],"hpluv":[135.623736827110406,90.428994130424627,64.0841229578331308],"hsluv":[135.623736827110406,56.3153951517164302,64.0841229578331308]},"#66aa88":{"lch":[64.4440140424290888,37.9133385548872752,148.25026899586868],"luv":[64.4440140424290888,-32.239785461804118,19.9503752785341248],"rgb":[0.4,0.66666666666666663,0.533333333333333326],"xyz":[0.242969241720801421,0.333508749323527864,0.284504383348751055],"hpluv":[148.25026899586868,74.65325904191441,64.4440140424290888],"hsluv":[148.25026899586868,58.1346686170252127,64.4440140424290888]},"#66aa99":{"lch":[64.861761772217136,32.5704605989434484,167.654678216446086],"luv":[64.861761772217136,-31.8173259789585323,6.96366793981576304],"rgb":[0.4,0.66666666666666663,0.6],"xyz":[0.256026205829874121,0.338731534967157,0.353271060989869],"hpluv":[167.654678216446086,63.7198120272805681,64.861761772217136],"hsluv":[167.654678216446086,60.083023100845935,64.861761772217136]},"#66aaaa":{"lch":[65.3382237636027,32.1097126044189949,192.177050630060876],"luv":[65.3382237636027,-31.387258852500235,-6.77300710648746396],"rgb":[0.4,0.66666666666666663,0.66666666666666663],"xyz":[0.271083898795126677,0.344754612153258144,0.432574910606867591],"hpluv":[192.177050630060876,62.3603323483304592,65.3382237636027],"hsluv":[192.177050630060876,62.1162357127798757,65.3382237636027]},"#66aabb":{"lch":[65.8737942906507641,37.4229485671739255,214.174175962111633],"luv":[65.8737942906507641,-30.9612713447490577,-21.020864781881972],"rgb":[0.4,0.66666666666666663,0.733333333333333282],"xyz":[0.288221490902463295,0.351609648996192903,0.522832895705509282],"hpluv":[214.174175962111633,72.0882777495769744,65.8737942906507641],"hsluv":[214.174175962111633,64.192083786910942,65.8737942906507641]},"#66aacc":{"lch":[66.4684397846860833,46.8829891397435361,229.336310284400895],"luv":[66.4684397846860833,-30.5497910563422188,-35.5629714322516],"rgb":[0.4,0.66666666666666663,0.8],"xyz":[0.30751386634618505,0.359326599173681704,0.624439406375779438],"hpluv":[229.336310284400895,89.5033179536005,66.4684397846860833],"hsluv":[229.336310284400895,66.2725553364081748,66.4684397846860833]},"#66aadd":{"lch":[67.1217354618507471,58.5746749070863473,239.007496148652194],"luv":[67.1217354618507471,-30.1616186688116876,-50.2122425285710676],"rgb":[0.4,0.66666666666666663,0.866666666666666696],"xyz":[0.329032191896818593,0.367933929393935211,0.737769254275785435],"hpluv":[239.007496148652194,110.735287258409116,67.1217354618507471],"hsluv":[239.007496148652194,68.3252248927570349,67.1217354618507471]},"#66aaee":{"lch":[67.8329035309127,71.3390505041132,245.305718817638592],"luv":[67.8329035309127,-29.803771094245274,-64.8150858627082584],"rgb":[0.4,0.66666666666666663,0.933333333333333348],"xyz":[0.352844372162993358,0.377458801500405228,0.863180070344308659],"hpluv":[245.305718817638592,133.452355648257935,67.8329035309127],"hsluv":[245.305718817638592,80.362890995181445,67.8329035309127]},"#66aaff":{"lch":[68.6008528128324144,84.5574659264264312,249.594848961048797],"luv":[68.6008528128324144,-29.4814940521041038,-79.2515397475312],"rgb":[0.4,0.66666666666666663,1],"xyz":[0.379015420572824724,0.387927220864337952,1.00101425863609061],"hpluv":[249.594848961048797,156.409011428865199,68.6008528128324144],"hsluv":[249.594848961048797,99.9999999999981,68.6008528128324144]},"#112200":{"lch":[11.0156269675282488,14.1286449823385087,113.920199516574741],"luv":[11.0156269675282488,-5.72865521459208082,12.9151507335100835],"rgb":[0.0666666666666666657,0.133333333333333331,0],"xyz":[0.00803163592779996757,0.0126319728938838038,0.00201503147454941628],"hpluv":[113.920199516574741,162.753605553330914,11.0156269675282488],"hsluv":[113.920199516574741,100.000000000002302,11.0156269675282488]},"#112211":{"lch":[11.3010826742418828,9.17677244733547,127.715012949238741],"luv":[11.3010826742418828,-5.61374683501564142,7.25940762201209555],"rgb":[0.0666666666666666657,0.133333333333333331,0.0666666666666666657],"xyz":[0.00904330142743709,0.0130366390937386584,0.00734313643930504731],"hpluv":[127.715012949238741,103.040803658029205,11.3010826742418828],"hsluv":[127.715012949238741,52.4661346244892783,11.3010826742418828]},"#112222":{"lch":[11.8149934741043623,5.60956124878379736,192.177050630060876],"luv":[11.8149934741043623,-5.48334870304322308,-1.18324317225625331],"rgb":[0.0666666666666666657,0.133333333333333331,0.133333333333333331],"xyz":[0.0109186595659141079,0.0137867823491294762,0.0172200226352842434],"hpluv":[192.177050630060876,60.2469040904941551,11.8149934741043623],"hsluv":[192.177050630060876,60.0110800331641911,11.8149934741043623]},"#112233":{"lch":[12.6219648570067733,12.7575995118883281,244.93155638428982],"luv":[12.6219648570067733,-5.40540262923445,-11.5558629154900672],"rgb":[0.0666666666666666657,0.133333333333333331,0.2],"xyz":[0.0140064102983718484,0.0150218826421125891,0.0334821764928953866],"hpluv":[244.93155638428982,128.257072990564865,12.6219648570067733],"hsluv":[244.93155638428982,68.2965554989448265,12.6219648570067733]},"#112244":{"lch":[13.7124312845167182,23.0561698733830092,256.354402060867073],"luv":[13.7124312845167182,-5.43930918870511082,-22.4053762472305387],"rgb":[0.0666666666666666657,0.133333333333333331,0.266666666666666663],"xyz":[0.0184644055425907255,0.0168050807398001656,0.0569609514457820251],"hpluv":[256.354402060867073,213.359519949101497,13.7124312845167182],"hsluv":[256.354402060867073,75.5965994738604508,13.7124312845167182]},"#112255":{"lch":[15.056320299603339,33.5848303856462849,260.40485184836416],"luv":[15.056320299603339,-5.59809589119781581,-33.114983835502386],"rgb":[0.0666666666666666657,0.133333333333333331,0.333333333333333315],"xyz":[0.024426819581952721,0.019190046355545,0.0883629987197559336],"hpluv":[260.40485184836416,283.050313811336878,15.056320299603339],"hsluv":[260.40485184836416,81.3424686793067,15.056320299603339]},"#112266":{"lch":[16.6136212231118279,43.9645077489691118,262.329755848243337],"luv":[16.6136212231118279,-5.86800935048734384,-43.5711419160865958],"rgb":[0.0666666666666666657,0.133333333333333331,0.4],"xyz":[0.0320118153554608958,0.02222404466494831,0.128310643126899909],"hpluv":[262.329755848243337,335.797328537363626,16.6136212231118279],"hsluv":[262.329755848243337,85.6428490187558396,16.6136212231118279]},"#112277":{"lch":[18.3427569840269769,54.1821774694947678,263.400149453671133],"luv":[18.3427569840269769,-6.22740469049246936,-53.8231157232341815],"rgb":[0.0666666666666666657,0.133333333333333331,0.466666666666666674],"xyz":[0.0413258283756628153,0.0259496498730291264,0.177364445033297818],"hpluv":[263.400149453671133,374.827260372181627,18.3427569840269769],"hsluv":[263.400149453671133,88.8099744527525559,18.3427569840269769]},"#112288":{"lch":[20.2056943122802366,64.2803592359499,264.056887374403459],"luv":[20.2056943122802366,-6.65565132438349316,-63.9348644242795103],"rgb":[0.0666666666666666657,0.133333333333333331,0.533333333333333326],"xyz":[0.0524662454776066434,0.0304058167138067173,0.236037308436869986],"hpluv":[264.056887374403459,403.686144257890874,20.2056943122802366],"hsluv":[264.056887374403459,91.1461001738222762,20.2056943122802366]},"#112299":{"lch":[22.17018380613613,74.2918952905243799,264.488199331991609],"luv":[22.17018380613613,-7.13579321215933149,-73.9484020185124677],"rgb":[0.0666666666666666657,0.133333333333333331,0.6],"xyz":[0.0655232095866793568,0.0356286023574358818,0.304803986077987865],"hpluv":[264.488199331991609,425.217833826531262,22.17018380613613],"hsluv":[264.488199331991609,92.8866294242426136,22.17018380613613]},"#1122aa":{"lch":[24.2101316823922517,84.2333021684004848,264.786067280823943],"luv":[24.2101316823922517,-7.6546801533155886,-83.8847725510625537],"rgb":[0.0666666666666666657,0.133333333333333331,0.66666666666666663],"xyz":[0.0805809025519319,0.0416516795435369833,0.384107835694986466],"hpluv":[264.786067280823943,441.495215422381477,24.2101316823922517],"hsluv":[264.786067280823943,94.2012423737010209,24.2101316823922517]},"#1122bb":{"lch":[26.3050242232650149,94.1101405136049891,264.999933480500431],"luv":[26.3050242232650149,-8.20234804116949334,-93.7520134935884926],"rgb":[0.0666666666666666657,0.133333333333333331,0.733333333333333282],"xyz":[0.0977184946592685455,0.0485067163864717418,0.474365820793628212],"hpluv":[264.999933480500431,453.98033637772636,26.3050242232650149],"hsluv":[264.999933480500431,95.2089691602506605,26.3050242232650149]},"#1122cc":{"lch":[28.4390102065576187,103.92243186966887,265.158337172634162],"luv":[28.4390102065576187,-8.77130520241401612,-103.551610565708117],"rgb":[0.0666666666666666657,0.133333333333333331,0.8],"xyz":[0.117010870102990286,0.0562236665639605435,0.575972331463898368],"hpluv":[265.158337172634162,463.69685512523705,28.4390102065576187],"hsluv":[265.158337172634162,95.9928942328389496,28.4390102065576187]},"#1122dd":{"lch":[30.599961250020371,113.668086087716972,265.278693166229971],"luv":[30.599961250020371,-9.35592092097037664,-113.282392888591403],"rgb":[0.0666666666666666657,0.133333333333333331,0.866666666666666696],"xyz":[0.138529195653623816,0.0648309967842140705,0.689302179363904366],"hpluv":[265.278693166229971,471.364637015548908,30.599961250020371],"hsluv":[265.278693166229971,96.6113336559982,30.599961250020371]},"#1122ee":{"lch":[32.7786459144851463,123.344693870669801,265.37211393361406],"luv":[32.7786459144851463,-9.95194954038693247,-122.942556531067964],"rgb":[0.0666666666666666657,0.133333333333333331,0.933333333333333348],"xyz":[0.162341375919798553,0.0743558688906841,0.814712995432427589],"hpluv":[265.37211393361406,477.494956838131543,32.7786459144851463],"hsluv":[265.37211393361406,97.1056530386567118,32.7786459144851463]},"#1122ff":{"lch":[34.9680553815075,132.950321242967135,265.445956583698],"luv":[34.9680553815075,-10.5561742154436597,-132.530581770930752],"rgb":[0.0666666666666666657,0.133333333333333331,1],"xyz":[0.188512424329629946,0.0848242882546168114,0.952547183724209434],"hpluv":[265.445956583698,482.455471693424897,34.9680553815075],"hsluv":[265.445956583698,99.9999999999995595,34.9680553815075]},"#66bb00":{"lch":[68.2883247343563,91.0397787832552297,117.384795663234385],"luv":[68.2883247343563,-41.875036539852637,80.8376313092488914],"rgb":[0.4,0.733333333333333282,0],"xyz":[0.232489130079593515,0.383643901320803504,0.0618002723559631373],"hpluv":[117.384795663234385,169.170277477244,68.2883247343563],"hsluv":[117.384795663234385,100.000000000002402,68.2883247343563]},"#66bb11":{"lch":[68.3179499939719079,89.8644626985519466,117.727722441428654],"luv":[68.3179499939719079,-41.8112733484955896,79.5452014710932644],"rgb":[0.4,0.733333333333333282,0.0666666666666666657],"xyz":[0.233500795579230647,0.384048567520658357,0.0671283773207187739],"hpluv":[117.727722441428654,166.91389144855998,68.3179499939719079],"hsluv":[117.727722441428654,98.2613130840239108,68.3179499939719079]},"#66bb22":{"lch":[68.3728123300379309,87.7153655991844374,118.381366327960222],"luv":[68.3728123300379309,-41.6944557120635579,77.1722600749346839],"rgb":[0.4,0.733333333333333282,0.133333333333333331],"xyz":[0.235376153717707648,0.384798710776049158,0.0770052635166979665],"hpluv":[118.381366327960222,162.791438416492724,68.3728123300379309],"hsluv":[118.381366327960222,95.072259168186676,68.3728123300379309]},"#66bb33":{"lch":[68.4629872592027766,84.2604886941914515,119.511012469656151],"luv":[68.4629872592027766,-41.5059446288263274,73.3286200296498691],"rgb":[0.4,0.733333333333333282,0.2],"xyz":[0.238463904450165409,0.386033811069032284,0.0932674173743091],"hpluv":[119.511012469656151,156.173540237969377,68.4629872592027766],"hsluv":[119.511012469656151,89.9157079277594846,68.4629872592027766]},"#66bb44":{"lch":[68.5928402387875451,79.4555052917154683,121.268984442668796],"luv":[68.5928402387875451,-41.2418962487648457,67.9137932600435761],"rgb":[0.4,0.733333333333333282,0.266666666666666663],"xyz":[0.242921899694384269,0.38781700916671985,0.116746192327195741],"hpluv":[121.268984442668796,146.988898097842537,68.5928402387875451],"hsluv":[121.268984442668796,82.6706505658268,68.5928402387875451]},"#66bb55":{"lch":[68.7658933773114711,73.3682686647690474,123.883282583110088],"luv":[68.7658933773114711,-40.9030232283392365,60.9085013577552417],"rgb":[0.4,0.733333333333333282,0.333333333333333315],"xyz":[0.248884313733746254,0.390201974782464711,0.148148239601169657],"hpluv":[123.883282583110088,135.386233996967292,68.7658933773114711],"hsluv":[123.883282583110088,73.3323147762666565,68.7658933773114711]},"#66bb66":{"lch":[68.985024233854773,66.1955602149500493,127.715012949239338],"luv":[68.985024233854773,-40.4940973290304953,52.3648763359380354],"rgb":[0.4,0.733333333333333282,0.4],"xyz":[0.256469309507254439,0.39323597309186803,0.188095884008313619],"hpluv":[127.715012949239338,121.76244699215377,68.985024233854773],"hsluv":[127.715012949239338,61.9987879490855889,68.985024233854773]},"#66bb77":{"lch":[69.2525700917713,58.3030977404443149,133.351332140289912],"luv":[69.2525700917713,-40.0233333378199134,42.395565742911792],"rgb":[0.4,0.733333333333333282,0.466666666666666674],"xyz":[0.265783322527456345,0.396961578299948825,0.237149685914711528],"hpluv":[133.351332140289912,106.830450835327468,69.2525700917713],"hsluv":[133.351332140289912,63.1630001095548,69.2525700917713]},"#66bb88":{"lch":[69.5703900447947632,50.3125315521488901,141.732198444264128],"luv":[69.5703900447947632,-39.5016033478381487,31.1604583428427624],"rgb":[0.4,0.733333333333333282,0.533333333333333326],"xyz":[0.276923739629400201,0.401417745140726423,0.295822549318283667],"hpluv":[141.732198444264128,91.7679559652102625,69.5703900447947632],"hsluv":[141.732198444264128,64.4651291783298888,69.5703900447947632]},"#66bb99":{"lch":[69.9399065468101924,43.264635747530761,154.168279853010262],"luv":[69.9399065468101924,-38.9415329854338594,18.8516767188195544],"rgb":[0.4,0.733333333333333282,0.6],"xyz":[0.2899807037384729,0.406640530784355581,0.364589226959401602],"hpluv":[154.168279853010262,78.4959645714096865,69.9399065468101924],"hsluv":[154.168279853010262,65.8787579381207848,69.9399065468101924]},"#66bbaa":{"lch":[70.3621368583926881,38.7745898249838348,171.579209782291855],"luv":[70.3621368583926881,-38.3565710720190296,5.67822786553099768],"rgb":[0.4,0.733333333333333282,0.66666666666666663],"xyz":[0.305038396703725456,0.412663607970456703,0.443893076576400203],"hpluv":[171.579209782291855,69.9274221790226278,70.3621368583926881],"hsluv":[171.579209782291855,67.37547943529961,70.3621368583926881]},"#66bbbb":{"lch":[70.8377198879813221,38.6292683935386592,192.177050630060933],"luv":[70.8377198879813221,-37.7601276376370194,-8.14819841495072161],"rgb":[0.4,0.733333333333333282,0.733333333333333282],"xyz":[0.322175988811062075,0.419518644813391461,0.534151061675042],"hpluv":[192.177050630060933,69.1976324805594629,70.8377198879813221],"hsluv":[192.177050630060933,68.9267726464228758,70.8377198879813221]},"#66bbcc":{"lch":[71.3669414392261103,43.4063518114314,211.106579982723787],"luv":[71.3669414392261103,-37.1648552128157,-22.4250956427882215],"rgb":[0.4,0.733333333333333282,0.8],"xyz":[0.341468364254783829,0.427235594990880263,0.635757572345312161],"hpluv":[211.106579982723787,77.1783568223693806,71.3669414392261103],"hsluv":[211.106579982723787,70.5055674968506736,71.3669414392261103]},"#66bbdd":{"lch":[71.9497594848613602,52.0084901368895629,225.300588521911806],"luv":[71.9497594848613602,-36.5821167433876298,-36.9679831866995059],"rgb":[0.4,0.733333333333333282,0.866666666666666696],"xyz":[0.362986689805417373,0.435842925211133769,0.749087420245318159],"hpluv":[225.300588521911806,91.724261948179759,71.9497594848613602],"hsluv":[225.300588521911806,72.0874065633031336,71.9497594848613602]},"#66bbee":{"lch":[72.5858302461357852,62.9426478584387183,235.089705553804919],"luv":[72.5858302461357852,-36.0216507769597953,-51.6160594653851135],"rgb":[0.4,0.733333333333333282,0.933333333333333348],"xyz":[0.386798870071592082,0.445367797317603786,0.874498236313841382],"hpluv":[235.089705553804919,110.035415213757233,72.5858302461357852],"hsluv":[235.089705553804919,76.908955535231712,72.5858302461357852]},"#66bbff":{"lch":[73.2745353232689638,75.1445669264803513,241.815748730615525],"luv":[73.2745353232689638,-35.4914181095182641,-66.2349241650025817],"rgb":[0.4,0.733333333333333282,1],"xyz":[0.412969918481423504,0.45583621668153651,1.01233242460562312],"hpluv":[241.815748730615525,130.131920555189879,73.2745353232689638],"hsluv":[241.815748730615525,99.9999999999976552,73.2745353232689638]},"#113300":{"lch":[17.8585390793191152,25.0449080182821966,121.332554648991049],"luv":[17.8585390793191152,-13.0234653569097247,21.3924465113644295],"rgb":[0.0666666666666666657,0.2,0],"xyz":[0.0141493580168107792,0.0248674170719056023,0.00405427217088629669],"hpluv":[121.332554648991049,177.956083469309505,17.8585390793191152],"hsluv":[121.332554648991049,100.000000000002288,17.8585390793191152]},"#113311":{"lch":[18.041211184449395,20.8015074137336562,127.715012949239792],"luv":[18.041211184449395,-12.7249964056056086,16.4553084796651738],"rgb":[0.0666666666666666657,0.2,0.0666666666666666657],"xyz":[0.015161023516447901,0.0252720832717604552,0.00938237713564192902],"hpluv":[127.715012949239792,146.308124837666583,18.041211184449395],"hsluv":[127.715012949239792,74.4969128915689254,18.041211184449395]},"#113322":{"lch":[18.3747440863758129,14.8635488733567129,145.575764327225926],"luv":[18.3747440863758129,-12.2605616690393529,8.40260154180516672],"rgb":[0.0666666666666666657,0.2,0.133333333333333331],"xyz":[0.0170363816549249196,0.0260222265271512765,0.0192592633316211251],"hpluv":[145.575764327225926,102.645648490479701,18.3747440863758129],"hsluv":[145.575764327225926,76.8412554017051,18.3747440863758129]},"#113333":{"lch":[18.910205854271,11.9516732098830207,192.177050630061075],"luv":[18.910205854271,-11.6827660646039035,-2.5210056714682163],"rgb":[0.0666666666666666657,0.2,0.2],"xyz":[0.0201241323873826601,0.0272573268201343893,0.0355214171892322683],"hpluv":[192.177050630061075,80.19952200231,18.910205854271],"hsluv":[192.177050630061075,79.885597544945341,18.910205854271]},"#113344":{"lch":[19.6554681695294136,18.5554908550806559,233.185939638237187],"luv":[19.6554681695294136,-11.1188227079461566,-14.8552355236207116],"rgb":[0.0666666666666666657,0.2,0.266666666666666663],"xyz":[0.0245821276316015372,0.0290405249178219624,0.0590001921421189068],"hpluv":[233.185939638237187,119.79215597403514,19.6554681695294136],"hsluv":[233.185939638237187,83.0941728600946163,19.6554681695294136]},"#113355":{"lch":[20.6059777210847557,29.4541985213363553,248.778672986371305],"luv":[20.6059777210847557,-10.6615827984222822,-27.4568837045772334],"rgb":[0.0666666666666666657,0.2,0.333333333333333315],"xyz":[0.0305445416709635327,0.0314254905335667953,0.0904022394160928222],"hpluv":[248.778672986371305,181.381634101163,20.6059777210847557],"hsluv":[248.778672986371305,86.0667890851332089,20.6059777210847557]},"#113366":{"lch":[21.7480278014825927,41.0513772817531262,255.392805777322508],"luv":[21.7480278014825927,-10.3527823296753354,-39.7244946445288178],"rgb":[0.0666666666666666657,0.2,0.4],"xyz":[0.0381295374444717075,0.0344594888429701068,0.130349883823236784],"hpluv":[255.392805777322508,239.522976201191227,21.7480278014825927],"hsluv":[255.392805777322508,88.6137215649990537,21.7480278014825927]},"#113377":{"lch":[23.0621320749224097,52.4639032010768602,258.793139915612699],"luv":[23.0621320749224097,-10.1964540550792755,-51.4635158514711293],"rgb":[0.0666666666666666657,0.2,0.466666666666666674],"xyz":[0.04744355046467362,0.0381850940510509232,0.179403685729634693],"hpluv":[258.793139915612699,288.669213908808,23.0621320749224097],"hsluv":[258.793139915612699,90.7010140503724926,23.0621320749224097]},"#113388":{"lch":[24.5260866455155693,63.5079254673071389,260.778240759541745],"luv":[24.5260866455155693,-10.1775299952298717,-62.6871157444433322],"rgb":[0.0666666666666666657,0.2,0.533333333333333326],"xyz":[0.0585839675666174481,0.0426412608918285141,0.238076549133206861],"hpluv":[260.778240759541745,328.5783880762134,24.5260866455155693],"hsluv":[260.778240759541745,92.3732755032704,24.5260866455155693]},"#113399":{"lch":[26.1173586094444445,74.1961224571638667,262.040130643645512],"luv":[26.1173586094444445,-10.2746398160742789,-73.4812653968914447],"rgb":[0.0666666666666666657,0.2,0.6],"xyz":[0.0716409316756901615,0.0478640465354576786,0.30684322677432474],"hpluv":[262.040130643645512,360.488391101723778,26.1173586094444445],"hsluv":[262.040130643645512,93.700931793532277,26.1173586094444445]},"#1133aa":{"lch":[27.8146812937100378,84.589542856674214,262.892366774415223],"luv":[27.8146812937100378,-10.4665753413372666,-83.9395113240792767],"rgb":[0.0666666666666666657,0.2,0.66666666666666663],"xyz":[0.0866986246409427,0.0538871237215587801,0.386147076391323341],"hpluv":[262.892366774415223,385.906342473210088,27.8146812937100378],"hsluv":[262.892366774415223,94.7540719156047544,27.8146812937100378]},"#1133bb":{"lch":[29.5989386642012917,94.7497677250031245,263.494633441352278],"luv":[29.5989386642012917,-10.734795769033445,-94.1396974912241],"rgb":[0.0666666666666666657,0.2,0.733333333333333282],"xyz":[0.10383621674827935,0.0607421605644935386,0.476405061489965087],"hpluv":[263.494633441352278,406.201330660618282,29.5989386642012917],"hsluv":[263.494633441352278,95.59270717643426,29.5989386642012917]},"#1133cc":{"lch":[31.4535171675710927,104.725970292241058,263.935552719695806],"luv":[31.4535171675710927,-11.0639900580249932,-104.139891384844844],"rgb":[0.0666666666666666657,0.2,0.8],"xyz":[0.123128592192001091,0.0684591107419823403,0.578011572160235243],"hpluv":[263.935552719695806,422.497850271701509,31.4535171675710927],"hsluv":[263.935552719695806,96.2648935085394299,31.4535171675710927]},"#1133dd":{"lch":[33.3643121953656845,114.554023382916327,264.267643395871801],"luv":[33.3643121953656845,-11.4418472625073555,-113.981175658242762],"rgb":[0.0666666666666666657,0.2,0.866666666666666696],"xyz":[0.144646917742634634,0.0770664409622358743,0.691341420060241241],"hpluv":[264.267643395871801,435.679872957086786,33.3643121953656845],"hsluv":[264.267643395871801,96.8079128297289913,33.3643121953656845]},"#1133ee":{"lch":[35.3195411096734375,124.259061611723823,264.523680461367292],"luv":[35.3195411096734375,-11.8585821660500468,-123.691909281234786],"rgb":[0.0666666666666666657,0.2,0.933333333333333348],"xyz":[0.168459098008809371,0.0865913130687059,0.816752236128764464],"hpluv":[264.523680461367292,446.428943593210363,35.3195411096734375],"hsluv":[264.523680461367292,97.2502875158067752,35.3195411096734375]},"#1133ff":{"lch":[37.3094684856901466,133.858437412957159,264.724991571549936],"luv":[37.3094684856901466,-12.3064438760062309,-133.291532760957],"rgb":[0.0666666666666666657,0.2,1],"xyz":[0.194630146418640765,0.0970597324326386,0.954586424420546309],"hpluv":[264.724991571549936,455.266836240216,37.3094684856901466],"hsluv":[264.724991571549936,99.9999999999995168,37.3094684856901466]},"#66cc00":{"lch":[73.5514640948473328,100.417876322708906,119.311479215942285],"luv":[73.5514640948473328,-49.1602904566029579,87.5614968315714322],"rgb":[0.4,0.8,0],"xyz":[0.270712873389210462,0.460091387940038399,0.0745415201258350923],"hpluv":[119.311479215942285,173.244332851636557,73.5514640948473328],"hsluv":[119.311479215942285,100.00000000000226,73.5514640948473328]},"#66cc11":{"lch":[73.5777109322390572,99.3703085818509,119.605548775623987],"luv":[73.5777109322390572,-49.0915230219986611,86.397225621155485],"rgb":[0.4,0.8,0.0666666666666666657],"xyz":[0.271724538888847567,0.460496054139893252,0.079869625090590729],"hpluv":[119.605548775623987,171.375877908330068,73.5777109322390572],"hsluv":[119.605548775623987,98.5479766016144652,73.5777109322390572]},"#66cc22":{"lch":[73.626324929263788,97.4510710028789333,120.162888823436575],"luv":[73.626324929263788,-48.965269014871545,84.2562381661406192],"rgb":[0.4,0.8,0.133333333333333331],"xyz":[0.273599897027324623,0.461246197395284052,0.0897465112865699216],"hpluv":[120.162888823436575,167.954954584373922,73.626324929263788],"hsluv":[120.162888823436575,95.8800576342850377,73.626324929263788]},"#66cc33":{"lch":[73.7062524827218084,94.3550745227874,121.116489614327122],"luv":[73.7062524827218084,-48.7607908304490252,80.779114663321],"rgb":[0.4,0.8,0.2],"xyz":[0.276687647759782329,0.462481297688267179,0.106008665144181058],"hpluv":[121.116489614327122,162.442721914772306,73.7062524827218084],"hsluv":[121.116489614327122,91.5533619475712896,73.7062524827218084]},"#66cc44":{"lch":[73.8213986639243,90.0253172969507318,122.577193203242018],"luv":[73.8213986639243,-48.472817822786439,75.8613451418811451],"rgb":[0.4,0.8,0.266666666666666663],"xyz":[0.281145643004001244,0.464264495785954745,0.129487440097067696],"hpluv":[122.577193203242018,154.746814564283426,73.8213986639243],"hsluv":[122.577193203242018,85.4474048693987527,73.8213986639243]},"#66cc55":{"lch":[73.974942724102462,84.4934421806047879,124.700104619680829],"luv":[73.974942724102462,-48.100513339115345,69.4656921655632118],"rgb":[0.4,0.8,0.333333333333333315],"xyz":[0.28710805704336323,0.466649461401699606,0.160889487371041612],"hpluv":[124.700104619680829,144.936474170198323,73.974942724102462],"hsluv":[124.700104619680829,77.5306238992907,73.974942724102462]},"#66cc66":{"lch":[74.1695172801941567,77.8884466842553564,127.715012949239551],"luv":[74.1695172801941567,-47.6470375142611218,61.6146893443493937],"rgb":[0.4,0.8,0.4],"xyz":[0.294693052816871415,0.469683459711102924,0.200837131778185574],"hpluv":[127.715012949239551,133.256044234036153,74.1695172801941567],"hsluv":[127.715012949239551,67.8510775159793,74.1695172801941567]},"#66cc77":{"lch":[74.407302734023375,70.4570986939790203,131.971622948486811],"luv":[74.407302734023375,-47.1190629819757234,52.3831715350808551],"rgb":[0.4,0.8,0.466666666666666674],"xyz":[0.30400706583707332,0.47340906491918372,0.249890933684583483],"hpluv":[131.971622948486811,120.156846155807528,74.407302734023375],"hsluv":[131.971622948486811,68.6882673601907499,74.407302734023375]},"#66cc88":{"lch":[74.6900832163393602,62.6050444414555045,138.002106903522986],"luv":[74.6900832163393602,-46.5261552249599859,41.8892404980031543],"rgb":[0.4,0.8,0.533333333333333326],"xyz":[0.315147482939017121,0.477865231759961318,0.308563797088155622],"hpluv":[138.002106903522986,106.361808066007058,74.6900832163393602],"hsluv":[138.002106903522986,69.6340873295455367,74.6900832163393602]},"#66cc99":{"lch":[75.0192831982140405,54.9734389641357382,146.572693391746668],"luv":[75.0192831982140405,-45.8800303566060634,30.2836887782922481],"rgb":[0.4,0.8,0.6],"xyz":[0.32820444704808982,0.483088017403590475,0.377330474729273557],"hpluv":[146.572693391746668,92.9863760296957338,75.0192831982140405],"hsluv":[146.572693391746668,70.6723780843603,75.0192831982140405]},"#66ccaa":{"lch":[75.3959940236094,48.5503126646653,158.569930493367366],"luv":[75.3959940236094,-45.1937477629490587,17.7386026218441692],"rgb":[0.4,0.8,0.66666666666666663],"xyz":[0.343262140013342376,0.489111094589691597,0.456634324346272158],"hpluv":[158.569930493367366,81.7114817988577187,75.3959940236094],"hsluv":[158.569930493367366,71.7849539596152368,75.3959940236094]},"#66ccbb":{"lch":[75.8209952994642,44.7015709258060667,174.304687468137473],"luv":[75.8209952994642,-44.4809102105153755,4.43610979112772],"rgb":[0.4,0.8,0.733333333333333282],"xyz":[0.360399732120679051,0.495966131432626356,0.546892309444913849],"hpluv":[174.304687468137473,74.8122352806046109,75.8209952994642],"hsluv":[174.304687468137473,72.9527506991265113,75.8209952994642]},"#66cccc":{"lch":[76.2947739303160262,44.7620652034609634,192.177050630061018],"luv":[76.2947739303160262,-43.7549393425641924,-9.44180938207391],"rgb":[0.4,0.8,0.8],"xyz":[0.379692107564400749,0.503683081610115102,0.648498820115184],"hpluv":[192.177050630061018,75.6461904464395,76.2947739303160262],"hsluv":[192.177050630061018,74.1568646821725679,76.2947739303160262]},"#66ccdd":{"lch":[76.8175423984245782,49.1342213212598082,208.868111129197587],"luv":[76.8175423984245782,-43.0284772118039101,-23.7217590764220851],"rgb":[0.4,0.8,0.866666666666666696],"xyz":[0.401210433115034348,0.512290411830368719,0.76182866801519],"hpluv":[208.868111129197587,85.3113130970085791,76.8175423984245782],"hsluv":[208.868111129197587,75.3794120212671714,76.8175423984245782]},"#66ccee":{"lch":[77.3892571801628435,57.0358051623713038,222.109360872917676],"luv":[77.3892571801628435,-42.312941633688304,-38.245235531031426],"rgb":[0.4,0.8,0.933333333333333348],"xyz":[0.425022613381209058,0.521815283936838736,0.887239484083713226],"hpluv":[222.109360872917676,102.061631830010029,77.3892571801628435],"hsluv":[222.109360872917676,76.6041682601332923,77.3892571801628435]},"#66ccff":{"lch":[78.0096377377628158,67.2874731922355664,231.792303901557148],"luv":[78.0096377377628158,-41.6182406850010267,-52.872734853430309],"rgb":[0.4,0.8,1],"xyz":[0.451193661791040479,0.53228370330077146,1.02507367237549518],"hpluv":[231.792303901557148,124.498094909356865,78.0096377377628158],"hsluv":[231.792303901557148,99.9999999999966604,78.0096377377628158]},"#114400":{"lch":[24.4916204196936391,35.767443133059956,124.131260038140155],"luv":[24.4916204196936391,-20.0687794552527912,29.6066559991685239],"rgb":[0.0666666666666666657,0.266666666666666663,0],"xyz":[0.0229819284997768124,0.0425325580378379114,0.00699846233187489172],"hpluv":[124.131260038140155,185.314627891622,24.4916204196936391],"hsluv":[124.131260038140155,100.000000000002416,24.4916204196936391]},"#114411":{"lch":[24.6196313539200702,32.2821952767626144,127.715012949240105],"luv":[24.6196313539200702,-19.7481274165088401,25.5372589646650674],"rgb":[0.0666666666666666657,0.266666666666666663,0.0666666666666666657],"xyz":[0.0239935939994139341,0.0429372242376927643,0.0123265672966305223],"hpluv":[127.715012949240105,166.387555424049935,24.6196313539200702],"hsluv":[127.715012949240105,84.7209219338948,24.6196313539200702]},"#114422":{"lch":[24.8548180969752792,26.7199561105771828,135.968420687644709],"luv":[24.8548180969752792,-19.2104947057918238,18.5718321042894203],"rgb":[0.0666666666666666657,0.266666666666666663,0.133333333333333331],"xyz":[0.0258689521378909527,0.0436873674930835856,0.0222034534926097184],"hpluv":[135.968420687644709,136.415738329938534,24.8548180969752792],"hsluv":[135.968420687644709,85.5945702875542338,24.8548180969752792]},"#114433":{"lch":[25.2362525898650887,20.3101465248311648,155.348193219538018],"luv":[25.2362525898650887,-18.4590663004995292,8.4714180143512],"rgb":[0.0666666666666666657,0.266666666666666663,0.2],"xyz":[0.0289567028703486933,0.0449224677860667,0.0384656073502208651],"hpluv":[155.348193219538018,102.123929581721498,25.2362525898650887],"hsluv":[155.348193219538018,86.8340768870874911,25.2362525898650887]},"#114444":{"lch":[25.774812755707849,18.0038630185053101,192.177050630061132],"luv":[25.774812755707849,-17.5987843886529483,-3.79761393914762779],"rgb":[0.0666666666666666657,0.266666666666666663,0.266666666666666663],"xyz":[0.0334146981145675703,0.0467056658837542715,0.0619443823031075036],"hpluv":[192.177050630061132,88.6358691141452226,25.774812755707849],"hsluv":[192.177050630061132,88.2889223192016743,25.774812755707849]},"#114455":{"lch":[26.4741010086829718,23.9697809957076196,225.699525295295985],"luv":[26.4741010086829718,-16.7410035671662349,-17.1548593857925162],"rgb":[0.0666666666666666657,0.266666666666666663,0.333333333333333315],"xyz":[0.0393771121539295693,0.0490906314994991044,0.0933464295770814],"hpluv":[225.699525295295985,114.889984549549212,26.4741010086829718],"hsluv":[225.699525295295985,89.7968555301121398,26.4741010086829718]},"#114466":{"lch":[27.3316922889079734,34.6428172107851182,242.548035964380944],"luv":[27.3316922889079734,-15.9705048052882308,-30.7419544037807526],"rgb":[0.0666666666666666657,0.266666666666666663,0.4],"xyz":[0.0469621079274377407,0.052124629808902416,0.133294073984225381],"hpluv":[242.548035964380944,160.837015687659374,27.3316922889079734],"hsluv":[242.548035964380944,91.2329185483074525,27.3316922889079734]},"#114477":{"lch":[28.3404051997208484,46.6267191674415,250.798290317077829],"luv":[28.3404051997208484,-15.3352867062553546,-44.0327142242719844],"rgb":[0.0666666666666666657,0.266666666666666663,0.466666666666666674],"xyz":[0.0562761209476396601,0.0558502350169832323,0.18234787589062329],"hpluv":[250.798290317077829,208.770018220734585,28.3404051997208484],"hsluv":[250.798290317077829,92.5248535524246734,28.3404051997208484]},"#114488":{"lch":[29.4896359978219706,58.6954673108201632,255.342505689020953],"luv":[29.4896359978219706,-14.8523182742844106,-56.7852667926718055],"rgb":[0.0666666666666666657,0.266666666666666663,0.533333333333333326],"xyz":[0.0674165380495834882,0.0603064018577608302,0.241020739294195457],"hpluv":[255.342505689020953,252.565763352450517,29.4896359978219706],"hsluv":[255.342505689020953,93.6449802292742817,29.4896359978219706]},"#114499":{"lch":[30.7666487879374699,70.4540899928233699,258.107815399211404],"luv":[30.7666487879374699,-14.5185243824624628,-68.9419411278265102],"rgb":[0.0666666666666666657,0.266666666666666663,0.6],"xyz":[0.0804735021586562,0.0655291875013899877,0.309787416935313364],"hpluv":[258.107815399211404,290.579747717257874,30.7666487879374699],"hsluv":[258.107815399211404,94.5943513350065359,30.7666487879374699]},"#1144aa":{"lch":[32.1577052090601185,81.8040240174920541,259.917940759024589],"luv":[32.1577052090601185,-14.3204852090806973,-80.5408098347099894],"rgb":[0.0666666666666666657,0.266666666666666663,0.66666666666666663],"xyz":[0.0955311951239087437,0.0715522646874911,0.389091266552311965],"hpluv":[259.917940759024589,322.796594575352628,32.1577052090601185],"hsluv":[259.917940759024589,95.3887741756132925,32.1577052090601185]},"#1144bb":{"lch":[33.6489603009756664,92.7573184463875435,261.168522985608377],"luv":[33.6489603009756664,-14.2409127099882671,-91.6576048702508928],"rgb":[0.0666666666666666657,0.266666666666666663,0.733333333333333282],"xyz":[0.11266878723124539,0.0784073015304258547,0.479349251650953712],"hpluv":[261.168522985608377,349.796823816496214,33.6489603009756664],"hsluv":[261.168522985608377,96.0495339612535872,33.6489603009756664]},"#1144cc":{"lch":[35.2271045850644597,103.362934076908545,262.068884255867147],"luv":[35.2271045850644597,-14.262270250582695,-102.374234005860515],"rgb":[0.0666666666666666657,0.266666666666666663,0.8],"xyz":[0.131961162674967131,0.0861242517079146563,0.580955762321223812],"hpluv":[262.068884255867147,372.329293739207799,35.2271045850644597],"hsluv":[262.068884255867147,96.5982694251149638,35.2271045850644597]},"#1144dd":{"lch":[36.8797734412618,113.676357292171801,262.73849416957313],"luv":[36.8797734412618,-14.3684841809298494,-112.764625967365617],"rgb":[0.0666666666666666657,0.266666666666666663,0.866666666666666696],"xyz":[0.153479488225600674,0.0947315819281681903,0.69428561022122981],"hpluv":[262.73849416957313,391.13009227787353,36.8797734412618],"hsluv":[262.73849416957313,97.0546019825808,36.8797734412618]},"#1144ee":{"lch":[38.5957670998368911,123.747928777943088,263.249741523271325],"luv":[38.5957670998368911,-14.5455638799169762,-122.890099065165245],"rgb":[0.0666666666666666657,0.266666666666666663,0.933333333333333348],"xyz":[0.177291668491775412,0.104256454034638207,0.819696426289753],"hpluv":[263.249741523271325,406.853061330967478,38.5957670998368911],"hsluv":[263.249741523271325,97.4353215147193623,38.5957670998368911]},"#1144ff":{"lch":[40.3651306844127546,133.619394536005728,263.648645306126298],"luv":[40.3651306844127546,-14.7816672391382209,-132.799265471613751],"rgb":[0.0666666666666666657,0.266666666666666663,1],"xyz":[0.203462716901606805,0.114724873398570917,0.957530614581534878],"hpluv":[263.648645306126298,420.051425771921231,40.3651306844127546],"hsluv":[263.648645306126298,99.9999999999994458,40.3651306844127546]},"#66dd00":{"lch":[78.7732081443282084,109.616469768408933,120.762072840728067],"luv":[78.7732081443282084,-56.0659919017112145,94.1932853050883],"rgb":[0.4,0.866666666666666696,0],"xyz":[0.313346863936385611,0.54535936903439,0.0887528503082264109],"hpluv":[120.762072840728067,211.559351010719155,78.7732081443282084],"hsluv":[120.762072840728067,100.000000000002444,78.7732081443282084]},"#66dd11":{"lch":[78.7966434753788576,108.675393583239966,121.014553037765893],"luv":[78.7966434753788576,-55.9956244091473678,93.1387739746547],"rgb":[0.4,0.866666666666666696,0.0666666666666666657],"xyz":[0.314358529436022716,0.545764035234244882,0.0940809552729820475],"hpluv":[121.014553037765893,210.019013530063148,78.7966434753788576],"hsluv":[121.014553037765893,98.7735218244661866,78.7966434753788576]},"#66dd22":{"lch":[78.8400557089289435,106.948443645027297,121.491090191754736],"luv":[78.8400557089289435,-55.866227309203758,91.1972271745690506],"rgb":[0.4,0.866666666666666696,0.133333333333333331],"xyz":[0.316233887574499772,0.546514178489635682,0.10395784146896124],"hpluv":[121.491090191754736,207.186246213049145,78.8400557089289435],"hsluv":[121.491090191754736,96.5169147905729,78.8400557089289435]},"#66dd33":{"lch":[78.911446872650572,104.154611952746194,122.300539429107701],"luv":[78.911446872650572,-55.6560904548950788,88.037394249850891],"rgb":[0.4,0.866666666666666696,0.2],"xyz":[0.319321638306957478,0.547749278782618809,0.120219995326572376],"hpluv":[122.300539429107701,202.586476802368111,78.911446872650572],"hsluv":[122.300539429107701,92.8487034899531807,78.911446872650572]},"#66dd44":{"lch":[79.0143300648071687,100.229492569308348,123.526451276321851],"luv":[79.0143300648071687,-55.3589437481663,83.5544045983716899],"rgb":[0.4,0.866666666666666696,0.266666666666666663],"xyz":[0.323779633551176393,0.549532476880306375,0.143698770279459015],"hpluv":[123.526451276321851,196.088207898644384,79.0143300648071687],"hsluv":[123.526451276321851,87.6539206040991843,79.0143300648071687]},"#66dd55":{"lch":[79.1515854502963,95.1800529291645603,125.27945296022996],"luv":[79.1515854502963,-54.9726586351532518,77.699737954393882],"rgb":[0.4,0.866666666666666696,0.333333333333333315],"xyz":[0.329742047590538379,0.551917442496051125,0.17510081755343293],"hpluv":[125.27945296022996,187.665730733793509,79.1515854502963],"hsluv":[125.27945296022996,80.8868034505971707,79.1515854502963]},"#66dd66":{"lch":[79.3256225689869723,89.0890908185611607,127.715012949239735],"luv":[79.3256225689869723,-54.4988561596450722,70.4751075215082921],"rgb":[0.4,0.866666666666666696,0.4],"xyz":[0.337327043364046564,0.554951440805454443,0.215048461960576892],"hpluv":[127.715012949239735,177.410630109117562,79.3256225689869723],"hsluv":[127.715012949239735,72.5638298210149,79.3256225689869723]},"#66dd77":{"lch":[79.538466322575843,82.1265081512392072,131.057978326052336],"luv":[79.538466322575843,-53.9425296262626048,61.9271090770055395],"rgb":[0.4,0.866666666666666696,0.466666666666666674],"xyz":[0.346641056384248469,0.558677046013535294,0.264102263866974774],"hpluv":[131.057978326052336,165.560886464635786,79.538466322575843],"hsluv":[131.057978326052336,73.175897046832489,79.538466322575843]},"#66dd88":{"lch":[79.7918079202835173,74.5708009722257543,135.636001638862723],"luv":[79.7918079202835173,-53.3115731427918,52.1409678341327378],"rgb":[0.4,0.866666666666666696,0.533333333333333326],"xyz":[0.35778147348619227,0.563133212854312837,0.322775127270546969],"hpluv":[135.636001638862723,152.557764790666909,79.7918079202835173],"hsluv":[135.636001638862723,73.8730513922454435,79.7918079202835173]},"#66dd99":{"lch":[80.0870378401123162,66.8478260511747919,141.915708870878916],"luv":[80.0870378401123162,-52.6162023759431392,41.2330825345609924],"rgb":[0.4,0.866666666666666696,0.6],"xyz":[0.370838437595265,0.568355998497942,0.391541804911664904],"hpluv":[141.915708870878916,139.150468179242381,80.0870378401123162],"hsluv":[141.915708870878916,74.6453790933081791,80.0870378401123162]},"#66ddaa":{"lch":[80.4252690581998877,59.592891473004542,150.502508447871207],"luv":[80.4252690581998877,-51.8682972227800931,29.3426729750825572],"rgb":[0.4,0.866666666666666696,0.66666666666666663],"xyz":[0.385896130560517525,0.574379075684043117,0.470845654528663449],"hpluv":[150.502508447871207,126.571308780245914,80.4252690581998877],"hsluv":[150.502508447871207,75.4812281571350638,80.4252690581998877]},"#66ddbb":{"lch":[80.807354973374558,53.7174771102931672,161.973645166837599],"luv":[80.807354973374558,-51.0807157732000334,16.6231111165276104],"rgb":[0.4,0.866666666666666696,0.733333333333333282],"xyz":[0.4030337226678542,0.581234112526977875,0.561103639627305251],"hpluv":[161.973645166837599,116.757770235740637,80.807354973374558],"hsluv":[161.973645166837599,76.3679029554368753,80.807354973374558]},"#66ddcc":{"lch":[81.2339045655681389,50.3705316419042148,176.319314132685548],"luv":[81.2339045655681389,-50.2666331071559256,3.23358221770368903],"rgb":[0.4,0.866666666666666696,0.8],"xyz":[0.422326098111575954,0.588951062704466732,0.662710150297575407],"hpluv":[176.319314132685548,112.393665646206941,81.2339045655681389],"hsluv":[176.319314132685548,77.2923330418296501,81.2339045655681389]},"#66dddd":{"lch":[81.7052962965957903,50.5769089008318389,192.177050630061],"luv":[81.7052962965957903,-49.4389517336029,-10.6683534552210038],"rgb":[0.4,0.866666666666666696,0.866666666666666696],"xyz":[0.443844423662209442,0.597558392924720239,0.776039998197581404],"hpluv":[192.177050630061,116.242714563462513,81.7052962965957903],"hsluv":[192.177050630061,78.2416694753709407,81.7052962965957903]},"#66ddee":{"lch":[82.2216916522674524,54.6311568672274745,207.154140846621715],"luv":[82.2216916522674524,-48.6098170936026577,-24.9328895793911158],"rgb":[0.4,0.866666666666666696,0.933333333333333348],"xyz":[0.467656603928384207,0.607083265031190256,0.901450814266104627],"hpluv":[207.154140846621715,129.793318723999505,82.2216916522674524],"hsluv":[207.154140846621715,79.2037752530793,82.2216916522674524]},"#66ddff":{"lch":[82.7830488398693376,61.9519841783888339,219.519505956683815],"luv":[82.7830488398693376,-47.7902556034158366,-39.4225799891321387],"rgb":[0.4,0.866666666666666696,1],"xyz":[0.493827652338215572,0.617551684395123,1.03928500255788636],"hpluv":[219.519505956683815,152.730665075356086,82.7830488398693376],"hsluv":[219.519505956683815,99.9999999999957,82.7830488398693376]},"#115500":{"lch":[30.9160157060817227,46.0913193883500583,125.457330883646421],"luv":[30.9160157060817227,-26.7374134918097575,37.543580579466358],"rgb":[0.0666666666666666657,0.333333333333333315,0],"xyz":[0.0347951852141227744,0.0661590714665301755,0.0109362145699901016],"hpluv":[125.457330883646421,189.179880792461034,30.9160157060817227],"hsluv":[125.457330883646421,100.000000000002402,30.9160157060817227]},"#115511":{"lch":[31.0114762783458957,43.2230667766736616,127.715012949240275],"luv":[31.0114762783458957,-26.4410342208804181,34.1921805521528697],"rgb":[0.0666666666666666657,0.333333333333333315,0.0666666666666666657],"xyz":[0.0358068507137599,0.0665637376663850283,0.0162643195347457331],"hpluv":[127.715012949240275,176.861157643680144,31.0114762783458957],"hsluv":[127.715012949240275,90.0538522348087156,31.0114762783458957]},"#115522":{"lch":[31.1874163697014737,38.3803455570512071,132.492971129528541],"luv":[31.1874163697014737,-25.925914044022,28.3001396827055132],"rgb":[0.0666666666666666657,0.333333333333333315,0.133333333333333331],"xyz":[0.0376822088522369147,0.0673138809217758427,0.0261412057307249292],"hpluv":[132.492971129528541,156.159643444286843,31.1874163697014737],"hsluv":[132.492971129528541,90.4316047034468653,31.1874163697014737]},"#115533":{"lch":[31.4742731349983,31.7764378074468219,142.363318860140765],"luv":[31.4742731349983,-25.163724938647551,19.4043538140960301],"rgb":[0.0666666666666666657,0.333333333333333315,0.2],"xyz":[0.0407699595846946553,0.0685489812147589556,0.0424033595883360759],"hpluv":[142.363318860140765,128.111709873485438,31.4742731349983],"hsluv":[142.363318860140765,90.9947325890089616,31.4742731349983]},"#115544":{"lch":[31.8824114421380642,25.5202649789159608,161.635705606154772],"luv":[31.8824114421380642,-24.2205825435089714,8.04035483341083435],"rgb":[0.0666666666666666657,0.333333333333333315,0.266666666666666663],"xyz":[0.0452279548289135358,0.0703321793124465355,0.0658821345412227144],"hpluv":[161.635705606154772,101.571845607751229,31.8824114421380642],"hsluv":[161.635705606154772,91.6999843863076194,31.8824114421380642]},"#115555":{"lch":[32.417637609391285,23.7206023942150033,192.177050630061103],"luv":[32.417637609391285,-23.1868997601056,-5.00346454561771115],"rgb":[0.0666666666666666657,0.333333333333333315,0.333333333333333315],"xyz":[0.0511903688682755278,0.0727171449281913684,0.0972841818151966159],"hpluv":[192.177050630061103,92.8503782686988899,32.417637609391285],"hsluv":[192.177050630061103,92.4869346485079,32.417637609391285]},"#115566":{"lch":[33.0818646063754045,29.1355194477524577,220.509575549450261],"luv":[33.0818646063754045,-22.1516601517912761,-18.9257085999416219],"rgb":[0.0666666666666666657,0.333333333333333315,0.4],"xyz":[0.0587753646417837061,0.0757511432375946869,0.137231826222340592],"hpluv":[220.509575549450261,111.756325010930979,33.0818646063754045],"hsluv":[220.509575549450261,93.2955878193037904,33.0818646063754045]},"#115577":{"lch":[33.8736729304774826,39.2775515041961185,237.359341141202208],"luv":[33.8736729304774826,-21.1850732372535866,-33.0744421585153958],"rgb":[0.0666666666666666657,0.333333333333333315,0.466666666666666674],"xyz":[0.0680893776619856117,0.0794767484456755,0.186285628128738501],"hpluv":[237.359341141202208,147.13684637222039,33.8736729304774826],"hsluv":[237.359341141202208,94.078253732623736,33.8736729304774826]},"#115588":{"lch":[34.7888943497230514,51.2161985161337938,246.60972521059881],"luv":[34.7888943497230514,-20.3324266151093482,-47.0073549392562455],"rgb":[0.0666666666666666657,0.333333333333333315,0.533333333333333326],"xyz":[0.0792297947639294398,0.0839329152864531,0.244958491532310668],"hpluv":[246.60972521059881,186.812546427038342,34.7888943497230514],"hsluv":[246.60972521059881,94.8038015691112719,34.7888943497230514]},"#115599":{"lch":[35.8212274371681403,63.5782184467896,252.028930114170464],"luv":[35.8212274371681403,-19.6162163870228632,-60.476391389741444],"rgb":[0.0666666666666666657,0.333333333333333315,0.6],"xyz":[0.0922867588730021671,0.0891557009300822517,0.313725169173428575],"hpluv":[252.028930114170464,225.22013661091745,35.8212274371681403],"hsluv":[252.028930114170464,95.4562831747131355,35.8212274371681403]},"#1155aa":{"lch":[36.9628521043173777,75.808874965898184,255.452401876993463],"luv":[36.9628521043173777,-19.0419916394553752,-73.3783897206670588],"rgb":[0.0666666666666666657,0.333333333333333315,0.66666666666666663],"xyz":[0.107344451838254695,0.0951787781161833601,0.393029018790427176],"hpluv":[255.452401876993463,260.251896817562397,36.9628521043173777],"hsluv":[255.452401876993463,96.0310300088164155,36.9628521043173777]},"#1155bb":{"lch":[38.2050019251475845,87.6984258792502089,257.752076786877694],"luv":[38.2050019251475845,-18.6045414354547205,-85.7023041678273216],"rgb":[0.0666666666666666657,0.333333333333333315,0.733333333333333282],"xyz":[0.124482043945591342,0.102033814959118119,0.483287003889068922],"hpluv":[257.752076786877694,291.280156181798475,38.2050019251475845],"hsluv":[257.752076786877694,96.5305142623785,38.2050019251475845]},"#1155cc":{"lch":[39.5384610498345523,99.1886562531622,259.372402836059223],"luv":[39.5384610498345523,-18.292845239891637,-97.4872368176334447],"rgb":[0.0666666666666666657,0.333333333333333315,0.8],"xyz":[0.143774419389313096,0.10975076513660692,0.584893514559339],"hpluv":[259.372402836059223,318.332933912315752,39.5384610498345523],"hsluv":[259.372402836059223,96.9610449958707,39.5384610498345523]},"#1155dd":{"lch":[40.9539668975822053,110.288480556245688,260.557616930578945],"luv":[40.9539668975822053,-18.0934548393737415,-108.7941902648341],"rgb":[0.0666666666666666657,0.333333333333333315,0.866666666666666696],"xyz":[0.16529274493994664,0.118358095356860454,0.698223362459345],"hpluv":[260.557616930578945,341.722445031840948,40.9539668975822053],"hsluv":[260.557616930578945,97.330522563257,40.9539668975822053]},"#1155ee":{"lch":[42.4425141949683038,121.034132372772049,261.450904748640312],"luv":[42.4425141949683038,-17.992549051743687,-119.689303523123172],"rgb":[0.0666666666666666657,0.333333333333333315,0.933333333333333348],"xyz":[0.189104925206121377,0.127882967463330471,0.823634178527868244],"hpluv":[261.450904748640312,361.864588035447412,42.4425141949683038],"hsluv":[261.450904748640312,97.6470858685672596,42.4425141949683038]},"#1155ff":{"lch":[43.9955669218353762,131.469960671873054,262.140820458865903],"luv":[43.9955669218353762,-17.9770474653633769,-130.235081001594637],"rgb":[0.0666666666666666657,0.333333333333333315,1],"xyz":[0.21527597361595277,0.138351386827263168,0.961468366819650089],"hpluv":[262.140820458865903,379.190057269809415,43.9955669218353762],"hsluv":[262.140820458865903,99.9999999999993321,43.9955669218353762]},"#66ee00":{"lch":[83.9510288300903511,118.631054776009961,121.878900606421581],"luv":[83.9510288300903511,-62.6521043104729145,100.737485489455693],"rgb":[0.4,0.933333333333333348,0],"xyz":[0.360525640276900428,0.639716921715420939,0.104479109088397595],"hpluv":[121.878900606421581,316.932305812441825,83.9510288300903511],"hsluv":[121.878900606421581,100.000000000002245,83.9510288300903511]},"#66ee11":{"lch":[83.9720997528394406,117.779830021225337,122.096631719604488],"luv":[83.9720997528394406,-62.5821687959979371,99.7775551344988401],"rgb":[0.4,0.933333333333333348,0.0666666666666666657],"xyz":[0.361537305776537532,0.640121587915275847,0.109807214053153232],"hpluv":[122.096631719604488,315.12898496103287,83.9720997528394406],"hsluv":[122.096631719604488,98.9534187198870825,83.9720997528394406]},"#66ee22":{"lch":[84.0111361497279461,116.215639794016113,122.506307539641156],"luv":[84.0111361497279461,-62.4534076072217061,98.0084017366813498],"rgb":[0.4,0.933333333333333348,0.133333333333333331],"xyz":[0.363412663915014589,0.640871731170666648,0.119684100249132425],"hpluv":[122.506307539641156,311.807725961995743,84.0111361497279461],"hsluv":[122.506307539641156,97.0256918708191,84.0111361497279461]},"#66ee33":{"lch":[84.0753427139745213,113.679067087327056,123.198426402241765],"luv":[84.0753427139745213,-62.2438639038254564,95.1242960560921],"rgb":[0.4,0.933333333333333348,0.2],"xyz":[0.366500414647472295,0.642106831463649774,0.135946254106743575],"hpluv":[123.198426402241765,306.400922934277446,84.0753427139745213],"hsluv":[123.198426402241765,93.8862320250161133,84.0753427139745213]},"#66ee44":{"lch":[84.1678970009459704,110.10189342016568,124.237870325737177],"luv":[84.1678970009459704,-61.946619900698991,91.0222127702015626],"rgb":[0.4,0.933333333333333348,0.266666666666666663],"xyz":[0.37095840989169121,0.64389002956133734,0.159425029059630213],"hpluv":[124.237870325737177,298.731636810455427,84.1678970009459704],"hsluv":[124.237870325737177,89.4277949312148337,84.1678970009459704]},"#66ee55":{"lch":[84.2914184237995414,105.474359140243067,125.706632503417083],"luv":[84.2914184237995414,-61.5585501093914829,85.6468641835444657],"rgb":[0.4,0.933333333333333348,0.333333333333333315],"xyz":[0.376920823931053195,0.64627499517708209,0.190827076333604129],"hpluv":[125.706632503417083,288.732343582820249,84.2914184237995414],"hsluv":[125.706632503417083,83.5978964235977315,84.2914184237995414]},"#66ee66":{"lch":[84.4481159447294374,99.8471979874678652,127.715012949239849],"luv":[84.4481159447294374,-61.0799597466417339,78.9854509596370633],"rgb":[0.4,0.933333333333333348,0.4],"xyz":[0.38450581970456138,0.649308993486485408,0.230774720740748063],"hpluv":[127.715012949239849,276.453302697114395,84.4481159447294374],"hsluv":[127.715012949239849,76.3932656313124454,84.4481159447294374]},"#66ee77":{"lch":[84.6398667383604391,93.3381964812165,130.416076861551431],"luv":[84.6398667383604391,-60.5142850922984863,71.0636350191446127],"rgb":[0.4,0.933333333333333348,0.466666666666666674],"xyz":[0.393819832724763286,0.65303459869456626,0.279828522647145972],"hpluv":[130.416076861551431,262.087365127001192,84.6398667383604391],"hsluv":[130.416076861551431,76.8478121958162461,84.6398667383604391]},"#66ee88":{"lch":[84.8682629083727704,86.1443361377895513,134.024834696689027],"luv":[84.8682629083727704,-59.8677379892917187,61.9411058721588503],"rgb":[0.4,0.933333333333333348,0.533333333333333326],"xyz":[0.404960249826707086,0.657490765535343802,0.338501386050718167],"hpluv":[134.024834696689027,246.018013362770375,84.8682629083727704],"hsluv":[134.024834696689027,77.3690194462974858,84.8682629083727704]},"#66ee99":{"lch":[85.1346415661787432,78.5628931277068,138.840952739605655],"luv":[85.1346415661787432,-59.1488647733143296,51.7062856200641718],"rgb":[0.4,0.933333333333333348,0.6],"xyz":[0.418017213935779841,0.662713551178973,0.407268063691836046],"hpluv":[138.840952739605655,228.905884969324347,85.1346415661787432],"hsluv":[138.840952739605655,77.9507906120806,85.1346415661787432]},"#66eeaa":{"lch":[85.4401056772853451,71.025817565124143,145.263991147699045],"luv":[85.4401056772853451,-58.3680297483556387,40.4702342974360576],"rgb":[0.4,0.933333333333333348,0.66666666666666663],"xyz":[0.433074906901032342,0.668736628365074082,0.486571913308834647],"hpluv":[145.263991147699045,211.83630636980061,85.4401056772853451],"hsluv":[145.263991147699045,78.5856392083502868,85.4401056772853451]},"#66eebb":{"lch":[85.7855396574798448,64.1465768711300228,153.7611846199909],"luv":[85.7855396574798448,-57.5368534805651,28.3600743271201026],"rgb":[0.4,0.933333333333333348,0.733333333333333282],"xyz":[0.450212499008369,0.67559166520800884,0.576829898407476449],"hpluv":[153.7611846199909,196.542528595596508,85.7855396574798448],"hsluv":[153.7611846199909,79.2651091664321683,85.7855396574798448]},"#66eecc":{"lch":[86.1716220205593,58.7524914026155827,164.690737532459508],"luv":[86.1716220205593,-56.6676444389915517,15.5123602250092176],"rgb":[0.4,0.933333333333333348,0.8],"xyz":[0.46950487445209077,0.683308615385497697,0.678436409077746605],"hpluv":[164.690737532459508,185.645341664818176,86.1716220205593],"hsluv":[164.690737532459508,79.9801993176568118,86.1716220205593]},"#66eedd":{"lch":[86.5988364705929285,55.8111450312658164,177.877712634427581],"luv":[86.5988364705929285,-55.7728621696499403,2.06682246606168096],"rgb":[0.4,0.933333333333333348,0.866666666666666696],"xyz":[0.491023200002724258,0.691915945605751204,0.791766256977752603],"hpluv":[177.877712634427581,182.628088950326941,86.5988364705929285],"hsluv":[177.877712634427581,80.7217641095277543,86.5988364705929285]},"#66eeee":{"lch":[87.0674822997282263,56.1274864183573783,192.177050630061075],"luv":[87.0674822997282263,-54.8646438121880493,-11.8391549953798521],"rgb":[0.4,0.933333333333333348,0.933333333333333348],"xyz":[0.514835380268899,0.701440817712221221,0.917177073046275826],"hpluv":[192.177050630061075,191.066910285097691,87.0674822997282263],"hsluv":[192.177050630061075,81.4808670778618165,87.0674822997282263]},"#66eeff":{"lch":[87.5776846199412518,59.9248574237073512,205.793536431897621],"luv":[87.5776846199412518,-53.9544158989052178,-26.0750751151289606],"rgb":[0.4,0.933333333333333348,1],"xyz":[0.541006428678730389,0.711909237076154,1.05501126133805756],"hpluv":[205.793536431897621,213.276590696447101,87.5776846199412518],"hsluv":[205.793536431897621,99.9999999999933351,87.5776846199412518]},"#116600":{"lch":[37.1543973335168118,56.0416844920186463,126.180156646926719],"luv":[37.1543973335168118,-33.0828721903909511,45.2348755755691201],"rgb":[0.0666666666666666657,0.4,0],"xyz":[0.0498232429199692434,0.0962151868782235159,0.0159455671386054508],"hpluv":[126.180156646926719,191.399273993181851,37.1543973335168118],"hsluv":[126.180156646926719,100.000000000002359,37.1543973335168118]},"#116611":{"lch":[37.2288128297302237,53.6508389550451668,127.715012949240304],"luv":[37.2288128297302237,-32.820060550512963,42.4412081124095124],"rgb":[0.0666666666666666657,0.4,0.0666666666666666657],"xyz":[0.0508349084196063616,0.0966198530780783688,0.021273672103361084],"hpluv":[127.715012949240304,182.867554307566394,37.2288128297302237],"hsluv":[127.715012949240304,93.1121786917857719,37.2288128297302237]},"#116622":{"lch":[37.366211587350719,49.4912288674311,130.823584918521846],"luv":[37.366211587350719,-32.3540076461773722,37.4513006989015125],"rgb":[0.0666666666666666657,0.4,0.133333333333333331],"xyz":[0.0527102665580833837,0.0973699963334691831,0.0311505582993402766],"hpluv":[130.823584918521846,168.069340269208539,37.366211587350719],"hsluv":[130.823584918521846,93.2954788878505639,37.366211587350719]},"#116633":{"lch":[37.5909073580641291,43.4152735453156,136.786924005406348],"luv":[37.5909073580641291,-31.6415889136076061,29.7270218494359924],"rgb":[0.0666666666666666657,0.4,0.2],"xyz":[0.0557980172905411242,0.0986050966264523,0.0474127121569514198],"hpluv":[136.786924005406348,146.554466726503705,37.5909073580641291],"hsluv":[136.786924005406348,93.5769168130898095,37.5909073580641291]},"#116644":{"lch":[37.9120295698984506,36.3990668435195417,147.559563985674146],"luv":[37.9120295698984506,-30.7189764474867033,19.525279846848818],"rgb":[0.0666666666666666657,0.4,0.266666666666666663],"xyz":[0.0602560125347600048,0.100388294724139876,0.0708914871098380583],"hpluv":[147.559563985674146,121.829522477327146,37.9120295698984506],"hsluv":[147.559563985674146,93.9439470857740559,37.9120295698984506]},"#116655":{"lch":[38.335629212958338,30.5483862618043851,166.063087397862887],"luv":[38.335629212958338,-29.6490880228798659,7.35768187759708869],"rgb":[0.0666666666666666657,0.4,0.333333333333333315],"xyz":[0.066218426574122,0.102773260339884709,0.102293534383811974],"hpluv":[166.063087397862887,101.117192726530064,38.335629212958338],"hsluv":[166.063087397862887,94.3739252192313529,38.335629212958338]},"#116666":{"lch":[38.8651381017916293,29.1618890828208741,192.177050630061217],"luv":[38.8651381017916293,-28.5057600031098204,-6.15121301239451324],"rgb":[0.0666666666666666657,0.4,0.4],"xyz":[0.0738034223476301682,0.105807258649288027,0.142241178790955936],"hpluv":[192.177050630061217,95.2126746116157392,38.8651381017916293],"hsluv":[192.177050630061217,94.8399842705083245,38.8651381017916293]},"#116677":{"lch":[39.5016809883423079,34.1234106492309124,216.700227589977857],"luv":[39.5016809883423079,-27.3592385518708738,-20.3931169809293316],"rgb":[0.0666666666666666657,0.4,0.466666666666666674],"xyz":[0.0831174353678320876,0.109532863857368837,0.191294980697353845],"hpluv":[216.700227589977857,109.616563248578402,39.5016809883423079],"hsluv":[216.700227589977857,95.3164106037614687,39.5016809883423079]},"#116688":{"lch":[40.2443638992953723,43.6497103352843823,233.004065811630028],"luv":[40.2443638992953723,-26.2665776267255495,-34.862072688430807],"rgb":[0.0666666666666666657,0.4,0.533333333333333326],"xyz":[0.0942578524697759157,0.113989030698146435,0.249967844100926],"hpluv":[233.004065811630028,137.630797119362086,40.2443638992953723],"hsluv":[233.004065811630028,95.7822055324918864,40.2443638992953723]},"#116699":{"lch":[41.090575936542443,55.3002439505846866,242.81143298809],"luv":[41.090575936542443,-25.2678118474637223,-49.189985418125],"rgb":[0.0666666666666666657,0.4,0.6],"xyz":[0.107314816578848629,0.119211816341775592,0.318734521742043919],"hpluv":[242.81143298809,170.774941475023041,41.090575936542443],"hsluv":[242.81143298809,96.2225162944548202,41.090575936542443]},"#1166aa":{"lch":[42.0363074660961757,67.6887016451143,248.882871092507173],"luv":[42.0363074660961757,-24.3865946332867658,-63.1431257746482615],"rgb":[0.0666666666666666657,0.4,0.66666666666666663],"xyz":[0.122372509544101171,0.125234893527876701,0.39803837135904252],"hpluv":[248.882871092507173,204.329442679703192,42.0363074660961757],"hsluv":[248.882871092507173,96.6284204735347885,42.0363074660961757]},"#1166bb":{"lch":[43.0764730814379746,80.16050208662584,252.853006907061769],"luv":[43.0764730814379746,-23.6332520973097289,-76.5974901030376429],"rgb":[0.0666666666666666657,0.4,0.733333333333333282],"xyz":[0.139510101651437818,0.132089930370811459,0.488296356457684266],"hpluv":[252.853006907061769,236.134594524550181,43.0764730814379746],"hsluv":[252.853006907061769,96.9958197331145,43.0764730814379746]},"#1166cc":{"lch":[44.2052232400861271,92.4179309088515737,255.583916344807051],"luv":[44.2052232400861271,-23.008531750755072,-89.5079964033815259],"rgb":[0.0666666666666666657,0.4,0.8],"xyz":[0.158802477095159544,0.139806880548300261,0.589902867127954367],"hpluv":[255.583916344807051,265.290671800528912,44.2052232400861271],"hsluv":[255.583916344807051,97.3240770235992159,44.2052232400861271]},"#1166dd":{"lch":[45.4162296513266455,104.336857924373376,257.542523527564185],"luv":[45.4162296513266455,-22.507022318245486,-101.880390006599782],"rgb":[0.0666666666666666657,0.4,0.866666666666666696],"xyz":[0.180320802645793088,0.148414210768553795,0.703232715027960364],"hpluv":[257.542523527564185,291.518421142394175,45.4162296513266455],"hsluv":[257.542523527564185,97.6147741074162,45.4162296513266455]},"#1166ee":{"lch":[46.7029335650228674,115.880201424536907,258.995545526323895],"luv":[46.7029335650228674,-22.1198283610194721,-113.74943637429719],"rgb":[0.0666666666666666657,0.4,0.933333333333333348],"xyz":[0.204132982911967853,0.157939082875023812,0.828643531096483588],"hpluv":[258.995545526323895,314.850514307077333,46.7029335650228674],"hsluv":[258.995545526323895,97.870742288996567,46.7029335650228674]},"#1166ff":{"lch":[48.0587511138394348,127.054293237547355,260.103604495506659],"luv":[48.0587511138394348,-21.8364562757409573,-125.163743182322264],"rgb":[0.0666666666666666657,0.4,1],"xyz":[0.230304031321799219,0.168407502238956508,0.966477719388265433],"hpluv":[260.103604495506659,335.471932494038299,48.0587511138394348],"hsluv":[260.103604495506659,99.9999999999992184,48.0587511138394348]},"#66ff00":{"lch":[89.0839511722278417,127.467952451328657,122.755484474710229],"luv":[89.0839511722278417,-68.9671698198214074,107.198919720201],"rgb":[0.4,1,0],"xyz":[0.41237801270657426,0.74342166657477,0.121763233231621706],"hpluv":[122.755484474710229,522.717702913530729,89.0839511722278417],"hsluv":[122.755484474710229,100.000000000002402,89.0839511722278417]},"#66ff11":{"lch":[89.1030144718140917,126.693355761899767,122.944319876693868],"luv":[89.1030144718140917,-68.8988566751164342,106.320994836735167],"rgb":[0.4,1,0.0666666666666666657],"xyz":[0.413389678206211364,0.743826332774625,0.127091338196377329],"hpluv":[122.944319876693868,520.53129302948,89.1030144718140917],"hsluv":[122.944319876693868,99.9999999999913456,89.1030144718140917]},"#66ff22":{"lch":[89.1383344673707825,125.268361506965746,123.29878008449495],"luv":[89.1383344673707825,-68.7729595958538482,104.70168300016438],"rgb":[0.4,1,0.133333333333333331],"xyz":[0.415265036344688421,0.744576476030015755,0.136968224392356536],"hpluv":[123.29878008449495,516.49933125362179,89.1383344673707825],"hsluv":[123.29878008449495,99.9999999999914877,89.1383344673707825]},"#66ff33":{"lch":[89.1964366933732,122.952924407393425,123.895139690212403],"luv":[89.1964366933732,-68.5677350303770368,102.0582546055644],"rgb":[0.4,1,0.2],"xyz":[0.418352787077146127,0.745811576322998881,0.153230378249967686],"hpluv":[123.895139690212403,509.920932540516333,89.1964366933732],"hsluv":[123.895139690212403,99.9999999999913456,89.1964366933732]},"#66ff44":{"lch":[89.2802097655713,119.677402261160566,124.785058224819977],"luv":[89.2802097655713,-68.2758869475835439,98.2908127624369143],"rgb":[0.4,1,0.266666666666666663],"xyz":[0.422810782321365042,0.747594774420686448,0.176709153202854324],"hpluv":[124.785058224819977,500.557479589511445,89.2802097655713],"hsluv":[124.785058224819977,99.9999999999914451,89.2802097655713]},"#66ff55":{"lch":[89.392045372062455,115.420778437487911,126.031255758612545],"luv":[89.392045372062455,-67.8935601171189802,93.3403481337991536],"rgb":[0.4,1,0.333333333333333315],"xyz":[0.428773196360727,0.749979740036431197,0.20811120047682824],"hpluv":[126.031255758612545,488.288652672415253,89.392045372062455],"hsluv":[126.031255758612545,99.9999999999912177,89.392045372062455]},"#66ff66":{"lch":[89.5339732348528088,110.211236984550467,127.715012949239977],"luv":[89.5339732348528088,-67.4199983006921428,87.1840615410833664],"rgb":[0.4,1,0.4],"xyz":[0.436358192134235212,0.753013738345834516,0.248058844883972174],"hpluv":[127.715012949239977,473.1190638884799,89.5339732348528088],"hsluv":[127.715012949239977,99.9999999999912177,89.5339732348528088]},"#66ff77":{"lch":[89.7077333531255,104.130085615398272,129.945267186452298],"luv":[89.7077333531255,-66.8572982376138754,79.8321764869086223],"rgb":[0.4,1,0.466666666666666674],"xyz":[0.445672205154437118,0.756739343553915367,0.297112646790370083],"hpluv":[129.945267186452298,455.203211628206077,89.7077333531255],"hsluv":[129.945267186452298,99.9999999999911466,89.7077333531255]},"#66ff88":{"lch":[89.9148190538961529,97.3190386909276413,132.870301628739924],"luv":[89.9148190538961529,-66.2101394375234378,71.3246992800528687],"rgb":[0.4,1,0.533333333333333326],"xyz":[0.456812622256380918,0.761195510394692909,0.355785510193942278],"hpluv":[132.870301628739924,434.894743355908361,89.9148190538961529],"hsluv":[132.870301628739924,99.999999999990834,89.9148190538961529]},"#66ff99":{"lch":[90.1565046807361,89.9924560427222247,136.692010716646195],"luv":[90.1565046807361,-65.4854512845448795,61.7276098246221707],"rgb":[0.4,1,0.6],"xyz":[0.469869586365453618,0.766418296038322122,0.424552187835060157],"hpluv":[136.692010716646195,412.835114866532763,90.1565046807361],"hsluv":[136.692010716646195,99.9999999999909903,90.1565046807361]},"#66ffaa":{"lch":[90.4338646074596113,82.4570841698328678,141.679424663280656],"luv":[90.4338646074596113,-64.6920148236146,51.1284064669742264],"rgb":[0.4,1,0.66666666666666663],"xyz":[0.484927279330706174,0.772441373224423189,0.503856037452058758],"hpluv":[141.679424663280656,390.10709074414774,90.4338646074596113],"hsluv":[141.679424663280656,99.9999999999905924,90.4338646074596113]},"#66ffbb":{"lch":[90.747787175062669,75.1410408914244101,148.168460326052468],"luv":[90.747787175062669,-63.84001546278364,39.631155067172358],"rgb":[0.4,1,0.733333333333333282],"xyz":[0.502064871438042792,0.779296410067358,0.59411402255070056],"hpluv":[148.168460326052468,368.486167720556807,90.747787175062669],"hsluv":[148.168460326052468,99.9999999999904077,90.747787175062669]},"#66ffcc":{"lch":[91.0989856399247486,68.6265957122477,156.512275503644645],"luv":[91.0989856399247486,-62.9405723747737085,27.3513068826366492],"rgb":[0.4,1,0.8],"xyz":[0.521357246881764547,0.787013360244846805,0.695720533220970716],"hpluv":[156.512275503644645,350.804850059399143,91.0989856399247486],"hsluv":[156.512275503644645,99.9999999999903508,91.0989856399247486]},"#66ffdd":{"lch":[91.4880074096490716,63.6578272942329875,166.916209854529029],"luv":[91.4880074096490716,-62.0052733715472826,14.410588119229697],"rgb":[0.4,1,0.866666666666666696],"xyz":[0.542875572432398146,0.795620690465100311,0.809050381120976714],"hpluv":[166.916209854529029,341.336295176875581,91.4880074096490716],"hsluv":[166.916209854529029,99.9999999999898819,91.4880074096490716]},"#66ffee":{"lch":[91.9152423718395113,61.0528599966611765,179.125088100836763],"luv":[91.9152423718395113,-61.045742111776633,0.93224663816584552],"rgb":[0.4,1,0.933333333333333348],"xyz":[0.566687752698572855,0.805145562571570328,0.934461197189499937],"hpluv":[179.125088100836763,345.840646438583576,91.9152423718395113],"hsluv":[179.125088100836763,99.9999999999894,91.9152423718395113]},"#66ffff":{"lch":[92.3809308294128,61.4559907165056,192.17705063006116],"luv":[92.3809308294128,-60.0732592166006256,-12.9631139022354667],"rgb":[0.4,1,1],"xyz":[0.592858801108404276,0.815613981935503,1.07229538548128178],"hpluv":[192.17705063006116,370.76546272919029,92.3809308294128],"hsluv":[192.17705063006116,99.9999999999889866,92.3809308294128]},"#117700":{"lch":[43.2300348418233042,65.6725964696673685,126.613348243544976],"luv":[43.2300348418233042,-39.1679175007181684,52.7139845365981],"rgb":[0.0666666666666666657,0.466666666666666674,0],"xyz":[0.0682769809733868721,0.133122662985059287,0.0220968131564111547],"hpluv":[126.613348243544976,192.769325646383436,43.2300348418233042],"hsluv":[126.613348243544976,100.000000000002359,43.2300348418233042]},"#117711":{"lch":[43.289989941732955,63.6505577690815443,127.715012949240403],"luv":[43.289989941732955,-38.9372319378938414,50.351618378457772],"rgb":[0.0666666666666666657,0.466666666666666674,0.0666666666666666657],"xyz":[0.0692886464730239904,0.13352732918491414,0.0274249181211667845],"hpluv":[127.715012949240403,186.57525992916959,43.289989941732955],"hsluv":[127.715012949240403,95.0000616991484321,43.289989941732955]},"#117722":{"lch":[43.400811094951429,60.069144786817489,129.889765673233825],"luv":[43.400811094951429,-38.5230987158151308,46.089836414888758],"rgb":[0.0666666666666666657,0.466666666666666674,0.133333333333333331],"xyz":[0.0711640046115010194,0.134277472440304968,0.037301804317145984],"hpluv":[129.889765673233825,175.627665872500842,43.400811094951429],"hsluv":[129.889765673233825,95.0973605906006725,43.400811094951429]},"#117733":{"lch":[43.5823807888255317,54.6433249694405205,133.881596062605809],"luv":[43.5823807888255317,-37.8771324094584756,39.3854770715327476],"rgb":[0.0666666666666666657,0.466666666666666674,0.2],"xyz":[0.074251755343958753,0.135512572733288067,0.0535639581747571272],"hpluv":[133.881596062605809,159.098283206795713,43.5823807888255317],"hsluv":[133.881596062605809,95.249567515942033,43.5823807888255317]},"#117744":{"lch":[43.8425891980029,47.8554364611196803,140.669149905405504],"luv":[43.8425891980029,-37.0161352468332083,30.3306533110056051],"rgb":[0.0666666666666666657,0.466666666666666674,0.266666666666666663],"xyz":[0.0787097505881776266,0.137295770830975661,0.0770427331276437588],"hpluv":[140.669149905405504,138.507858249946878,43.8425891980029],"hsluv":[140.669149905405504,95.4533619015585373,43.8425891980029]},"#117755":{"lch":[44.18711059062651,40.7988283335817243,151.872601466806259],"luv":[44.18711059062651,-35.9805491223838843,19.2339407882209947],"rgb":[0.0666666666666666657,0.466666666666666674,0.333333333333333315],"xyz":[0.0846721646275396256,0.139680736446720494,0.108444780401617674],"hpluv":[151.872601466806259,117.163251003272293,44.18711059062651],"hsluv":[151.872601466806259,95.7000805167539426,44.18711059062651]},"#117766":{"lch":[44.6197667240920879,35.4343089397309186,169.362936023125116],"luv":[44.6197667240920879,-34.8254110013137463,6.54071850990925796],"rgb":[0.0666666666666666657,0.466666666666666674,0.4],"xyz":[0.0922571604010478,0.142714734756123784,0.148392424808761636],"hpluv":[169.362936023125116,100.771099800457392,44.6197667240920879],"hsluv":[169.362936023125116,95.9777414193434453,44.6197667240920879]},"#117777":{"lch":[45.1427402486772138,34.384087641882445,192.177050630061217],"luv":[45.1427402486772138,-33.6104614986274584,-7.25274850066749],"rgb":[0.0666666666666666657,0.466666666666666674,0.466666666666666674],"xyz":[0.101571173421249716,0.146440339964204608,0.197446226715159545],"hpluv":[192.177050630061217,96.651570122263351,45.1427402486772138],"hsluv":[192.177050630061217,96.2732475219964385,45.1427402486772138]},"#117788":{"lch":[45.7567431438856502,38.9735922704815891,213.78628123605418],"luv":[45.7567431438856502,-32.3916401681270685,-21.6730833451154119],"rgb":[0.0666666666666666657,0.466666666666666674,0.533333333333333326],"xyz":[0.112711590523193544,0.150896506804982206,0.256119090118731685],"hpluv":[213.78628123605418,108.082320192335175,45.7567431438856502],"hsluv":[213.78628123605418,96.5742797371803192,45.7567431438856502]},"#117799":{"lch":[46.4611794427891169,47.8902134896154763,229.321579893426758],"luv":[46.4611794427891169,-31.2154548044213769,-36.3189747850083791],"rgb":[0.0666666666666666657,0.466666666666666674,0.6],"xyz":[0.125768554632266272,0.156119292448611363,0.32488576775984962],"hpluv":[229.321579893426758,130.796423620493698,46.4611794427891169],"hsluv":[229.321579893426758,96.8705519561321,46.4611794427891169]},"#1177aa":{"lch":[47.254315604307827,59.1280670765604199,239.379878554404911],"luv":[47.254315604307827,-30.1165063567495856,-50.8834389666627231],"rgb":[0.0666666666666666657,0.466666666666666674,0.66666666666666663],"xyz":[0.1408262475975188,0.162142369634712458,0.40418961737684822],"hpluv":[239.379878554404911,158.77844008322549,47.254315604307827],"hsluv":[239.379878554404911,97.1543662497403488,47.254315604307827]},"#1177bb":{"lch":[48.1334597651774914,71.3648635001192133,245.920143546346225],"luv":[48.1334597651774914,-29.1175429122131746,-65.1545273725937761],"rgb":[0.0666666666666666657,0.466666666666666674,0.733333333333333282],"xyz":[0.157963839704855447,0.168997406477647216,0.494447602475489967],"hpluv":[245.920143546346225,188.138070935962588,48.1334597651774914],"hsluv":[245.920143546346225,97.4206074841270464,48.1334597651774914]},"#1177cc":{"lch":[49.0951452720171488,83.8954152066927463,250.336037436893122],"luv":[49.0951452720171488,-28.2310616920000612,-79.0028344329863756],"rgb":[0.0666666666666666657,0.466666666666666674,0.8],"xyz":[0.177256215148577201,0.176714356655136018,0.596054113145760178],"hpluv":[250.336037436893122,216.83980339157776,49.0951452720171488],"hsluv":[250.336037436893122,97.666394869173061,49.0951452720171488]},"#1177dd":{"lch":[50.1353116048344702,96.3594544857749,253.441700788778064],"luv":[50.1353116048344702,-27.4615589113116805,-92.3634519220491512],"rgb":[0.0666666666666666657,0.466666666666666674,0.866666666666666696],"xyz":[0.198774540699210744,0.185321686875389552,0.709383961045766176],"hpluv":[253.441700788778064,243.887723915279508,50.1353116048344702],"hsluv":[253.441700788778064,97.8905898818146341,50.1353116048344702]},"#1177ee":{"lch":[51.2494756916451593,108.579054392530807,255.706052301270915],"luv":[51.2494756916451593,-26.8078049752198453,-105.217644172385562],"rgb":[0.0666666666666666657,0.466666666666666674,0.933333333333333348],"xyz":[0.222586720965385454,0.194846558981859597,0.834794777114289399],"hpluv":[255.706052301270915,268.841280267375566,51.2494756916451593],"hsluv":[255.706052301270915,98.0932983984315,51.2494756916451593]},"#1177ff":{"lch":[52.4328877873246739,120.474912105814852,257.407785454377859],"luv":[52.4328877873246739,-26.2648114927385947,-117.577056112809359],"rgb":[0.0666666666666666657,0.466666666666666674,1],"xyz":[0.248757769375216875,0.205314978345792293,0.972628965406071133],"hpluv":[257.407785454377859,291.562836812545811,52.4328877873246739],"hsluv":[257.407785454377859,99.9999999999990905,52.4328877873246739]},"#118800":{"lch":[49.1629818744817157,75.0325981068150725,126.891404302910644],"luv":[49.1629818744817157,-45.0420871994947447,60.0091756264985],"rgb":[0.0666666666666666657,0.533333333333333326,0],"xyz":[0.0903493506983573252,0.177267402435000831,0.0294542697314011],"hpluv":[126.891404302910644,193.664979881129256,49.1629818744817157],"hsluv":[126.891404302910644,100.000000000002487,49.1629818744817157]},"#118811":{"lch":[49.2125288978643,73.2988946552939211,127.715012949240403],"luv":[49.2125288978643,-44.8394509336223663,57.9840633075946883],"rgb":[0.0666666666666666657,0.533333333333333326,0.0666666666666666657],"xyz":[0.0913610161979944435,0.177672068634855684,0.0347823746961567343],"hpluv":[127.715012949240403,188.999680167490567,49.2125288978643],"hsluv":[127.715012949240403,96.2345237189928326,49.2125288978643]},"#118822":{"lch":[49.3041772439320312,70.1927728141533,129.31476933948187],"luv":[49.3041772439320312,-44.4727599639014315,54.3065279366352556],"rgb":[0.0666666666666666657,0.533333333333333326,0.133333333333333331],"xyz":[0.0932363743364714725,0.178422211890246513,0.0446592608921359269],"hpluv":[129.31476933948187,180.6541776618526,49.3041772439320312],"hsluv":[129.31476933948187,96.2899748067816859,49.3041772439320312]},"#118833":{"lch":[49.454516912369769,65.3819990709954766,132.170105234646456],"luv":[49.454516912369769,-43.8931572746598917,48.4581938064309767],"rgb":[0.0666666666666666657,0.533333333333333326,0.2],"xyz":[0.0963241250689292,0.179657312183229612,0.060921414749747077],"hpluv":[132.170105234646456,167.761213036429979,49.454516912369769],"hsluv":[132.170105234646456,96.3778002926358,49.454516912369769]},"#118844":{"lch":[49.6703617695526,59.1036258375550787,136.829676092870073],"luv":[49.6703617695526,-43.1056388924535057,40.4368950689726887],"rgb":[0.0666666666666666657,0.533333333333333326,0.266666666666666663],"xyz":[0.10078212031314808,0.181440510280917205,0.0844001897026337156],"hpluv":[136.829676092870073,150.9927614306973,49.6703617695526],"hsluv":[136.829676092870073,96.4975069627829356,49.6703617695526]},"#118855":{"lch":[49.9568473676091145,51.9652717779864091,144.176427678513875],"luv":[49.9568473676091145,-42.1346422468413806,30.4148219408018328],"rgb":[0.0666666666666666657,0.533333333333333326,0.333333333333333315],"xyz":[0.106744534352510079,0.183825475896662038,0.115802236976607617],"hpluv":[144.176427678513875,131.995007799011802,49.9568473676091145],"hsluv":[144.176427678513875,96.6457662191899658,49.9568473676091145]},"#118866":{"lch":[50.3177367885428879,45.0776565581224133,155.49998607369966],"luv":[50.3177367885428879,-41.0189171061503615,18.6934095394821433],"rgb":[0.0666666666666666657,0.533333333333333326,0.4],"xyz":[0.11432953012601825,0.186859474206065329,0.155749881383751593],"hpluv":[155.49998607369966,113.67882025976219,50.3177367885428879],"hsluv":[155.49998607369966,96.8171590628882512,50.3177367885428879]},"#118877":{"lch":[50.7555873970602391,40.2042284802375036,171.921706717236162],"luv":[50.7555873970602391,-39.8052806191025255,5.64974535051283322],"rgb":[0.0666666666666666657,0.533333333333333326,0.466666666666666674],"xyz":[0.12364354314622017,0.190585079414146152,0.204803683290149502],"hpluv":[171.921706717236162,100.514149141729121,50.7555873970602391],"hsluv":[171.921706717236162,97.0050762990714333,50.7555873970602391]},"#118888":{"lch":[51.2718664023781088,39.4294820301430349,192.17705063006116],"luv":[51.2718664023781088,-38.5423368357954814,-8.3169901046866368],"rgb":[0.0666666666666666657,0.533333333333333326,0.533333333333333326],"xyz":[0.134783960248164,0.19504124625492375,0.263476546693721669],"hpluv":[192.17705063006116,97.5845966821491118,51.2718664023781088],"hsluv":[192.17705063006116,97.2026219422035,51.2718664023781088]},"#118899":{"lch":[51.8670503792929907,43.7110075029310678,211.486174513119295],"luv":[51.8670503792929907,-37.2752705782940623,-22.8299448145688864],"rgb":[0.0666666666666666657,0.533333333333333326,0.6],"xyz":[0.147840924357236725,0.200264031898552908,0.332243224334839549],"hpluv":[211.486174513119295,106.93960912970239,51.8670503792929907],"hsluv":[211.486174513119295,97.4033619208845,51.8670503792929907]},"#1188aa":{"lch":[52.5407237145479371,52.059033028958666,226.184651315961702],"luv":[52.5407237145479371,-36.0423686073764102,-37.5644856890150507],"rgb":[0.0666666666666666657,0.533333333333333326,0.66666666666666663],"xyz":[0.162898617322489253,0.206287109084654,0.411547073951838149],"hpluv":[226.184651315961702,125.730132415512543,52.5407237145479371],"hsluv":[226.184651315961702,97.6018250350267,52.5407237145479371]},"#1188bb":{"lch":[53.2916815113449047,62.8295543710454396,236.286042109927791],"luv":[53.2916815113449047,-34.8733609598062557,-52.2628127623381573],"rgb":[0.0666666666666666657,0.533333333333333326,0.733333333333333282],"xyz":[0.1800362094298259,0.213142145927588761,0.501805059050479896],"hpluv":[236.286042109927791,149.604233097343041,53.2916815113449047],"hsluv":[236.286042109927791,97.7937430875757201,53.2916815113449047]},"#1188cc":{"lch":[54.1180375597057548,74.8024459991104607,243.146336149822275],"luv":[54.1180375597057548,-33.7892633498457826,-66.735984369188742],"rgb":[0.0666666666666666657,0.533333333333333326,0.8],"xyz":[0.199328584873547654,0.220859096105077563,0.60341156972075],"hpluv":[243.146336149822275,175.393335022858878,54.1180375597057548],"hsluv":[243.146336149822275,97.9760759990174819,54.1180375597057548]},"#1188dd":{"lch":[55.0173353812408266,87.2581949437380331,247.918019831454984],"luv":[55.0173353812408266,-32.8032215872693484,-80.8575366823396138],"rgb":[0.0666666666666666657,0.533333333333333326,0.866666666666666696],"xyz":[0.220846910424181198,0.229466426325331097,0.716741417620756],"hpluv":[247.918019831454984,201.254684785248685,55.0173353812408266],"hsluv":[247.918019831454984,98.1468934162311513,55.0173353812408266]},"#1188ee":{"lch":[55.9866591638471363,99.7959623087877645,251.344854654704591],"luv":[55.9866591638471363,-31.921869990719685,-94.5527805483930734],"rgb":[0.0666666666666666657,0.533333333333333326,0.933333333333333348],"xyz":[0.244659090690355907,0.238991298431801141,0.842152233689279273],"hpluv":[251.344854654704591,226.187053837960264,55.9866591638471363],"hsluv":[251.344854654704591,98.3051827042817,55.9866591638471363]},"#1188ff":{"lch":[57.0227411270994082,112.196885547184024,253.882464988485651],"luv":[57.0227411270994082,-31.1468293758358783,-107.786901552649141],"rgb":[0.0666666666666666657,0.533333333333333326,1],"xyz":[0.270830139100187328,0.249459717795733837,0.979986421981061118],"hpluv":[253.882464988485651,249.673263359937977,57.0227411270994082],"hsluv":[253.882464988485651,99.9999999999988916,57.0227411270994082]},"#119900":{"lch":[54.9698669410824721,84.160615619067471,127.079428544988929],"luv":[54.9698669410824721,-50.7422517332937772,67.1433772639973],"rgb":[0.0666666666666666657,0.6,0],"xyz":[0.116218951150824812,0.229006603339936526,0.0380774698822233526],"hpluv":[127.079428544988929,194.277964405092661,54.9698669410824721],"hsluv":[127.079428544988929,100.000000000002373,54.9698669410824721]},"#119911":{"lch":[55.0116447857556494,82.6558224500047,127.715012949240403],"luv":[55.0116447857556494,-50.563404981135136,65.3859852078442],"rgb":[0.0666666666666666657,0.6,0.0666666666666666657],"xyz":[0.11723061665046193,0.229411269539791379,0.0434055748469789823],"hpluv":[127.715012949240403,190.659367551848248,55.0116447857556494],"hsluv":[127.715012949240403,97.0796004133795094,55.0116447857556494]},"#119922":{"lch":[55.0889600096002852,79.9388272851777657,128.936266554168185],"luv":[55.0889600096002852,-50.237998627918941,62.1800579091938204],"rgb":[0.0666666666666666657,0.6,0.133333333333333331],"xyz":[0.119105974788938959,0.230161412795182208,0.0532824610429581819],"hpluv":[128.936266554168185,184.133380166819137,55.0889600096002852],"hsluv":[128.936266554168185,97.113065541928691,55.0889600096002852]},"#119933":{"lch":[55.215893256771821,75.6695179958245916,131.075562701176153],"luv":[55.215893256771821,-49.7189430335536,57.0429895547794175],"rgb":[0.0666666666666666657,0.6,0.2],"xyz":[0.122193725521396693,0.231396513088165307,0.0695446149005693182],"hpluv":[131.075562701176153,173.898642472918851,55.215893256771821],"hsluv":[131.075562701176153,97.1665253707361,55.215893256771821]},"#119944":{"lch":[55.398361036949,69.9528706873860671,134.469703140623466],"luv":[55.398361036949,-49.0042253731102591,49.9198358669935303],"rgb":[0.0666666666666666657,0.6,0.266666666666666663],"xyz":[0.126651720765615566,0.2331797111858529,0.0930233898534559567],"hpluv":[134.469703140623466,160.231519707698453,55.398361036949],"hsluv":[134.469703140623466,97.2403070889690184,55.398361036949]},"#119955":{"lch":[55.6409569880907497,63.1400511875114887,139.633471194580181],"luv":[55.6409569880907497,-48.1074656204671172,40.8942271664002206],"rgb":[0.0666666666666666657,0.6,0.333333333333333315],"xyz":[0.132614134804977579,0.235564676801597733,0.124425437127429872],"hpluv":[139.633471194580181,143.995747016857166,55.6409569880907497],"hsluv":[139.633471194580181,97.3331834328701575,55.6409569880907497]},"#119966":{"lch":[55.9472168173363,55.8918514512489466,147.340496807064056],"luv":[55.9472168173363,-47.0549257965888,30.1617807320125095],"rgb":[0.0666666666666666657,0.6,0.4],"xyz":[0.140199130578485737,0.238598675111001024,0.164373081534573834],"hpluv":[147.340496807064056,126.76791164907155,55.9472168173363],"hsluv":[147.340496807064056,97.4426708460479,55.9472168173363]},"#119977":{"lch":[56.319758368673476,49.2851425936320169,158.582299284916047],"luv":[56.319758368673476,-45.8816608646539308,17.9971796894826],"rgb":[0.0666666666666666657,0.6,0.466666666666666674],"xyz":[0.14951314359868767,0.242324280319081847,0.213426883440971743],"hpluv":[158.582299284916047,111.043862853999471,56.319758368673476],"hsluv":[158.582299284916047,97.5654087237770398,56.319758368673476]},"#119988":{"lch":[56.7603710001512951,44.8759084930006864,173.96527373508107],"luv":[56.7603710001512951,-44.6272223318454451,4.71785862613608131],"rgb":[0.0666666666666666657,0.6,0.533333333333333326],"xyz":[0.16065356070063147,0.246780447159859445,0.27209974684454391],"hpluv":[173.96527373508107,100.324581054675164,56.7603710001512951],"hsluv":[173.96527373508107,97.6975811674153647,56.7603710001512951]},"#119999":{"lch":[57.2700846473106822,44.3289506401906692,192.177050630061103],"luv":[57.2700846473106822,-43.3315696575835219,-9.35045110518458422],"rgb":[0.0666666666666666657,0.6,0.6],"xyz":[0.173710524809704198,0.252003232803488575,0.340866424485661845],"hpluv":[192.177050630061103,98.2197789195824384,57.2700846473106822],"hsluv":[192.177050630061103,97.8353178900151903,57.2700846473106822]},"#1199aa":{"lch":[57.849232550626823,48.3524707931101716,209.625127722111756],"luv":[57.849232550626823,-42.0317498411296384,-23.9017454821038378],"rgb":[0.0666666666666666657,0.6,0.66666666666666663],"xyz":[0.188768217774956726,0.258026309989589697,0.42017027410266039],"hpluv":[209.625127722111756,106.062142541807418,57.849232550626823],"hsluv":[209.625127722111756,97.9750198241805492,57.849232550626823]},"#1199bb":{"lch":[58.4975141278551263,56.1838887208170235,223.492153209811363],"luv":[58.4975141278551263,-40.7596491137071553,-38.6688551152037832],"rgb":[0.0666666666666666657,0.6,0.733333333333333282],"xyz":[0.2059058098822934,0.264881346832524456,0.510428259201302192],"hpluv":[223.492153209811363,121.8747424026255,58.4975141278551263],"hsluv":[223.492153209811363,98.1135798876595686,58.4975141278551263]},"#1199cc":{"lch":[59.2140605434028515,66.4726101728698211,233.498474693243395],"luv":[59.2140605434028515,-39.5408457239066138,-53.4334111079625274],"rgb":[0.0666666666666666657,0.6,0.8],"xyz":[0.225198185326015127,0.272598297010013257,0.612034769871572348],"hpluv":[233.498474693243395,142.448281943894045,59.2140605434028515],"hsluv":[233.498474693243395,98.2484961488154482,59.2140605434028515]},"#1199dd":{"lch":[59.9975033067865553,78.1149919905427907,240.560044488236258],"luv":[59.9975033067865553,-38.3943918665613637,-68.0281018909060151],"rgb":[0.0666666666666666657,0.6,0.866666666666666696],"xyz":[0.24671651087664867,0.281205627230266819,0.725364617771578346],"hpluv":[240.560044488236258,165.211601361935521,59.9975033067865553],"hsluv":[240.560044488236258,98.3778942246892285,59.9975033067865553]},"#1199ee":{"lch":[60.8460449735814706,90.4022578402124,245.60857134482],"luv":[60.8460449735814706,-37.3332566635070862,-82.3334450239084106],"rgb":[0.0666666666666666657,0.6,0.933333333333333348],"xyz":[0.270528691142823408,0.290730499336736836,0.850775433840101569],"hpluv":[245.60857134482,188.532510112076068,60.8460449735814706],"hsluv":[245.60857134482,98.5004851129029788,60.8460449735814706]},"#1199ff":{"lch":[61.7575303771721877,102.910627792409826,249.306643617498082],"luv":[61.7575303771721877,-36.3651553748586,-96.2713497733895167],"rgb":[0.0666666666666666657,0.6,1],"xyz":[0.296699739552654829,0.301198918700669505,0.988609622131883414],"hpluv":[249.306643617498082,211.450946466820028,61.7575303771721877],"hsluv":[249.306643617498082,99.9999999999986215,61.7575303771721877]},"#000000":{"lch":[0,0,0],"luv":[0,0,0],"rgb":[0,0,0],"xyz":[0,0,0],"hpluv":[0,0,0],"hsluv":[0,0,0]},"#000011":{"lch":[0.365533479526218952,1.47895322486610792,265.8743202181779],"luv":[0.365533479526218952,-0.106402530834795422,-1.47512072142377915],"rgb":[0,0,0.0666666666666666657],"xyz":[0.00101166549963712174,0.000404666199854854377,0.00532810496475563146],"hpluv":[265.8743202181779,513.41269684428039,0.365533479526218952],"hsluv":[265.8743202181779,100.000000000000867,0.365533479526218952]},"#000022":{"lch":[1.04313510374015572,4.22053823263236,265.8743202181779],"luv":[1.04313510374015572,-0.303644457367982512,-4.20960128950726],"rgb":[0,0,0.133333333333333331],"xyz":[0.0028870236381141408,0.00115480945524567245,0.0152049911607348275],"hpluv":[265.8743202181779,513.41269684428039,1.04313510374015572],"hsluv":[265.8743202181779,100.000000000000838,1.04313510374015572]},"#000033":{"lch":[2.15879662382733661,8.73451929157831,265.8743202181779],"luv":[2.15879662382733661,-0.62840050829424543,-8.71188498868810868],"rgb":[0,0,0.2],"xyz":[0.00597477437057188088,0.00238990974822878574,0.0314671450183459725],"hpluv":[265.8743202181779,513.412696844280276,2.15879662382733661],"hsluv":[265.8743202181779,100.000000000000838,2.15879662382733661]},"#000044":{"lch":[3.76955286085941,15.251660031516769,265.874320218177957],"luv":[3.76955286085941,-1.0972728545435857,-15.2121374566379668],"rgb":[0,0,0.266666666666666663],"xyz":[0.0104327696147907597,0.00417310784591636182,0.054945919971232611],"hpluv":[265.874320218177957,513.41269684428039,3.76955286085941],"hsluv":[265.874320218177957,100.000000000000981,3.76955286085941]},"#000055":{"lch":[5.92388346812606947,23.9681097618519345,265.8743202181779],"luv":[5.92388346812606947,-1.7243733575266309,-23.905999708860417],"rgb":[0,0,0.333333333333333315],"xyz":[0.0163951836541527535,0.00655807346166119385,0.0863479672452065194],"hpluv":[265.8743202181779,513.41269684428039,5.92388346812606947],"hsluv":[265.8743202181779,100.000000000000838,5.92388346812606947]},"#000066":{"lch":[8.64689012997685,34.9854302247980513,265.8743202181779],"luv":[8.64689012997685,-2.51700882467034193,-34.8947703043127149],"rgb":[0,0,0.4],"xyz":[0.0239801794276609283,0.00959207177106450627,0.126295611652350481],"hpluv":[265.8743202181779,513.412696844280276,8.64689012997685],"hsluv":[265.8743202181779,100.000000000000838,8.64689012997685]},"#000077":{"lch":[11.4958709948623863,46.5124439559768703,265.874320218177957],"luv":[11.4958709948623863,-3.34631391244679577,-46.3919133681426672],"rgb":[0,0,0.466666666666666674],"xyz":[0.0332941924478628443,0.0133176769791453226,0.17534941355874839],"hpluv":[265.874320218177957,513.412696844280276,11.4958709948623863],"hsluv":[265.874320218177957,100.000000000001,11.4958709948623863]},"#000088":{"lch":[14.2727431262745554,57.7477048111956535,265.874320218177957],"luv":[14.2727431262745554,-4.15462898927595781,-57.598059593379169],"rgb":[0,0,0.533333333333333326],"xyz":[0.0444346095498066723,0.0177738438199229153,0.234022276962320558],"hpluv":[265.874320218177957,513.41269684428039,14.2727431262745554],"hsluv":[265.874320218177957,100.000000000000952,14.2727431262745554]},"#000099":{"lch":[16.9872454361813823,68.7306165552763701,265.874320218177957],"luv":[16.9872454361813823,-4.94478893879780923,-68.5525106354185567],"rgb":[0,0,0.6],"xyz":[0.0574915736588793858,0.0229966294635520763,0.302788954603438465],"hpluv":[265.874320218177957,513.412696844280163,16.9872454361813823],"hsluv":[265.874320218177957,100.000000000000952,16.9872454361813823]},"#0000aa":{"lch":[19.6469460262523299,79.4917998262647529,265.8743202181779],"luv":[19.6469460262523299,-5.71899674710351302,-79.2858077831434116],"rgb":[0,0,0.66666666666666663],"xyz":[0.0725492666241319278,0.0290197066496531778,0.382092804220437066],"hpluv":[265.8743202181779,513.41269684428039,19.6469460262523299],"hsluv":[265.8743202181779,100.000000000000824,19.6469460262523299]},"#0000bb":{"lch":[22.2578820656552736,90.0556810893410926,265.8743202181779],"luv":[22.2578820656552736,-6.47900976369593895,-89.8223142039161644],"rgb":[0,0,0.733333333333333282],"xyz":[0.0896868587314685745,0.0358747434925879363,0.472350789319078812],"hpluv":[265.8743202181779,513.41269684428039,22.2578820656552736],"hsluv":[265.8743202181779,100.000000000000796,22.2578820656552736]},"#0000cc":{"lch":[24.8249727536546274,100.442163488877583,265.874320218177957],"luv":[24.8249727536546274,-7.22625991008361535,-100.18188146585355],"rgb":[0,0,0.8],"xyz":[0.108979234175190315,0.043591693670076738,0.573957299989349],"hpluv":[265.874320218177957,513.41269684428039,24.8249727536546274],"hsluv":[265.874320218177957,100.000000000001,24.8249727536546274]},"#0000dd":{"lch":[27.3522973211786535,110.667751646404724,265.8743202181779],"luv":[27.3522973211786535,-7.96193460279319343,-110.380971421034161],"rgb":[0,0,0.866666666666666696],"xyz":[0.130497559725823858,0.052199023890330272,0.687287147889355],"hpluv":[265.8743202181779,513.412696844280276,27.3522973211786535],"hsluv":[265.8743202181779,100.000000000000824,27.3522973211786535]},"#0000ee":{"lch":[29.8432887766479737,120.746335558760222,265.8743202181779],"luv":[29.8432887766479737,-8.68703315051946,-120.433438072283309],"rgb":[0,0,0.933333333333333348],"xyz":[0.154309739991998596,0.0617238959968003,0.812697963957878189],"hpluv":[265.8743202181779,513.41269684428039,29.8432887766479737],"hsluv":[265.8743202181779,100.000000000000838,29.8432887766479737]},"#0000ff":{"lch":[32.3008729039800215,130.68975298582734,265.8743202181779],"luv":[32.3008729039800215,-9.40240721482262,-130.351088503561101],"rgb":[0,0,1],"xyz":[0.18048078840183,0.072192315360733,0.95053215224966],"hpluv":[265.8743202181779,513.41269684428039,32.3008729039800215],"hsluv":[265.8743202181779,100.000000000000824,32.3008729039800215]},"#001100":{"lch":[3.62113466359794112,5.60448249758782424,127.715012949240474],"luv":[3.62113466359794112,-3.42845440085753106,4.43350025228474376],"rgb":[0,0.0666666666666666657,0],"xyz":[0.00200440026092840902,0.00400880052185687355,0.00066813342030945088],"hpluv":[127.715012949240474,196.394882900214469,3.62113466359794112],"hsluv":[127.715012949240474,100.000000000002217,3.62113466359794112]},"#001111":{"lch":[3.9866681431241604,3.15408977882195618,192.17705063006116],"luv":[3.9866681431241604,-3.08312421078118115,-0.665302512969894178],"rgb":[0,0.0666666666666666657,0.0666666666666666657],"xyz":[0.00301606576056553076,0.00441346672171172814,0.00599623838506508234],"hpluv":[192.17705063006116,100.392967527320764,3.9866681431241604],"hsluv":[192.17705063006116,99.9999999999914,3.9866681431241604]},"#001122":{"lch":[4.66426976733809706,7.30142401028103372,246.87889630792742],"luv":[4.66426976733809706,-2.86709314837997242,-6.71495118794031054],"rgb":[0,0.0666666666666666657,0.133333333333333331],"xyz":[0.00489142389904254939,0.005163609977102546,0.0158731245810442775],"hpluv":[246.87889630792742,198.638412351210178,4.66426976733809706],"hsluv":[246.87889630792742,99.9999999999921414,4.66426976733809706]},"#001133":{"lch":[5.77993128742527773,13.8979406242137369,257.974087263939282],"luv":[5.77993128742527773,-2.89569220292521434,-13.5929290537429299],"rgb":[0,0.0666666666666666657,0.2],"xyz":[0.00797917463150029,0.00639871027008565886,0.0321352784386554208],"hpluv":[257.974087263939282,305.117489912579458,5.77993128742527773],"hsluv":[257.974087263939282,99.9999999999925,5.77993128742527773]},"#001144":{"lch":[7.39068752445735111,21.802452480470059,261.611708702028636],"luv":[7.39068752445735111,-3.1805605696034065,-21.569213444774455],"rgb":[0,0.0666666666666666657,0.266666666666666663],"xyz":[0.0124371698757191687,0.00818190836777323537,0.0556140533915420593],"hpluv":[261.611708702028636,374.334482048802613,7.39068752445735111],"hsluv":[261.611708702028636,99.9999999999929656,7.39068752445735111]},"#001155":{"lch":[9.4550232844459714,31.0886305445366773,263.238579866128873],"luv":[9.4550232844459714,-3.6602302532303379,-30.8724094237562916],"rgb":[0,0.0666666666666666657,0.333333333333333315],"xyz":[0.0183995839150811608,0.0105668739835180665,0.0870161006655159747],"hpluv":[263.238579866128873,417.232678203522596,9.4550232844459714],"hsluv":[263.238579866128873,99.9999999999929514,9.4550232844459714]},"#001166":{"lch":[11.6894020192987682,40.9340765206813302,264.100423242359113],"luv":[11.6894020192987682,-4.20741678933990659,-40.7172723123955791],"rgb":[0,0.0666666666666666657,0.4],"xyz":[0.025984579688589339,0.0136008722929213798,0.126963745072659923],"hpluv":[264.100423242359113,444.357002567308371,11.6894020192987682],"hsluv":[264.100423242359113,99.9999999999928235,11.6894020192987682]},"#001177":{"lch":[14.0165943101603965,51.0460922578313898,264.608714664977526],"luv":[14.0165943101603965,-4.79613195559092276,-50.8202779710972621],"rgb":[0,0.0666666666666666657,0.466666666666666674],"xyz":[0.0352985927087912515,0.0173264775010021979,0.176017546979057832],"hpluv":[264.608714664977526,462.124851551559573,14.0165943101603965],"hsluv":[264.608714664977526,99.9999999999931504,14.0165943101603965]},"#001188":{"lch":[16.3962585295353378,61.2721603523949625,264.931782730652174],"luv":[16.3962585295353378,-5.41289085195630371,-61.0325998698597871],"rgb":[0,0.0666666666666666657,0.533333333333333326],"xyz":[0.0464390098107350796,0.0217826443417797888,0.23469041038263],"hpluv":[264.931782730652174,474.195864485329537,16.3962585295353378],"hsluv":[264.931782730652174,99.9999999999933209,16.3962585295353378]},"#001199":{"lch":[18.8023327262484941,71.5200065602600148,265.148843888859801],"luv":[18.8023327262484941,-6.04826966448705239,-71.2638040834565771],"rgb":[0,0.0666666666666666657,0.6],"xyz":[0.059495973919807793,0.0270054299854089498,0.303457088023747934],"hpluv":[265.148843888859801,482.675370310212884,18.8023327262484941],"hsluv":[265.148843888859801,99.9999999999930651,18.8023327262484941]},"#0011aa":{"lch":[21.2181090603332123,81.7349311996174919,265.301088447161305],"luv":[21.2181090603332123,-6.69569086805443892,-81.4602154551880488],"rgb":[0,0.0666666666666666657,0.66666666666666663],"xyz":[0.0745536668850603351,0.0330285071715100548,0.382760937640746535],"hpluv":[265.301088447161305,488.81030222212587,21.2181090603332123],"hsluv":[265.301088447161305,99.9999999999931788,21.2181090603332123]},"#0011bb":{"lch":[23.6329047323064216,91.8852368853417,265.411605614461337],"luv":[23.6329047323064216,-7.35054503717070418,-91.590754146539723],"rgb":[0,0.0666666666666666657,0.733333333333333282],"xyz":[0.0916912589923969817,0.0398835440144448133,0.473018922739388281],"hpluv":[265.411605614461337,493.364573724961247,23.6329047323064216],"hsluv":[265.411605614461337,99.999999999993,23.6329047323064216]},"#0011cc":{"lch":[26.0399131129061345,101.953231398784169,265.494123438592396],"luv":[26.0399131129061345,-8.00958293333115,-101.638122640513785],"rgb":[0,0.0666666666666666657,0.8],"xyz":[0.110983634436118722,0.047600494191933615,0.574625433409658437],"hpluv":[265.494123438592396,496.821968194535657,26.0399131129061345],"hsluv":[265.494123438592396,99.9999999999927383,26.0399131129061345]},"#0011dd":{"lch":[28.43483595206839,111.929749681002491,265.557201901085818],"luv":[28.43483595206839,-8.67050070949402496,-111.593419524175076],"rgb":[0,0.0666666666666666657,0.866666666666666696],"xyz":[0.132501959986752266,0.056207824412187149,0.687955281309664435],"hpluv":[265.557201901085818,499.498435149301031,28.43483595206839],"hsluv":[265.557201901085818,99.9999999999932214,28.43483595206839]},"#0011ee":{"lch":[30.8150119654139019,121.810820553676152,265.60639254385444],"luv":[30.8150119654139019,-9.33165721729429798,-121.452855781734542],"rgb":[0,0.0666666666666666657,0.933333333333333348],"xyz":[0.156314140252927,0.0657326965186571799,0.813366097378187658],"hpluv":[265.60639254385444,501.606152289563909,30.8150119654139019],"hsluv":[265.60639254385444,99.9999999999933635,30.8150119654139019]},"#0011ff":{"lch":[33.1788572452669683,131.59562707663585,265.645416939351662],"luv":[33.1788572452669683,-9.99188030865750321,-131.215743695604147],"rgb":[0,0.0666666666666666657,1],"xyz":[0.182485188662758396,0.076201115882589876,0.951200285669969503],"hpluv":[265.645416939351662,503.291227463659,33.1788572452669683],"hsluv":[265.645416939351662,99.9999999999995,33.1788572452669683]},"#55aa00":{"lch":[62.2364297391950743,84.7105424007581291,119.071642820441127],"luv":[62.2364297391950743,-41.1610955154551661,74.0380997176333437],"rgb":[0.333333333333333315,0.66666666666666663,0],"xyz":[0.181203244729902568,0.306798408854291604,0.0496696976001293408],"hpluv":[119.071642820441127,172.715819722381468,62.2364297391950743],"hsluv":[119.071642820441127,100.00000000000216,62.2364297391950743]},"#55aa11":{"lch":[62.270812500354296,83.3839078255156352,119.512873370738717],"luv":[62.270812500354296,-41.0765057562956173,72.5644317769187808],"rgb":[0.333333333333333315,0.66666666666666663,0.0666666666666666657],"xyz":[0.182214910229539701,0.307203075054146457,0.0549978025648849705],"hpluv":[119.512873370738717,169.917081036602212,62.270812500354296],"hsluv":[119.512873370738717,97.826098763204655,62.270812500354296]},"#55aa22":{"lch":[62.3344691942433826,80.9675552156414,120.358690899927907],"luv":[62.3344691942433826,-40.9219560187625078,69.8651451955580285],"rgb":[0.333333333333333315,0.66666666666666663,0.133333333333333331],"xyz":[0.184090268368016702,0.307953218309537258,0.0648746887608641631],"hpluv":[120.358690899927907,164.824621464176317,62.3344691942433826],"hsluv":[120.358690899927907,93.8493385636837729,62.3344691942433826]},"#55aa33":{"lch":[62.4390542004851312,77.1100321042589343,121.835090998601942],"luv":[62.4390542004851312,-40.6737079775314143,65.5103543760705094],"rgb":[0.333333333333333315,0.66666666666666663,0.2],"xyz":[0.187178019100474435,0.309188318602520384,0.0811368426184753133],"hpluv":[121.835090998601942,156.708983850290963,62.4390542004851312],"hsluv":[121.835090998601942,87.4478443822902,62.4390542004851312]},"#55aa44":{"lch":[62.5895604608427192,71.8060360850404322,124.168545167949461],"luv":[62.5895604608427192,-40.3283690350335959,59.4115264003566281],"rgb":[0.333333333333333315,0.66666666666666663,0.266666666666666663],"xyz":[0.191636014344693323,0.310971516700207951,0.104615617571361952],"hpluv":[124.168545167949461,145.578881327618376,62.5895604608427192],"hsluv":[124.168545167949461,78.5131262768233569,62.5895604608427192]},"#55aa55":{"lch":[62.7899606618147317,65.2067785819955361,127.715012949239551],"luv":[62.7899606618147317,-39.8892256495404212,51.582687503865472],"rgb":[0.333333333333333315,0.66666666666666663,0.333333333333333315],"xyz":[0.197598428384055336,0.313356482315952811,0.136017664845335867],"hpluv":[127.715012949239551,131.777681042751937,62.7899606618147317],"hsluv":[127.715012949239551,67.0983271543339583,62.7899606618147317]},"#55aa66":{"lch":[63.0434325957243402,57.6560159218084,133.059858461454269],"luv":[63.0434325957243402,-39.3653397911167744,42.1258376190401904],"rgb":[0.333333333333333315,0.66666666666666663,0.4],"xyz":[0.205183424157563493,0.31639048062535613,0.175965309252479829],"hpluv":[133.059858461454269,116.049721847977636,63.0434325957243402],"hsluv":[133.059858461454269,68.1368400599560289,63.0434325957243402]},"#55aa77":{"lch":[63.3524771250310863,49.7736139598232441,141.163090238883626],"luv":[63.3524771250310863,-38.7703675351212311,31.2133184364163512],"rgb":[0.333333333333333315,0.66666666666666663,0.466666666666666674],"xyz":[0.214497437177765427,0.320116085833436925,0.225019111158877738],"hpluv":[141.163090238883626,99.6953496544650903,63.3524771250310863],"hsluv":[141.163090238883626,69.3257510819996696,63.3524771250310863]},"#55aa88":{"lch":[63.7189896387035901,42.62351374085884,153.427389325734708],"luv":[63.7189896387035901,-38.1211143540371324,19.0668446268281784],"rgb":[0.333333333333333315,0.66666666666666663,0.533333333333333326],"xyz":[0.225637854279709227,0.324572252674214523,0.283691974562449878],"hpluv":[153.427389325734708,84.882799477410984,63.7189896387035901],"hsluv":[153.427389325734708,70.6362499177174783,63.7189896387035901]},"#55aa99":{"lch":[64.1443101574831473,37.9035590936142697,170.991128647613664],"luv":[64.1443101574831473,-37.4359848569684885,5.93521943587048106],"rgb":[0.333333333333333315,0.66666666666666663,0.6],"xyz":[0.238694818388781954,0.329795038317843681,0.352458652203567813],"hpluv":[170.991128647613664,74.9827180661079211,64.1443101574831473],"hsluv":[170.991128647613664,72.0364673991159918,64.1443101574831473]},"#55aaaa":{"lch":[64.6292640862610881,37.5790288142004414,192.177050630061],"luv":[64.6292640862610881,-36.7335179653569526,-7.92666793219602717],"rgb":[0.333333333333333315,0.66666666666666663,0.66666666666666663],"xyz":[0.253752511354034482,0.335818115503944803,0.431762501820566413],"hpluv":[192.177050630061,73.7828909738526,64.6292640862610881],"hsluv":[192.177050630061,73.4940830927894808,64.6292640862610881]},"#55aabb":{"lch":[65.1741997434662466,42.3607987370151307,211.725401595501864],"luv":[65.1741997434662466,-36.0311661131296148,-22.2753751520813346],"rgb":[0.333333333333333315,0.66666666666666663,0.733333333333333282],"xyz":[0.270890103461371157,0.342673152346879561,0.522020486919208104],"hpluv":[211.725401595501864,82.4760322189960249,65.1741997434662466],"hsluv":[211.725401595501864,74.9784994025983,65.1741997434662466]},"#55aacc":{"lch":[65.7790257871148327,51.0903516363502916,226.227071697937646],"luv":[65.7790257871148327,-35.3444111183519212,-36.8916878581455236],"rgb":[0.333333333333333315,0.66666666666666663,0.8],"xyz":[0.290182478905092855,0.350390102524368363,0.62362699758947826],"hpluv":[226.227071697937646,98.5577501957325808,65.7790257871148327],"hsluv":[226.227071697937646,76.4624197891718,65.7790257871148327]},"#55aadd":{"lch":[66.4432499478878071,62.1650528283955595,236.084470311275709],"luv":[66.4432499478878071,-34.6862381636523693,-51.5883579425784404],"rgb":[0.333333333333333315,0.66666666666666663,0.866666666666666696],"xyz":[0.311700804455726455,0.358997432744621869,0.736956845489484258],"hpluv":[236.084470311275709,118.722973851074883,66.4432499478878071],"hsluv":[236.084470311275709,77.9227939155192928,66.4432499478878071]},"#55aaee":{"lch":[67.1660194476775274,74.4631251020179832,242.774049894046698],"luv":[67.1660194476775274,-34.0669326024190866,-66.2133000462974763],"rgb":[0.333333333333333315,0.66666666666666663,0.933333333333333348],"xyz":[0.335512984721901164,0.368522304851091886,0.862367661558007481],"hpluv":[242.774049894046698,140.679551339708695,67.1660194476775274],"hsluv":[242.774049894046698,80.7550915423080085,67.1660194476775274]},"#55aaff":{"lch":[67.9461628502375135,87.3278464079016,247.446578213330071],"luv":[67.9461628502375135,-33.4941307575646476,-80.6492155140842897],"rgb":[0.333333333333333315,0.66666666666666663,1],"xyz":[0.361684033131732585,0.37899072421502461,1.00020184984978933],"hpluv":[247.446578213330071,163.089927997179217,67.9461628502375135],"hsluv":[247.446578213330071,99.9999999999981,67.9461628502375135]},"#002200":{"lch":[10.1376941245203973,15.6902558355344119,127.715012949240474],"luv":[10.1376941245203973,-9.59826829561359141,12.4119850914324186],"rgb":[0,0.133333333333333331,0],"xyz":[0.00572002399569634425,0.0114400479913928481,0.00190667466523206119],"hpluv":[127.715012949240474,196.394882900214583,10.1376941245203973],"hsluv":[127.715012949240474,100.000000000002331,10.1376941245203973]},"#002211":{"lch":[10.4423176349325608,11.2803579121031614,143.951720967420982],"luv":[10.4423176349325608,-9.12041102953238614,6.63811549142769763],"rgb":[0,0.133333333333333331,0.0666666666666666657],"xyz":[0.00673168949533346599,0.0118447141912477027,0.00723477962998769243],"hpluv":[143.951720967420982,137.077225818420459,10.4423176349325608],"hsluv":[143.951720967420982,99.9999999999911,10.4423176349325608]},"#002222":{"lch":[10.9891417742670896,8.69416226881610399,192.17705063006116],"luv":[10.9891417742670896,-8.49854762011842,-1.83388819318003415],"rgb":[0,0.133333333333333331,0.133333333333333331],"xyz":[0.00860704763381048461,0.0125948574466385205,0.0171116658259668902],"hpluv":[192.17705063006116,100.392967527320849,10.9891417742670896],"hsluv":[192.17705063006116,99.9999999999915,10.9891417742670896]},"#002233":{"lch":[11.8439988341371283,14.4341695325786503,236.81663495428262],"luv":[11.8439988341371283,-7.90011340243738758,-12.0802921456333543],"rgb":[0,0.133333333333333331,0.2],"xyz":[0.0116947983662682251,0.0138299577396216334,0.0333738196835780335],"hpluv":[236.81663495428262,154.643892414528665,11.8439988341371283],"hsluv":[236.81663495428262,99.9999999999918572,11.8439988341371283]},"#002244":{"lch":[12.9926705590666103,23.9154033254141893,251.756603241059679],"luv":[12.9926705590666103,-7.48682111947174356,-22.713300635140282],"rgb":[0,0.133333333333333331,0.266666666666666663],"xyz":[0.0161527936104871039,0.0156131558373092099,0.056852594636464672],"hpluv":[251.756603241059679,233.570832873869165,12.9926705590666103],"hsluv":[251.756603241059679,99.9999999999922551,12.9926705590666103]},"#002255":{"lch":[14.3995425627967926,34.0053227001087492,257.612107564284656],"luv":[14.3995425627967926,-7.29512566501762105,-33.2135983216232162],"rgb":[0,0.133333333333333331,0.333333333333333315],"xyz":[0.022115207649849096,0.0179981214530540411,0.0882546419104385804],"hpluv":[257.612107564284656,299.666041626864057,14.3995425627967926],"hsluv":[257.612107564284656,99.9999999999922551,14.3995425627967926]},"#002266":{"lch":[16.0198287291043684,44.1221041927951489,260.479541157990241],"luv":[16.0198287291043684,-7.29778599254304705,-43.514392998258792],"rgb":[0,0.133333333333333331,0.4],"xyz":[0.0297002034233572743,0.0210321197624573561,0.128202286317582542],"hpluv":[260.479541157990241,349.492349810916096,16.0198287291043684],"hsluv":[260.479541157990241,99.9999999999926672,16.0198287291043684]},"#002277":{"lch":[17.8086814865908138,54.1839210795750787,262.094384047744654],"luv":[17.8086814865908138,-7.45254493353373,-53.6689563674502708],"rgb":[0,0.133333333333333331,0.466666666666666674],"xyz":[0.0390142164435591868,0.0247577249705381724,0.177256088223980451],"hpluv":[262.094384047744654,386.080609388904179,17.8086814865908138],"hsluv":[262.094384047744654,99.9999999999926246,17.8086814865908138]},"#002288":{"lch":[19.7262797638069571,64.1945165648047862,263.091662768615947],"luv":[19.7262797638069571,-7.7213996360385595,-63.7284547486409778],"rgb":[0,0.133333333333333331,0.533333333333333326],"xyz":[0.0501546335455030148,0.0292138918113157633,0.235928951627552619],"hpluv":[263.091662768615947,412.944865974292611,19.7262797638069571],"hsluv":[263.091662768615947,99.9999999999928093,19.7262797638069571]},"#002299":{"lch":[21.7396965211461932,74.1610579713059082,263.749129578079874],"luv":[21.7396965211461932,-8.0748025544340809,-73.7201470639492129],"rgb":[0,0.133333333333333331,0.6],"xyz":[0.0632115976545757352,0.0344366774549449278,0.304695629268670554],"hpluv":[263.749129578079874,432.874263951475,21.7396965211461932],"hsluv":[263.749129578079874,99.9999999999928662,21.7396965211461932]},"#0022aa":{"lch":[23.8228560713303921,84.0831956926279389,264.204285416148139],"luv":[23.8228560713303921,-8.49087961251211532,-83.6533846373868641],"rgb":[0,0.133333333333333331,0.66666666666666663],"xyz":[0.0782692906198282773,0.0404597546410460224,0.383999478885669154],"hpluv":[264.204285416148139,447.872821658188343,23.8228560713303921],"hsluv":[264.204285416148139,99.9999999999925251,23.8228560713303921]},"#0022bb":{"lch":[25.9556350824861326,93.9557715434331868,264.531619021467236],"luv":[25.9556350824861326,-8.95364890679069,-93.5281731756572725],"rgb":[0,0.133333333333333331,0.733333333333333282],"xyz":[0.0954068827271649239,0.0473147914839807809,0.474257463984310901],"hpluv":[264.531619021467236,459.336683180505304,25.9556350824861326],"hsluv":[264.531619021467236,99.9999999999932783,25.9556350824861326]},"#0022cc":{"lch":[28.122733334265547,103.772183036952711,264.774345627526145],"luv":[28.122733334265547,-9.45141286238599143,-103.340876555018355],"rgb":[0,0.133333333333333331,0.8],"xyz":[0.114699258170886664,0.0550317416614695826,0.575863974654581057],"hpluv":[264.774345627526145,468.233789407088068,28.122733334265547],"hsluv":[264.774345627526145,99.9999999999932,28.122733334265547]},"#0022dd":{"lch":[30.3126112219004114,113.526334495176528,264.958927468127968],"luv":[30.3126112219004114,-9.97554123069502552,-113.087210599012522],"rgb":[0,0.133333333333333331,0.866666666666666696],"xyz":[0.136217583721520208,0.0636390718817231166,0.689193822554587],"hpluv":[264.958927468127968,475.239568383116307,30.3126112219004114],"hsluv":[264.958927468127968,99.9999999999930651,30.3126112219004114]},"#0022ee":{"lch":[32.516600051948771,123.213441320075319,265.102292473050682],"luv":[32.516600051948771,-10.519601137712538,-122.76355368691101],"rgb":[0,0.133333333333333331,0.933333333333333348],"xyz":[0.160029763987694945,0.0731639439881931475,0.814604638623110278],"hpluv":[265.102292473050682,480.830806343612153,32.516600051948771],"hsluv":[265.102292473050682,99.9999999999931504,32.516600051948771]},"#0022ff":{"lch":[34.728199222084136,132.830192238289243,265.215668718406278],"luv":[34.728199222084136,-11.0787458291525667,-132.367372720447662],"rgb":[0,0.133333333333333331,1],"xyz":[0.186200812397526339,0.0836323633521258575,0.952438826914892123],"hpluv":[265.215668718406278,485.348691920142073,34.728199222084136],"hsluv":[265.215668718406278,99.9999999999995595,34.728199222084136]},"#55bb00":{"lch":[67.6287132051522093,94.1564927152114421,120.799924159261636],"luv":[67.6287132051522093,-48.2120532219748839,80.8767150949587403],"rgb":[0.333333333333333315,0.733333333333333282,0],"xyz":[0.215157742638501348,0.374707404671490163,0.0609878635696619598],"hpluv":[120.799924159261636,176.668237076728246,67.6287132051522093],"hsluv":[120.799924159261636,100.000000000002245,67.6287132051522093]},"#55bb11":{"lch":[67.658807387059241,92.983820197622,121.168613223743336],"luv":[67.658807387059241,-48.1245535730997,79.5614112615755],"rgb":[0.333333333333333315,0.733333333333333282,0.0666666666666666657],"xyz":[0.21616940813813848,0.375112070871345,0.0663159685344176],"hpluv":[121.168613223743336,174.390319462510746,67.658807387059241],"hsluv":[121.168613223743336,98.2170484527892853,67.658807387059241]},"#55bb22":{"lch":[67.7145367797011,90.8418307914021739,121.8702408444057],"luv":[67.7145367797011,-47.9642424389893733,77.1470651987980318],"rgb":[0.333333333333333315,0.733333333333333282,0.133333333333333331],"xyz":[0.218044766276615481,0.375862214126735816,0.076192854730396789],"hpluv":[121.8702408444057,170.232819736279453,67.7145367797011],"hsluv":[121.8702408444057,94.9476871157098401,67.7145367797011]},"#55bb33":{"lch":[67.8061331119394595,87.4049119918652337,123.079288563119889],"luv":[67.8061331119394595,-47.7055226907732077,73.2379802090816128],"rgb":[0.333333333333333315,0.733333333333333282,0.2],"xyz":[0.221132517009073215,0.377097314419718943,0.0924550085880079253],"hpluv":[123.079288563119889,163.570954697809668,67.8061331119394595],"hsluv":[123.079288563119889,89.6636954368763526,67.8061331119394595]},"#55bb44":{"lch":[67.9380247917114701,82.6396215824211851,124.951716096499126],"luv":[67.9380247917114701,-47.3430758547011195,67.7343356349037293],"rgb":[0.333333333333333315,0.733333333333333282,0.266666666666666663],"xyz":[0.225590512253292103,0.378880512517406509,0.115933783540894564],"hpluv":[124.951716096499126,154.352877500253584,67.9380247917114701],"hsluv":[124.951716096499126,82.2446152582935213,67.9380247917114701]},"#55bb55":{"lch":[68.1137800414251,76.6309713561306154,127.715012949239735],"luv":[68.1137800414251,-46.8777966745344372,60.6199467990950964],"rgb":[0.333333333333333315,0.733333333333333282,0.333333333333333315],"xyz":[0.231552926292654115,0.38126547813315137,0.147335830814868479],"hpluv":[127.715012949239735,142.760701907139094,68.1137800414251],"hsluv":[127.715012949239735,72.6906423420812189,68.1137800414251]},"#55bb66":{"lch":[68.3363083667640723,69.6002362161904813,131.717534816394789],"luv":[68.3363083667640723,-46.3160914021311,51.9520216986687728],"rgb":[0.333333333333333315,0.733333333333333282,0.4],"xyz":[0.239137922066162273,0.384299476442554688,0.187283475222012441],"hpluv":[131.717534816394789,129.240469264566769,68.3363083667640723],"hsluv":[131.717534816394789,73.4099839145656432,68.3363083667640723]},"#55bb77":{"lch":[68.6079661831172416,61.943926665161591,137.498849513297245],"luv":[68.6079661831172416,-45.6690129611091,41.8496273084595956],"rgb":[0.333333333333333315,0.733333333333333282,0.466666666666666674],"xyz":[0.248451935086364206,0.388025081650635484,0.23633727712841035],"hpluv":[137.498849513297245,114.568047908441656,68.6079661831172416],"hsluv":[137.498849513297245,74.2430874467708719,68.6079661831172416]},"#55bb88":{"lch":[68.930619778887035,54.3103726013937376,145.860320527647957],"luv":[68.930619778887035,-44.9511677919681389,30.4796503628330058],"rgb":[0.333333333333333315,0.733333333333333282,0.533333333333333326],"xyz":[0.259592352188308,0.392481248491413082,0.29501014053198249],"hpluv":[145.860320527647957,99.9792617157038421,68.930619778887035],"hsluv":[145.860320527647957,75.173468866550067,68.930619778887035]},"#55bb99":{"lch":[69.3056876145919176,47.7211055743842465,157.786981113384826],"luv":[69.3056876145919176,-44.1794697421466793,18.0410191104680564],"rgb":[0.333333333333333315,0.733333333333333282,0.6],"xyz":[0.272649316297380762,0.397704034135042239,0.363776818173100425],"hpluv":[157.786981113384826,87.3737441175344713,69.3056876145919176],"hsluv":[157.786981113384826,76.1818306173187807,69.3056876145919176]},"#55bbaa":{"lch":[69.7341725511637378,43.6310575063277497,173.751690425302456],"luv":[69.7341725511637378,-43.37186937951342,4.74869725787034813],"rgb":[0.333333333333333315,0.733333333333333282,0.66666666666666663],"xyz":[0.287707009262633262,0.403727111321143362,0.443080667790099],"hpluv":[173.751690425302456,79.3943164161001675,69.7341725511637378],"hsluv":[173.751690425302456,77.247554342351421,69.7341725511637378]},"#55bbbb":{"lch":[70.2166895771587605,43.5254926875218899,192.177050630061075],"luv":[70.2166895771587605,-42.5461891389785691,-9.18097508120914796],"rgb":[0.333333333333333315,0.733333333333333282,0.733333333333333282],"xyz":[0.304844601369969936,0.41058214816407812,0.533338652888740716],"hpluv":[192.177050630061075,78.6579587560082274,70.2166895771587605],"hsluv":[192.177050630061075,78.350068429440185,70.2166895771587605]},"#55bbcc":{"lch":[70.753492069254392,47.9033609117661214,209.436295084806801],"luv":[70.753492069254392,-41.719164640327179,-23.5423721905035848],"rgb":[0.333333333333333315,0.733333333333333282,0.8],"xyz":[0.324136976813691691,0.418299098341566922,0.634945163559010872],"hpluv":[209.436295084806801,85.9127126132272849,70.753492069254392],"hsluv":[209.436295084806801,79.4699741443966445,70.753492069254392]},"#55bbdd":{"lch":[71.3444981992470701,55.9344204047748121,223.003151043067675],"luv":[71.3444981992470701,-40.905747403701568,-38.1494327004039633],"rgb":[0.333333333333333315,0.733333333333333282,0.866666666666666696],"xyz":[0.345655302364325179,0.426906428561820428,0.74827501145901687],"hpluv":[223.003151043067675,99.4850863142100081,71.3444981992470701],"hsluv":[223.003151043067675,80.5898663629362,71.3444981992470701]},"#55bbee":{"lch":[71.9893182406489,66.3452770137575385,232.793079173014576],"luv":[71.9893182406489,-40.1186787976363846,-52.8411524624918272],"rgb":[0.333333333333333315,0.733333333333333282,0.933333333333333348],"xyz":[0.369467482630499944,0.436431300668290445,0.873685827527540093],"hpluv":[232.793079173014576,116.944897502912525,71.9893182406489],"hsluv":[232.793079173014576,81.6948376758296888,71.9893182406489]},"#55bbff":{"lch":[72.6872829834048417,78.1278426582451146,239.741904567598624],"luv":[72.6872829834048417,-39.3683093588317803,-67.4840426816504788],"rgb":[0.333333333333333315,0.733333333333333282,1],"xyz":[0.395638531040331309,0.446899720032223169,1.01152001581932205],"hpluv":[239.741904567598624,136.39131713467242,72.6872829834048417],"hsluv":[239.741904567598624,99.9999999999976126,72.6872829834048417]},"#003300":{"lch":[17.3086983277836381,26.7889227675687067,127.71501294924046],"luv":[17.3086983277836381,-16.3877039844862402,21.1917328494772867],"rgb":[0,0.2,0],"xyz":[0.0118377460847071559,0.0236754921694146449,0.00394591536156894181],"hpluv":[127.71501294924046,196.394882900214611,17.3086983277836381],"hsluv":[127.71501294924046,100.000000000002402,17.3086983277836381]},"#003311":{"lch":[17.4974002223845133,22.6621201022865968,134.58430385811792],"luv":[17.4974002223845133,-15.9078557679049606,16.1403783226414816],"rgb":[0,0.2,0.0666666666666666657],"xyz":[0.0128494115843442776,0.0240801583692694977,0.00927402032632457241],"hpluv":[134.58430385811792,164.348724425256108,17.4974002223845133],"hsluv":[134.58430385811792,99.9999999999909335,17.4974002223845133]},"#003322":{"lch":[17.8416856931397234,17.1190432019509622,152.323942273369369],"luv":[17.8416856931397234,-15.1604156821769873,7.95131665159082601],"rgb":[0,0.2,0.133333333333333331],"xyz":[0.0147247697228212963,0.0248303016246603156,0.0191509065223037685],"hpluv":[152.323942273369369,121.753913655152402,17.8416856931397234],"hsluv":[152.323942273369369,99.9999999999912177,17.8416856931397234]},"#003333":{"lch":[18.3937448040413543,14.5523831926532932,192.17705063006116],"luv":[18.3937448040413543,-14.2249612699966086,-3.06958196712752551],"rgb":[0,0.2,0.2],"xyz":[0.017812520455279035,0.0260654019176434319,0.0354130603799149152],"hpluv":[192.17705063006116,100.392967527320849,18.3937448040413543],"hsluv":[192.17705063006116,99.9999999999915,18.3937448040413543]},"#003344":{"lch":[19.1608294605123817,20.3566459399555,229.223567805483242],"luv":[19.1608294605123817,-13.2951121246929258,-15.41535038578591],"rgb":[0,0.2,0.266666666666666663],"xyz":[0.0222705156994979156,0.0278486000153310084,0.0588918353328015537],"hpluv":[229.223567805483242,134.812835768594709,19.1608294605123817],"hsluv":[229.223567805483242,99.9999999999917577,19.1608294605123817]},"#003355":{"lch":[20.1371955335767296,30.6237106081975696,245.893961784182551],"luv":[20.1371955335767296,-12.5075398018694361,-27.9530517031554915],"rgb":[0,0.2,0.333333333333333315],"xyz":[0.0282329297388599076,0.0302335656310758379,0.0902938826067754552],"hpluv":[245.893961784182551,192.973712242731381,20.1371955335767296],"hsluv":[245.893961784182551,99.9999999999920419,20.1371955335767296]},"#003366":{"lch":[21.3076868402923836,41.8514919359335167,253.451236278131262],"luv":[21.3076868402923836,-11.9206140697212764,-40.1179054471226308],"rgb":[0,0.2,0.4],"xyz":[0.0358179255123680859,0.0332675639404791529,0.130241527013919417],"hpluv":[253.451236278131262,249.237832456686277,21.3076868402923836],"hsluv":[253.451236278131262,99.9999999999920846,21.3076868402923836]},"#003377":{"lch":[22.6513946103128916,53.0186284648852251,257.430711853641924],"luv":[22.6513946103128916,-11.5379190314963687,-51.7479602372902434],"rgb":[0,0.2,0.466666666666666674],"xyz":[0.04513193853257,0.0369931691485599692,0.179295328920317326],"hpluv":[257.430711853641924,297.011229333042763,22.6513946103128916],"hsluv":[257.430711853641924,99.9999999999922409,22.6513946103128916]},"#003388":{"lch":[24.1449124481648099,63.8887963004775941,259.778872090702237],"luv":[24.1449124481648099,-11.3369168899634012,-62.8748964862287636],"rgb":[0,0.2,0.533333333333333326],"xyz":[0.0562723556345138265,0.0414493359893375601,0.237968192323889494],"hpluv":[259.778872090702237,335.767299249073346,24.1449124481648099],"hsluv":[259.778872090702237,99.9999999999925677,24.1449124481648099]},"#003399":{"lch":[25.764809398314533,74.4520642325545481,261.279947020055374],"luv":[25.764809398314533,-11.2874373109462987,-73.5914643653724596],"rgb":[0,0.2,0.6],"xyz":[0.0693293197435865399,0.0466721216329667177,0.306734869965007428],"hpluv":[261.279947020055374,366.681615332004242,25.764809398314533],"hsluv":[261.279947020055374,99.9999999999928662,25.764809398314533]},"#0033aa":{"lch":[27.4892253326185596,84.7561178753388447,262.297068677869788],"luv":[27.4892253326185596,-11.360446037840406,-83.9913077831251],"rgb":[0,0.2,0.66666666666666663],"xyz":[0.084387012708839082,0.0526951988190678261,0.386038719582006029],"hpluv":[262.297068677869788,391.244172205097584,27.4892253326185596],"hsluv":[262.297068677869788,99.9999999999925819,27.4892253326185596]},"#0033bb":{"lch":[29.2987082140811808,94.8530383242648725,263.01737082090068],"luv":[29.2987082140811808,-11.531133966499155,-94.1495184734957178],"rgb":[0,0.2,0.733333333333333282],"xyz":[0.101524604816175729,0.0595502356620025847,0.476296704680647776],"hpluv":[263.01737082090068,410.811034734971429,29.2987082140811808],"hsluv":[263.01737082090068,99.999999999992923,29.2987082140811808]},"#0033cc":{"lch":[31.1765026722858281,104.784892642773883,263.545454640352943],"luv":[31.1765026722858281,-11.7793879173059235,-104.120697973319764],"rgb":[0,0.2,0.8],"xyz":[0.120816980259897469,0.0672671858394913863,0.577903215350917931],"hpluv":[263.545454640352943,426.491720029659064,31.1765026722858281],"hsluv":[263.545454640352943,99.9999999999928519,31.1765026722858281]},"#0033dd":{"lch":[33.108496036114694,114.582250296133722,263.943596884481394],"luv":[33.108496036114694,-12.0892798728815123,-113.942711022166648],"rgb":[0,0.2,0.866666666666666696],"xyz":[0.142335305810531026,0.0758745160597449203,0.691233063250923929],"hpluv":[263.943596884481394,439.154381827523366,33.108496036114694],"hsluv":[263.943596884481394,99.999999999992724,33.108496036114694]},"#0033ee":{"lch":[35.0829820911796091,124.266344101148519,264.250786122927309],"luv":[35.0829820911796091,-12.4483077284590724,-123.641271066592637],"rgb":[0,0.2,0.933333333333333348],"xyz":[0.166147486076705764,0.0853993881662149512,0.816643879319447152],"hpluv":[264.250786122927309,449.46548401365061,35.0829820911796091],"hsluv":[264.250786122927309,99.9999999999932214,35.0829820911796091]},"#0033ff":{"lch":[37.0903499028545482,133.851694130242549,264.492451291459133],"luv":[37.0903499028545482,-12.8466699872586325,-133.233776092154926],"rgb":[0,0.2,1],"xyz":[0.192318534486537157,0.0958678075301476473,0.954478067611229],"hpluv":[264.492451291459133,457.933345064777,37.0903499028545482],"hsluv":[264.492451291459133,99.999999999999531,37.0903499028545482]},"#55cc00":{"lch":[72.9678739916599,103.392643433537373,122.072672834653702],"luv":[72.9678739916599,-54.9009234662034089,87.6123696673744661],"rgb":[0.333333333333333315,0.8,0],"xyz":[0.253381485948118268,0.451154891290725057,0.0737291113395339148],"hpluv":[122.072672834653702,179.803140433373983,72.9678739916599],"hsluv":[122.072672834653702,100.000000000002444,72.9678739916599]},"#55cc11":{"lch":[72.9944661394807497,102.34674561848017,122.382691003133885],"luv":[72.9944661394807497,-54.8140205324080085,86.4307786136781431],"rgb":[0.333333333333333315,0.8,0.0666666666666666657],"xyz":[0.254393151447755372,0.45155955749057991,0.0790572163042895515],"hpluv":[122.382691003133885,177.91945009175069,72.9944661394807497],"hsluv":[122.382691003133885,98.5172338886757757,72.9944661394807497]},"#55cc22":{"lch":[73.0437189009647909,100.431941691916791,122.969611448584445],"luv":[73.0437189009647909,-54.6544745496639663,84.2583130836875114],"rgb":[0.333333333333333315,0.8,0.133333333333333331],"xyz":[0.256268509586232429,0.452309700745970711,0.0889341025002687441],"hpluv":[122.969611448584445,174.473032354427772,73.0437189009647909],"hsluv":[122.969611448584445,95.7933392549395,73.0437189009647909]},"#55cc33":{"lch":[73.1246943704287702,97.3470237033586,123.971835615120114],"luv":[73.1246943704287702,-54.3960871275936384,80.7310889875115123],"rgb":[0.333333333333333315,0.8,0.2],"xyz":[0.259356260318690135,0.453544801038953838,0.10519625635787988],"hpluv":[123.971835615120114,168.926560877595364,73.1246943704287702],"hsluv":[123.971835615120114,91.3772697810403542,73.1246943704287702]},"#55cc44":{"lch":[73.2413452172043,93.0415252478239836,125.502056943833935],"luv":[73.2413452172043,-54.0322080150887771,75.7446098244333399],"rgb":[0.333333333333333315,0.8,0.266666666666666663],"xyz":[0.26381425556290905,0.455327999136641404,0.128675031310766519],"hpluv":[125.502056943833935,161.198069131808353,73.2413452172043],"hsluv":[125.502056943833935,85.148140842768953,73.2413452172043]},"#55cc55":{"lch":[73.3968865779486919,87.5572640326508207,127.71501294923992],"luv":[73.3968865779486919,-53.5617851120033066,69.2633356148757144],"rgb":[0.333333333333333315,0.8,0.333333333333333315],"xyz":[0.269776669602271035,0.457712964752386264,0.160077078584740434],"hpluv":[127.71501294923992,151.374900584602614,73.3968865779486919],"hsluv":[127.71501294923992,77.0768048277098,73.3968865779486919]},"#55cc66":{"lch":[73.5939772793636,81.0375847478920832,130.834727778769576],"luv":[73.5939772793636,-52.9887999422805,61.3129449826769175],"rgb":[0.333333333333333315,0.8,0.4],"xyz":[0.277361665375779221,0.460746963061789583,0.200024722991884396],"hpluv":[130.834727778769576,139.728031568505,73.5939772793636],"hsluv":[130.834727778769576,77.5857883184082766,73.5939772793636]},"#55cc77":{"lch":[73.8348152761848553,73.7475179973278898,135.191797127350526],"luv":[73.8348152761848553,-52.3216404431773,51.972515352838883],"rgb":[0.333333333333333315,0.8,0.466666666666666674],"xyz":[0.286675678395981126,0.464472568269870378,0.249078524898282305],"hpluv":[135.191797127350526,126.743455190439619,73.8348152761848553],"hsluv":[135.191797127350526,78.1806978106980779,73.8348152761848553]},"#55cc88":{"lch":[74.1211942127210648,66.1117924559585646,141.267644806662588],"luv":[74.1211942127210648,-51.5723023085178269,41.3650424433311343],"rgb":[0.333333333333333315,0.8,0.533333333333333326],"xyz":[0.297816095497924926,0.468928735110648,0.307751388301854445],"hpluv":[141.267644806662588,113.181605649052202,74.1211942127210648],"hsluv":[141.267644806662588,78.852064841283763,74.1211942127210648]},"#55cc99":{"lch":[74.4545405069311,58.7794373107374923,149.710693018120253],"luv":[74.4545405069311,-50.7554383804248,29.646377947024483],"rgb":[0.333333333333333315,0.8,0.6],"xyz":[0.310873059606997626,0.474151520754277134,0.37651806594297238],"hpluv":[149.710693018120253,100.178278207809555,74.4545405069311],"hsluv":[149.710693018120253,79.5881732610030355,74.4545405069311]},"#55ccaa":{"lch":[74.8359403329188808,52.7021878309829361,161.189357777818884],"luv":[74.8359403329188808,-49.8873315971569866,16.9933736582089097],"rgb":[0.333333333333333315,0.8,0.66666666666666663],"xyz":[0.325930752572250182,0.480174597940378256,0.455821915559971],"hpluv":[161.189357777818884,89.3630022499163772,74.8359403329188808],"hsluv":[161.189357777818884,80.3759073289738097,74.8359403329188808]},"#55ccbb":{"lch":[75.2661614985634,49.1164256219739315,175.805780272408356],"luv":[75.2661614985634,-48.9848849956305372,3.59225665059547428],"rgb":[0.333333333333333315,0.8,0.733333333333333282],"xyz":[0.343068344679586856,0.487029634783313,0.546079900658612782],"hpluv":[175.805780272408356,82.8068592257523619,75.2661614985634],"hsluv":[175.805780272408356,81.2015846585734238,75.2661614985634]},"#55cccc":{"lch":[75.7456730324682894,49.1710405410584386,192.177050630061103],"luv":[75.7456730324682894,-48.0647147647340063,-10.3718090261618983],"rgb":[0.333333333333333315,0.8,0.8],"xyz":[0.362360720123308555,0.494746584960801816,0.647686411328882938],"hpluv":[192.177050630061103,82.3741405590198639,75.7456730324682894],"hsluv":[192.177050630061103,82.0517040066532815,75.7456730324682894]},"#55ccdd":{"lch":[76.2746640882933349,53.2320113470533514,207.674227909684788],"luv":[76.2746640882933349,-47.1424090239802069,-24.7232745296525458],"rgb":[0.333333333333333315,0.8,0.866666666666666696],"xyz":[0.383879045673942154,0.503353915181055322,0.761016259228888936],"hpluv":[207.674227909684788,89.8673986045394,76.2746640882933349],"hsluv":[207.674227909684788,82.913556803619926,76.2746640882933349]},"#55ccee":{"lch":[76.8530630513789674,60.6801737900983298,220.368363670310828],"luv":[76.8530630513789674,-46.2319850937693673,-39.3025068600722207],"rgb":[0.333333333333333315,0.8,0.933333333333333348],"xyz":[0.407691225940116864,0.51287878728752534,0.886427075297412159],"hpluv":[220.368363670310828,105.55411204702996,76.8530630513789674],"hsluv":[220.368363670310828,83.7756757275922865,76.8530630513789674]},"#55ccff":{"lch":[77.4805572724897758,70.4908339109135511,229.9629437526429],"luv":[77.4805572724897758,-45.3455492712466395,-53.9697955040126445],"rgb":[0.333333333333333315,0.8,1],"xyz":[0.433862274349948285,0.523347206651458063,1.02426126358919389],"hpluv":[229.9629437526429,126.754412601721029,77.4805572724897758],"hsluv":[229.9629437526429,99.9999999999968878,77.4805572724897758]},"#004400":{"lch":[24.1097877444294397,37.3150672336374782,127.715012949240432],"luv":[24.1097877444294397,-22.8269080205926969,29.5185791133361732],"rgb":[0,0.266666666666666663,0],"xyz":[0.0206703165676731908,0.0413406331353469575,0.00689010552255753684],"hpluv":[127.715012949240432,196.39488290021464,24.1097877444294397],"hsluv":[127.715012949240432,100.000000000002458,24.1097877444294397]},"#004411":{"lch":[24.2402356883412295,33.8624764720942082,131.447767669063751],"luv":[24.2402356883412295,-22.4148262696793807,25.3819399598065552],"rgb":[0,0.266666666666666663,0.0666666666666666657],"xyz":[0.0216819820673103125,0.0417452993352018104,0.0122182104873131692],"hpluv":[131.447767669063751,177.264269230781338,24.2402356883412295],"hsluv":[131.447767669063751,99.9999999999909335,24.2402356883412295]},"#004422":{"lch":[24.4798388415780295,28.4164365287723264,139.862893984056171],"luv":[24.4798388415780295,-21.7244820008415864,18.3177713379345413],"rgb":[0,0.266666666666666663,0.133333333333333331],"xyz":[0.0235573402057873311,0.0424954425905926317,0.0220950966832923652],"hpluv":[139.862893984056171,147.299199898382369,24.4798388415780295],"hsluv":[139.862893984056171,99.9999999999911466,24.4798388415780295]},"#004433":{"lch":[24.8682723444395748,22.2877633761795622,158.664607016269599],"luv":[24.8682723444395748,-20.760308528761005,8.10888316004269427],"rgb":[0,0.266666666666666663,0.2],"xyz":[0.0266450909382450717,0.0437305428835757445,0.0383572505409035119],"hpluv":[158.664607016269599,113.726114076625834,24.8682723444395748],"hsluv":[158.664607016269599,99.9999999999913172,24.8682723444395748]},"#004444":{"lch":[25.4163828994624552,20.1084089871091685,192.17705063006116],"luv":[25.4163828994624552,-19.6559790417892835,-4.24153273022775057],"rgb":[0,0.266666666666666663,0.266666666666666663],"xyz":[0.0311030861824639487,0.0455137409812633176,0.0618360254937901505],"hpluv":[192.17705063006116,100.392967527320792,25.4163828994624552],"hsluv":[192.17705063006116,99.9999999999914166,25.4163828994624552]},"#004455":{"lch":[26.1275223832094383,25.5944772375096541,223.546306053382096],"luv":[26.1275223832094383,-18.5513329588178841,-17.6330743352507042],"rgb":[0,0.266666666666666663,0.333333333333333315],"xyz":[0.0370655002218259477,0.0478987065970081505,0.093238072767764052],"hpluv":[223.546306053382096,124.304646155287358,26.1275223832094383],"hsluv":[223.546306053382096,99.999999999991644,26.1275223832094383]},"#004466":{"lch":[26.9988561724938734,35.8050932952910514,240.647496291889979],"luv":[26.9988561724938734,-17.5509899640931621,-31.2084516944496499],"rgb":[0,0.266666666666666663,0.4],"xyz":[0.0446504959953341191,0.050932704906411462,0.133185717174908],"hpluv":[240.647496291889979,168.282428552664811,26.9988561724938734],"hsluv":[240.647496291889979,99.9999999999920135,26.9988561724938734]},"#004477":{"lch":[28.0227048150185141,47.4927479988473422,249.396343090395135],"luv":[28.0227048150185141,-16.7127641209025413,-44.4549730392572684],"rgb":[0,0.266666666666666663,0.466666666666666674],"xyz":[0.0539645090155360385,0.0546583101144922784,0.182239519081305923],"hpluv":[249.396343090395135,215.05848085050232,28.0227048150185141],"hsluv":[249.396343090395135,99.9999999999921698,28.0227048150185141]},"#004488":{"lch":[29.1879465441319326,59.3592998069098,254.306666373838311],"luv":[29.1879465441319326,-16.0560040952153962,-57.1465765034181956],"rgb":[0,0.266666666666666663,0.533333333333333326],"xyz":[0.0651049261174798666,0.0591144769552698762,0.24091238248487809],"hpluv":[254.306666373838311,258.06229412425995,29.1879465441319326],"hsluv":[254.306666373838311,99.9999999999923,29.1879465441319326]},"#004499":{"lch":[30.4813623757938217,70.9684349502494,257.321762040288718],"luv":[30.4813623757938217,-15.5758442205369825,-69.2380808233832141],"rgb":[0,0.266666666666666663,0.6],"xyz":[0.07816189022655258,0.0643372625988990338,0.309679060125996],"hpluv":[257.321762040288718,295.440602563868879,30.4813623757938217],"hsluv":[257.321762040288718,99.9999999999926672,30.4813623757938217]},"#0044aa":{"lch":[31.8888011745219231,82.2033012029853,259.305022310013101],"luv":[31.8888011745219231,-15.2553283345918977,-80.7753532092093138],"rgb":[0,0.266666666666666663,0.66666666666666663],"xyz":[0.0932195831918051221,0.0703603397850001422,0.388982909742994598],"hpluv":[259.305022310013101,327.107417663034141,31.8888011745219231],"hsluv":[259.305022310013101,99.9999999999925109,31.8888011745219231]},"#0044bb":{"lch":[33.3960915948532602,93.0667571364503,260.679203518012741],"luv":[33.3960915948532602,-15.0732787327803415,-91.8379962332527],"rgb":[0,0.266666666666666663,0.733333333333333282],"xyz":[0.110357175299141769,0.0772153766279349,0.479240894841636345],"hpluv":[260.679203518012741,353.621176249907,33.3960915948532602],"hsluv":[260.679203518012741,99.9999999999929656,33.3960915948532602]},"#0044cc":{"lch":[34.9896851087579108,103.60206818965716,261.670396128603272],"luv":[34.9896851087579108,-15.0085679377548828,-102.509177255659253],"rgb":[0,0.266666666666666663,0.8],"xyz":[0.129649550742863495,0.0849323268054237,0.5808474055119065],"hpluv":[261.670396128603272,375.722944942957042,34.9896851087579108],"hsluv":[261.670396128603272,99.999999999992923,34.9896851087579108]},"#0044dd":{"lch":[36.6570567010139499,113.860579159150092,262.408492682931296],"luv":[36.6570567010139499,-15.0420602661110987,-112.862606338006245],"rgb":[0,0.266666666666666663,0.866666666666666696],"xyz":[0.151167876293497039,0.0935396570256772364,0.694177253411912498],"hpluv":[262.408492682931296,394.144185167595538,36.6570567010139499],"hsluv":[262.408492682931296,99.9999999999929088,36.6570567010139499]},"#0044ee":{"lch":[38.386911506645724,123.889384104134805,262.972536787865295],"luv":[38.386911506645724,-15.1572566165017264,-122.958680318078251],"rgb":[0,0.266666666666666663,0.933333333333333348],"xyz":[0.174980056559671776,0.103064529132147253,0.819588069480435721],"hpluv":[262.972536787865295,409.534269399062566,38.386911506645724],"hsluv":[262.972536787865295,99.9999999999931,38.386911506645724]},"#0044ff":{"lch":[40.1692504091911928,133.727629508879147,263.412926975584469],"luv":[40.1692504091911928,-15.3403008413028115,-132.844849595919101],"rgb":[0,0.266666666666666663,1],"xyz":[0.201151104969503169,0.113532948496079963,0.957422257772217566],"hpluv":[263.412926975584469,422.441664595501038,40.1692504091911928],"hsluv":[263.412926975584469,99.9999999999994174,40.1692504091911928]},"#55dd00":{"lch":[78.2526895057908121,112.425836873112019,123.034721453117925],"luv":[78.2526895057908121,-61.2886270790004488,94.2511166373683267],"rgb":[0.333333333333333315,0.866666666666666696,0],"xyz":[0.296015476495293473,0.536422872385076577,0.0879404415219252333],"hpluv":[123.034721453117925,210.800433631405241,78.2526895057908121],"hsluv":[123.034721453117925,100.000000000002288,78.2526895057908121]},"#55dd11":{"lch":[78.2763843013059102,111.485784004679431,123.297526334296066],"luv":[78.2763843013059102,-61.2042162992655108,93.1832814529020368],"rgb":[0.333333333333333315,0.866666666666666696,0.0666666666666666657],"xyz":[0.297027141994930577,0.536827538584931485,0.09326854648668087],"hpluv":[123.297526334296066,209.310421322213443,78.2763843013059102],"hsluv":[123.297526334296066,98.7516598856555561,78.2763843013059102]},"#55dd22":{"lch":[78.3202766586626353,109.761570808260174,123.793166282380056],"luv":[78.3202766586626353,-61.0490014413279738,91.2174426812846235],"rgb":[0.333333333333333315,0.866666666666666696,0.133333333333333331],"xyz":[0.298902500133407634,0.537577681840322286,0.103145432682660063],"hpluv":[123.793166282380056,206.571995072092733,78.3202766586626353],"hsluv":[123.793166282380056,96.4551350157602201,78.3202766586626353]},"#55dd33":{"lch":[78.3924559312840898,106.97461234521991,124.633900466047606],"luv":[78.3924559312840898,-60.7969536029841819,88.018737317724927],"rgb":[0.333333333333333315,0.866666666666666696,0.2],"xyz":[0.30199025086586534,0.538812782133305412,0.119407586540271199],"hpluv":[124.633900466047606,202.130538056106332,78.3924559312840898],"hsluv":[124.633900466047606,92.7228817840519355,78.3924559312840898]},"#55dd44":{"lch":[78.4964717161501255,103.064578059178857,125.904361390923313],"luv":[78.4964717161501255,-60.4405744101571756,83.4819993500804],"rgb":[0.333333333333333315,0.866666666666666696,0.266666666666666663],"xyz":[0.306448246110084255,0.540595980230993,0.142886361493157837],"hpluv":[125.904361390923313,195.867385876976442,78.4964717161501255],"hsluv":[125.904361390923313,87.4391970363123221,78.4964717161501255]},"#55dd55":{"lch":[78.635232286968062,98.0447483954765175,127.715012949239977],"luv":[78.635232286968062,-59.9773394353739,77.559599291037074],"rgb":[0.333333333333333315,0.866666666666666696,0.333333333333333315],"xyz":[0.31241066014944624,0.542980945846737728,0.174288408767131753],"hpluv":[127.715012949239977,187.771435495127037,78.635232286968062],"hsluv":[127.715012949239977,80.5594181605674891,78.635232286968062]},"#55dd66":{"lch":[78.8111684825228451,92.0067823672703469,130.218539636235505],"luv":[78.8111684825228451,-59.4092211255214551,70.2551951590567],"rgb":[0.333333333333333315,0.866666666666666696,0.4],"xyz":[0.319995655922954425,0.546014944156141,0.214236053174275715],"hpluv":[130.218539636235505,177.951388767985407,78.8111684825228451],"hsluv":[130.218539636235505,80.9267337864342693,78.8111684825228451]},"#55dd77":{"lch":[79.0263204832261863,85.1319563310668315,133.631202536406704],"luv":[79.0263204832261863,-58.7422260542947043,61.618186170487121],"rgb":[0.333333333333333315,0.866666666666666696,0.466666666666666674],"xyz":[0.329309668943156331,0.549740549364221898,0.263289855080673596],"hpluv":[133.631202536406704,166.66460441184762,79.0263204832261863],"hsluv":[133.631202536406704,81.3592233632428,79.0263204832261863]},"#55dd88":{"lch":[79.2823892178289,77.7115996221609322,138.259418470179128],"luv":[79.2823892178289,-57.9858175415186921,51.7371982221375],"rgb":[0.333333333333333315,0.866666666666666696,0.533333333333333326],"xyz":[0.340450086045100131,0.55419671620499944,0.321962718484245791],"hpluv":[138.259418470179128,154.371102046011828,79.2823892178289],"hsluv":[138.259418470179128,81.8514411788724,79.2823892178289]},"#55dd99":{"lch":[79.5807696492298504,70.1818875082800133,144.522564094970761],"luv":[79.5807696492298504,-57.1522092721799737,40.7323251181885624],"rgb":[0.333333333333333315,0.866666666666666696,0.6],"xyz":[0.353507050154172831,0.559419501848628653,0.390729396125363726],"hpluv":[144.522564094970761,141.828030979619143,79.5807696492298504],"hsluv":[144.522564094970761,82.3962440946128538,79.5807696492298504]},"#55ddaa":{"lch":[79.9225742847085,63.1747442044720913,152.933070337002903],"luv":[79.9225742847085,-56.2555676549498145,28.7464678372812266],"rgb":[0.333333333333333315,0.866666666666666696,0.66666666666666663],"xyz":[0.368564743119425386,0.56544257903472972,0.470033245742362271],"hpluv":[152.933070337002903,130.236824512138128,79.9225742847085],"hsluv":[152.933070337002903,82.9852754707380313,79.9225742847085]},"#55ddbb":{"lch":[80.3086513857730466,57.5612329714098649,163.927126105934775],"luv":[80.3086513857730466,-55.3111838467604926,15.9363886328987263],"rgb":[0.333333333333333315,0.866666666666666696,0.733333333333333282],"xyz":[0.385702335226762061,0.572297615877664478,0.560291230841004073],"hpluv":[163.927126105934775,121.406580229851471,80.3086513857730466],"hsluv":[163.927126105934775,83.6094665313934,80.3086513857730466]},"#55ddcc":{"lch":[80.7396004409482657,54.3905283694756534,177.403333860877041],"luv":[80.7396004409482657,-54.3346805898883076,2.46415533308082235],"rgb":[0.333333333333333315,0.866666666666666696,0.8],"xyz":[0.40499471067048376,0.580014566055153336,0.661897741511274229],"hpluv":[177.403333860877041,117.73427745544555,80.7396004409482657],"hsluv":[177.403333860877041,84.2595162876674664,80.7396004409482657]},"#55dddd":{"lch":[81.2157864208401605,54.5690893966631236,192.177050630061103],"luv":[81.2157864208401605,-53.3413100060750764,-11.5104371948595805],"rgb":[0.333333333333333315,0.866666666666666696,0.866666666666666696],"xyz":[0.426513036221117359,0.588621896275406842,0.775227589411280227],"hpluv":[192.177050630061103,121.625211000731653,81.2157864208401605],"hsluv":[192.177050630061103,84.9263164151063847,81.2157864208401605]},"#55ddee":{"lch":[81.73735371635685,58.3741450028570412,206.269517439458],"luv":[81.73735371635685,-52.3453816136692609,-25.8360567528002605],"rgb":[0.333333333333333315,0.866666666666666696,0.933333333333333348],"xyz":[0.450325216487292068,0.598146768381876859,0.90063840547980345],"hpluv":[206.269517439458,134.436687270459231,81.73735371635685],"hsluv":[206.269517439458,85.6012975649288421,81.73735371635685]},"#55ddff":{"lch":[82.3042402700550753,65.3293790133507599,218.171205050819623],"luv":[82.3042402700550753,-51.3598401525014268,-40.374429801293],"rgb":[0.333333333333333315,0.866666666666666696,1],"xyz":[0.476496264897123489,0.608615187745809583,1.0384725937715853],"hpluv":[218.171205050819623,156.046773818868189,82.3042402700550753],"hsluv":[218.171205050819623,99.9999999999958078,82.3042402700550753]},"#005500":{"lch":[30.6325595368381371,47.4104554868850059,127.715012949240474],"luv":[30.6325595368381371,-29.0026036892131067,37.5046699588244152],"rgb":[0,0.333333333333333315,0],"xyz":[0.0324835732820191528,0.0649671465640392215,0.0108278577606727468],"hpluv":[127.715012949240474,196.39488290021464,30.6325595368381371],"hsluv":[127.715012949240474,100.000000000002331,30.6325595368381371]},"#005511":{"lch":[30.7291805540017933,44.5531719728198325,130.030983014983661],"luv":[30.7291805540017933,-28.6566785608310113,34.1142185415534129],"rgb":[0,0.333333333333333315,0.0666666666666666657],"xyz":[0.033495238781656278,0.0653718127638940744,0.01615596272542838],"hpluv":[130.030983014983661,183.978458821492183,30.7291805540017933],"hsluv":[130.030983014983661,99.9999999999909335,30.7291805540017933]},"#005522":{"lch":[30.9072407208055395,39.7502752239143149,134.89425658266407],"luv":[30.9072407208055395,-28.0557665948475297,28.1595159964153758],"rgb":[0,0.333333333333333315,0.133333333333333331],"xyz":[0.0353705969201332932,0.0661219560192848888,0.0260328489214075726],"hpluv":[134.89425658266407,163.199653312489744,30.9072407208055395],"hsluv":[134.89425658266407,99.9999999999909903,30.9072407208055395]},"#005533":{"lch":[31.1975029455576802,33.2574057268159,144.773587953954916],"luv":[31.1975029455576802,-27.1672793055155033,19.1831689460880241],"rgb":[0,0.333333333333333315,0.2],"xyz":[0.0384583476525910337,0.067357056312268,0.0422950027790187227],"hpluv":[144.773587953954916,135.271984326190278,31.1975029455576802],"hsluv":[144.773587953954916,99.9999999999912177,31.1975029455576802]},"#005544":{"lch":[31.6103799108948778,27.1932751339722678,163.464109831123295],"luv":[31.6103799108948778,-26.0686058468900157,7.73963834500076331],"rgb":[0,0.333333333333333315,0.266666666666666663],"xyz":[0.0429163428968099142,0.0691402544099555816,0.0657737777319053613],"hpluv":[163.464109831123295,109.16191048912313,31.6103799108948778],"hsluv":[163.464109831123295,99.999999999991374,31.6103799108948778]},"#005555":{"lch":[32.1516370434520482,25.4370682812028797,192.17705063006116],"luv":[32.1516370434520482,-24.8647459548099441,-5.36552433088697445],"rgb":[0,0.333333333333333315,0.333333333333333315],"xyz":[0.0488787569361719063,0.0715252200257004145,0.0971758250058792628],"hpluv":[192.17705063006116,100.392967527320877,32.1516370434520482],"hsluv":[192.17705063006116,99.9999999999915,32.1516370434520482]},"#005566":{"lch":[32.8230722751799036,30.545644410021449,219.238547792689275],"luv":[32.8230722751799036,-23.6581848019048806,-19.3216636007977201],"rgb":[0,0.333333333333333315,0.4],"xyz":[0.0564637527096800845,0.074559218335103733,0.137123469413023225],"hpluv":[219.238547792689275,118.088984839520307,32.8230722751799036],"hsluv":[219.238547792689275,99.9999999999916298,32.8230722751799036]},"#005577":{"lch":[33.6230950493472065,40.3511971197610322,236.060106868306946],"luv":[33.6230950493472065,-22.5289967279924532,-33.4763112577822142],"rgb":[0,0.333333333333333315,0.466666666666666674],"xyz":[0.065777765729882,0.0782848235431845424,0.186177271319421134],"hpluv":[236.060106868306946,152.285327594300298,33.6230950493472065],"hsluv":[236.060106868306946,99.9999999999918,33.6230950493472065]},"#005588":{"lch":[34.5473308406039266,52.0529464564925703,245.569923252468897],"luv":[34.5473308406039266,-21.5281838547339461,-47.3924733973576764],"rgb":[0,0.333333333333333315,0.533333333333333326],"xyz":[0.076918182831825832,0.0827409903839621402,0.244850134722993301],"hpluv":[245.569923252468897,191.192188881903292,34.5473308406039266],"hsluv":[245.569923252468897,99.9999999999919709,34.5473308406039266]},"#005599":{"lch":[35.5892574919693772,64.2489447401961655,251.22324643469841],"luv":[35.5892574919693772,-20.6805523421639172,-60.8296116628390067],"rgb":[0,0.333333333333333315,0.6],"xyz":[0.0899751469408985316,0.0879637760275913,0.313616812364111208],"hpluv":[251.22324643469841,229.079590546614583,35.5892574919693772],"hsluv":[251.22324643469841,99.9999999999922125,35.5892574919693772]},"#0055aa":{"lch":[36.7408379507026,76.3552968047486189,254.821646708521541],"luv":[36.7408379507026,-19.9916927982920107,-73.6916791042243347],"rgb":[0,0.333333333333333315,0.66666666666666663],"xyz":[0.105032839906151088,0.0939868532136924,0.392920661981109809],"hpluv":[254.821646708521541,263.711724718685957,36.7408379507026],"hsluv":[254.821646708521541,99.9999999999921556,36.7408379507026]},"#0055bb":{"lch":[37.993106438468665,88.146943006458784,257.249085911334646],"luv":[37.993106438468665,-19.4551758320548949,-85.9731335635018],"rgb":[0,0.333333333333333315,0.733333333333333282],"xyz":[0.122170432013487734,0.100841890056627165,0.483178647079751555],"hpluv":[257.249085911334646,294.402692429224658,37.993106438468665],"hsluv":[257.249085911334646,99.9999999999924114,37.993106438468665]},"#0055cc":{"lch":[39.3366742314503384,99.5579220492412,258.963845190076711],"luv":[39.3366742314503384,-19.0582121518786707,-97.7167559446012888],"rgb":[0,0.333333333333333315,0.8],"xyz":[0.141462807457209461,0.108558840234115966,0.584785157750021711],"hpluv":[258.963845190076711,321.157087606315883,39.3366742314503384],"hsluv":[258.963845190076711,99.9999999999926,39.3366742314503384]},"#0055dd":{"lch":[40.7621365800243538,110.592821589198408,260.220233587680809],"luv":[40.7621365800243538,-18.7854624460211568,-108.985680654613518],"rgb":[0,0.333333333333333315,0.866666666666666696],"xyz":[0.162981133007843,0.1171661704543695,0.698115005650027709],"hpluv":[260.220233587680809,344.278042660470817,40.7621365800243538],"hsluv":[260.220233587680809,99.9999999999926672,40.7621365800243538]},"#0055ee":{"lch":[42.2603772648371105,121.285075365136905,261.168248695532611],"luv":[42.2603772648371105,-18.6213165580406681,-119.847052846418293],"rgb":[0,0.333333333333333315,0.933333333333333348],"xyz":[0.186793313274017742,0.126691042560839517,0.823525821718550932],"hpluv":[261.168248695532611,364.177675198016914,42.2603772648371105],"hsluv":[261.168248695532611,99.9999999999924256,42.2603772648371105]},"#0055ff":{"lch":[43.8227784910393,131.676969611306021,261.90102950371454],"luv":[43.8227784910393,-18.5511048350842884,-130.363648443170376],"rgb":[0,0.333333333333333315,1],"xyz":[0.212964361683849135,0.137159461924772241,0.961360010010332777],"hpluv":[261.90102950371454,381.28457852045068,43.8227784910393],"hsluv":[261.90102950371454,99.9999999999993321,43.8227784910393]},"#55ee00":{"lch":[83.4834241678481277,121.26988118033438,123.77813801339137],"luv":[83.4834241678481277,-67.423446821455,100.799121524975831],"rgb":[0.333333333333333315,0.933333333333333348,0],"xyz":[0.343194252835808289,0.630780425066107542,0.103666700302096418],"hpluv":[123.77813801339137,313.542875178701877,83.4834241678481277],"hsluv":[123.77813801339137,100.000000000002402,83.4834241678481277]},"#55ee11":{"lch":[83.5046935730824487,120.419265504422668,124.002811201886018],"luv":[83.5046935730824487,-67.3424968648776456,99.8287915414615412],"rgb":[0.333333333333333315,0.933333333333333348,0.0666666666666666657],"xyz":[0.344205918335445393,0.63118509126596245,0.108994805266852055],"hpluv":[124.002811201886018,311.80236567126093,83.5046935730824487],"hsluv":[124.002811201886018,98.9375412624106616,83.5046935730824487]},"#55ee22":{"lch":[83.5440973470955868,118.856748008926118,124.425313598414533],"luv":[83.5440973470955868,-67.1934622190367463,98.0406302625408728],"rgb":[0.333333333333333315,0.933333333333333348,0.133333333333333331],"xyz":[0.34608127647392245,0.631935234521353251,0.118871691462831247],"hpluv":[124.425313598414533,308.59848358059196,83.5440973470955868],"hsluv":[124.425313598414533,96.9807587800033133,83.5440973470955868]},"#55ee33":{"lch":[83.6089072227085524,116.32446068797897,125.138397832270286],"luv":[83.6089072227085524,-66.950941309724243,95.1259775880964469],"rgb":[0.333333333333333315,0.933333333333333348,0.2],"xyz":[0.349169027206380156,0.633170334814336377,0.135133845320442397],"hpluv":[125.138397832270286,303.387603747434184,83.6089072227085524],"hsluv":[125.138397832270286,93.7945051225822084,83.6089072227085524]},"#55ee44":{"lch":[83.7023291233000748,112.756808619009803,126.207644663357115],"luv":[83.7023291233000748,-66.6069499756988535,90.9813832873448547],"rgb":[0.333333333333333315,0.933333333333333348,0.266666666666666663],"xyz":[0.353627022450599071,0.634953532912023944,0.158612620273329036],"hpluv":[126.207644663357115,296.007020538140409,83.7023291233000748],"hsluv":[126.207644663357115,89.2707337544585,83.7023291233000748]},"#55ee55":{"lch":[83.8270046653184,108.148092962556504,127.715012949240077],"luv":[83.8270046653184,-66.1579022543843,85.5519840841642747],"rgb":[0.333333333333333315,0.933333333333333348,0.333333333333333315],"xyz":[0.359589436489961056,0.637338498527768693,0.190014667547302951],"hpluv":[127.715012949240077,286.404562223907249,83.8270046653184],"hsluv":[127.715012949240077,83.3573838846113091,83.8270046653184]},"#55ee66":{"lch":[83.985160091985378,102.554744038676162,129.769393513035965],"luv":[83.985160091985378,-65.6041880698479645,78.8261760618539853],"rgb":[0.333333333333333315,0.933333333333333348,0.4],"xyz":[0.367174432263469241,0.640372496837172,0.229962311954446885],"hpluv":[129.769393513035965,274.647728218817576,83.985160091985378],"hsluv":[129.769393513035965,83.6273111034757477,83.985160091985378]},"#55ee77":{"lch":[84.1786855608653752,96.1019099790829756,132.519661951802362],"luv":[84.1786855608653752,-64.9498200787083,70.8314758661090451],"rgb":[0.333333333333333315,0.933333333333333348,0.466666666666666674],"xyz":[0.376488445283671147,0.644098102045252863,0.279016113860844794],"hpluv":[132.519661951802362,260.948457539577589,84.1786855608653752],"hsluv":[132.519661951802362,83.9470254314832687,84.1786855608653752]},"#55ee88":{"lch":[84.4091822183787741,88.9952087097784,136.170997575445568],"luv":[84.4091822183787741,-64.2020140446184371,61.6299323860706],"rgb":[0.333333333333333315,0.933333333333333348,0.533333333333333326],"xyz":[0.387628862385614947,0.648554268886030405,0.337688977264417],"hpluv":[136.170997575445568,245.709397001158351,84.4091822183787741],"hsluv":[136.170997575445568,84.3134084109568533,84.4091822183787741]},"#55ee99":{"lch":[84.6779925165317877,81.540352796223317,141.002136712429774],"luv":[84.6779925165317877,-63.3706695007570531,51.3126434824633151],"rgb":[0.333333333333333315,0.933333333333333348,0.6],"xyz":[0.400685826494687647,0.653777054529659618,0.406455654905534869],"hpluv":[141.002136712429774,229.604367075154897,84.6779925165317877],"hsluv":[141.002136712429774,84.7220894550445394,84.6779925165317877]},"#55eeaa":{"lch":[84.9862212486181363,74.1734332109310373,147.37159021859884],"luv":[84.9862212486181363,-62.4677637576075426,39.9934580327855755],"rgb":[0.333333333333333315,0.933333333333333348,0.66666666666666663],"xyz":[0.415743519459940203,0.659800131715760685,0.48575950452253347],"hpluv":[147.37159021859884,213.709694911287,84.9862212486181363],"hsluv":[147.37159021859884,85.1677250765186358,84.9862212486181363]},"#55eebb":{"lch":[85.334751323756052,67.4984157699475418,155.676120933413],"luv":[85.334751323756052,-61.5066955643592337,27.8022037293077737],"rgb":[0.333333333333333315,0.933333333333333348,0.733333333333333282],"xyz":[0.432881111567276877,0.666655168558695443,0.576017489621175272],"hpluv":[155.676120933413,199.690784145783283,85.334751323756052],"hsluv":[155.676120933413,85.6443005177139298,85.334751323756052]},"#55eecc":{"lch":[85.7242566025865784,62.3040769944455,166.184583472908372],"luv":[85.7242566025865784,-60.5016239571924643,14.8778865660505755],"rgb":[0.333333333333333315,0.933333333333333348,0.8],"xyz":[0.452173487010998576,0.674372118736184301,0.677624000291445427],"hpluv":[166.184583472908372,189.979166061651426,85.7242566025865784],"hsluv":[166.184583472908372,86.1454332210543186,85.7242566025865784]},"#55eedd":{"lch":[86.1552131978466349,59.4824491826881427,178.687660418725557],"luv":[86.1552131978466349,-59.4668469392298462,1.36230535390821395],"rgb":[0.333333333333333315,0.933333333333333348,0.866666666666666696],"xyz":[0.473691812561632175,0.682979448956437807,0.790953848191451425],"hpluv":[178.687660418725557,187.703134777137279,86.1552131978466349],"hsluv":[178.687660418725557,86.6646578889921,86.1552131978466349]},"#55eeee":{"lch":[86.6279101052896578,59.7608483004272202,192.177050630061245],"luv":[86.6279101052896578,-58.4162567245265265,-12.6055519466972967],"rgb":[0.333333333333333315,0.933333333333333348,0.933333333333333348],"xyz":[0.497503992827806885,0.692504321062907824,0.916364664259974648],"hpluv":[192.177050630061245,196.025490067494644,86.6279101052896578],"hsluv":[192.177050630061245,87.195676441965972,86.6279101052896578]},"#55eeff":{"lch":[87.1424596935915901,63.3545065705612274,205.119112492248092],"luv":[87.1424596935915901,-57.3628964007582169,-26.8940814923128677],"rgb":[0.333333333333333315,0.933333333333333348,1],"xyz":[0.523675041237638306,0.702972740426840548,1.05419885255175649],"hpluv":[205.119112492248092,217.06231600799947,87.1424596935915901],"hsluv":[205.119112492248092,99.9999999999933,87.1424596935915901]},"#006600":{"lch":[36.9339903888407548,57.1632711650289735,127.71501294924046],"luv":[36.9339903888407548,-34.9687359497521086,45.2197642227726249],"rgb":[0,0.4,0],"xyz":[0.0475116309878656218,0.0950232619757325619,0.0158372103292880942],"hpluv":[127.71501294924046,196.394882900214554,36.9339903888407548],"hsluv":[127.71501294924046,100.000000000002331,36.9339903888407548]},"#006611":{"lch":[37.0090255636121412,54.7765813256580216,129.276595687178855],"luv":[37.0090255636121412,-34.6771211058740789,42.4024897091546933],"rgb":[0,0.4,0.0666666666666666657],"xyz":[0.04852329648750274,0.0954279281755874148,0.0211653152940437239],"hpluv":[129.276595687178855,187.813410896691579,37.0090255636121412],"hsluv":[129.276595687178855,99.9999999999908908,37.0090255636121412]},"#006622":{"lch":[37.1475616040544949,50.6324758020482761,132.428423847637788],"luv":[37.1475616040544949,-34.160143827310165,37.3728802682170453],"rgb":[0,0.4,0.133333333333333331],"xyz":[0.0503986546259797621,0.0961780714309782292,0.0310422014900229234],"hpluv":[132.428423847637788,172.957013965329963,37.1475616040544949],"hsluv":[132.428423847637788,99.9999999999909619,37.1475616040544949]},"#006633":{"lch":[37.3740982281225911,44.601943170857588,138.432874640413417],"luv":[37.3740982281225911,-33.3702331720845464,29.5932572160807972],"rgb":[0,0.4,0.2],"xyz":[0.0534864053584375,0.0974131717239613421,0.0473043553476340667],"hpluv":[138.432874640413417,151.43364776149042,37.3740982281225911],"hsluv":[138.432874640413417,99.9999999999910187,37.3740982281225911]},"#006644":{"lch":[37.6978110334583292,37.6830106217376226,149.139540405640531],"luv":[37.6978110334583292,-32.3478161181420845,19.3294615006434647],"rgb":[0,0.4,0.266666666666666663],"xyz":[0.0579444006026563832,0.099196369821648922,0.0707831303005207],"hpluv":[149.139540405640531,126.843666215367492,37.6978110334583292],"hsluv":[149.139540405640531,99.9999999999911893,37.6978110334583292]},"#006655":{"lch":[38.1247572916394191,31.9621551107412678,167.158861879927684],"luv":[38.1247572916394191,-31.1627826377188839,7.10354401671241],"rgb":[0,0.4,0.333333333333333315],"xyz":[0.0639068146420183752,0.101581335437393755,0.102185177574494607],"hpluv":[167.158861879927684,106.382034992292617,38.1247572916394191],"hsluv":[167.158861879927684,99.9999999999912461,38.1247572916394191]},"#006666":{"lch":[38.6583399620500714,30.584907136256998,192.177050630061132],"luv":[38.6583399620500714,-29.8967608054288689,-6.45137488264605441],"rgb":[0,0.4,0.4],"xyz":[0.0714918104155265466,0.104615333746797073,0.142132821981638569],"hpluv":[192.177050630061132,100.392967527320849,38.6583399620500714],"hsluv":[192.177050630061132,99.9999999999914877,38.6583399620500714]},"#006677":{"lch":[39.2996251720959648,35.3400629634721852,215.899751113488037],"luv":[39.2996251720959648,-28.6270125920824867,-20.7223116547099835],"rgb":[0,0.4,0.466666666666666674],"xyz":[0.080805823435728466,0.108340938954877883,0.191186623888036478],"hpluv":[215.899751113488037,114.108563264217921,39.2996251720959648],"hsluv":[215.899751113488037,99.999999999991644,39.2996251720959648]},"#006688":{"lch":[40.0476371065618721,44.619030030948764,232.088426656893603],"luv":[40.0476371065618721,-27.4159210327312195,-35.2026293738089109],"rgb":[0,0.4,0.533333333333333326],"xyz":[0.0919462405376723,0.112797105795655481,0.249859487291608645],"hpluv":[232.088426656893603,141.378234692038774,40.0476371065618721],"hsluv":[232.088426656893603,99.9999999999918145,40.0476371065618721]},"#006699":{"lch":[40.8996671875350728,56.0796471869528546,242.024131169727298],"luv":[40.8996671875350728,-26.3069429553173038,-49.5264735364712863],"rgb":[0,0.4,0.6],"xyz":[0.105003204646745008,0.118019891439284638,0.318626164932726552],"hpluv":[242.024131169727298,173.990215160848891,40.8996671875350728],"hsluv":[242.024131169727298,99.9999999999919,40.8996671875350728]},"#0066aa":{"lch":[41.8515997707465104,68.3303466488807345,248.245335088520562],"luv":[41.8515997707465104,-25.3254853434547229,-63.4638169768779861],"rgb":[0,0.4,0.66666666666666663],"xyz":[0.12006089761199755,0.124042968625385747,0.397930014549725153],"hpluv":[248.245335088520562,207.176688473106537,41.8515997707465104],"hsluv":[248.245335088520562,99.9999999999921,41.8515997707465104]},"#0066bb":{"lch":[42.8982420202673396,80.6980154219041452,252.339105133311591],"luv":[42.8982420202673396,-24.4823887435570384,-76.8946183711398],"rgb":[0,0.4,0.733333333333333282],"xyz":[0.137198489719334182,0.130898005468320505,0.488187999648366899],"hpluv":[252.339105133311591,238.705643004687346,42.8982420202673396],"hsluv":[252.339105133311591,99.9999999999922125,42.8982420202673396]},"#0066cc":{"lch":[44.0336413015701211,92.8728169416488356,255.165448618736946],"luv":[44.0336413015701211,-23.7781103155697018,-89.7772888680517696],"rgb":[0,0.4,0.8],"xyz":[0.156490865163055937,0.138614955645809307,0.589794510318637],"hpluv":[255.165448618736946,267.63526922347819,44.0336413015701211],"hsluv":[255.165448618736946,99.9999999999922835,44.0336413015701211]},"#0066dd":{"lch":[45.2513748624169807,104.723900430114114,257.197154574648096],"luv":[45.2513748624169807,-23.2064943358636171,-102.120291528843495],"rgb":[0,0.4,0.866666666666666696],"xyz":[0.17800919071368948,0.147222285866062841,0.703124358218643],"hpluv":[257.197154574648096,293.665789717253858,45.2513748624169807],"hsluv":[257.197154574648096,99.9999999999923119,45.2513748624169807]},"#0066ee":{"lch":[46.5448008930790422,116.210429262859975,258.70668283343889],"luv":[46.5448008930790422,-22.7576936505684415,-113.960305585607557],"rgb":[0,0.4,0.933333333333333348],"xyz":[0.201821370979864217,0.156747157972532858,0.828535174287166276],"hpluv":[258.70668283343889,316.82048544727013,46.5448008930790422],"hsluv":[258.70668283343889,99.9999999999923119,46.5448008930790422]},"#0066ff":{"lch":[47.9072652547968758,127.336469583599694,259.859032010401279],"luv":[47.9072652547968758,-22.4202120236612075,-125.347160234402949],"rgb":[0,0.4,1],"xyz":[0.227992419389695611,0.167215577336465582,0.966369362578948121],"hpluv":[259.859032010401279,337.280125749862,47.9072652547968758],"hsluv":[259.859032010401279,99.9999999999992326,47.9072652547968758]},"#55ff00":{"lch":[88.6611895097861691,129.940408372856581,124.363532639485271],"luv":[88.6611895097861691,-73.3437881830395213,107.262288168144963],"rgb":[0.333333333333333315,1,0],"xyz":[0.395046625265482121,0.734485169925456649,0.120950824445320529],"hpluv":[124.363532639485271,511.214684976108288,88.6611895097861691],"hsluv":[124.363532639485271,100.000000000002203,88.6611895097861691]},"#55ff11":{"lch":[88.6804070841335488,129.16615931328721,124.557188606571273],"luv":[88.6804070841335488,-73.2667318726085597,106.376137890284312],"rgb":[0.333333333333333315,1,0.0666666666666666657],"xyz":[0.396058290765119225,0.734889836125311557,0.126278929410076152],"hpluv":[124.557188606571273,509.111714190739917,88.6804070841335488],"hsluv":[124.557188606571273,99.999999999991374,88.6804070841335488]},"#55ff22":{"lch":[88.7160126920472862,127.742171235629925,124.920549061750862],"luv":[88.7160126920472862,-73.1247263453711867,104.741762009752222],"rgb":[0.333333333333333315,1,0.133333333333333331],"xyz":[0.397933648903596282,0.735639979380702358,0.136155815606055358],"hpluv":[124.920549061750862,505.235489858807625,88.7160126920472862],"hsluv":[124.920549061750862,99.9999999999912461,88.7160126920472862]},"#55ff33":{"lch":[88.7745841250638819,125.429409451765778,125.531442964179078],"luv":[88.7745841250638819,-72.893256299655377,102.074041467218606],"rgb":[0.333333333333333315,1,0.2],"xyz":[0.401021399636054,0.736875079673685485,0.152417969463666508],"hpluv":[125.531442964179078,498.916518871762833,88.7745841250638819],"hsluv":[125.531442964179078,99.9999999999915445,88.7745841250638819]},"#55ff44":{"lch":[88.8590323294941271,122.159967165607114,126.442013329478428],"luv":[88.8590323294941271,-72.5641116581323189,98.2726171279075658],"rgb":[0.333333333333333315,1,0.266666666666666663],"xyz":[0.405479394880272903,0.738658277771373,0.175896744416553147],"hpluv":[126.442013329478428,489.934204596741552,88.8590323294941271],"hsluv":[126.442013329478428,99.9999999999914735,88.8590323294941271]},"#55ff55":{"lch":[88.9717666926620154,117.915518658848484,127.715012949240119],"luv":[88.9717666926620154,-72.1329719647303,93.2786357968462],"rgb":[0.333333333333333315,1,0.333333333333333315],"xyz":[0.411441808919634888,0.7410432433871178,0.207298791690527062],"hpluv":[127.715012949240119,478.187207442594797,88.9717666926620154],"hsluv":[127.715012949240119,99.9999999999912461,88.9717666926620154]},"#55ff66":{"lch":[89.1148309932425,112.728028648536309,129.430986513959965],"luv":[89.1148309932425,-71.5990188667543919,87.0700232014633713],"rgb":[0.333333333333333315,1,0.4],"xyz":[0.419026804693143073,0.744077241696521119,0.247246436097671],"hpluv":[129.430986513959965,463.701047487447568,89.1148309932425],"hsluv":[129.430986513959965,99.999999999991374,89.1148309932425]},"#55ff77":{"lch":[89.2899761450384233,106.6837193332601,131.696695826109391],"luv":[89.2899761450384233,-70.9646547782272705,79.6582308552282825],"rgb":[0.333333333333333315,1,0.466666666666666674],"xyz":[0.428340817713345,0.747802846904602,0.296300238004068905],"hpluv":[131.696695826109391,446.653165807945641,89.2899761450384233],"hsluv":[131.696695826109391,99.9999999999911466,89.2899761450384233]},"#55ff88":{"lch":[89.4987035327786344,99.9302046144725722,134.655503696120093],"luv":[89.4987035327786344,-70.2351927280585784,71.0849034376696807],"rgb":[0.333333333333333315,1,0.533333333333333326],"xyz":[0.439481234815288779,0.752259013745379512,0.354973101407641101],"hpluv":[134.655503696120093,427.420708471833962,89.4987035327786344],"hsluv":[134.655503696120093,99.9999999999910472,89.4987035327786344]},"#55ff99":{"lch":[89.7422928839939544,92.6881300553494185,138.499225093055145],"luv":[89.7422928839939544,-69.4184746025382395,61.4179520744067275],"rgb":[0.333333333333333315,1,0.6],"xyz":[0.452538198924361534,0.757481799389008725,0.423739779048759],"hpluv":[138.499225093055145,406.664135605650245,89.7422928839939544],"hsluv":[138.499225093055145,99.9999999999909193,89.7422928839939544]},"#55ffaa":{"lch":[90.021821419032733,85.2692799565717081,143.477548510033301],"luv":[90.021821419032733,-68.524415632830582,50.7469660816416095],"rgb":[0.333333333333333315,1,0.66666666666666663],"xyz":[0.467595891889614035,0.763504876575109792,0.503043628665757581],"hpluv":[143.477548510033301,385.467603776639692,90.021821419032733],"hsluv":[143.477548510033301,99.9999999999908908,90.021821419032733]},"#55ffbb":{"lch":[90.3381779071049635,78.1017696608261929,149.892156464581973],"luv":[90.3381779071049635,-67.5644942943643514,39.178125719584358],"rgb":[0.333333333333333315,1,0.733333333333333282],"xyz":[0.484733483996950709,0.770359913418044551,0.593301613764399383],"hpluv":[149.892156464581973,365.560319764238727,90.3381779071049635],"hsluv":[149.892156464581973,99.9999999999906,90.3381779071049635]},"#55ffcc":{"lch":[90.6920737330737836,71.7555158590460849,158.04408297895796],"luv":[90.6920737330737836,-66.5512174426729217,26.828893251416094],"rgb":[0.333333333333333315,1,0.8],"xyz":[0.504025859440672463,0.778076863595533408,0.694908124434669539],"hpluv":[158.04408297895796,349.620992563925881,90.6920737330737836],"hsluv":[158.04408297895796,99.9999999999905214,90.6920737330737836]},"#55ffdd":{"lch":[91.0840522607878142,66.9403052018893874,168.083008151042208],"luv":[91.0840522607878142,-65.4975936461766,13.8227959213187273],"rgb":[0.333333333333333315,1,0.866666666666666696],"xyz":[0.525544184991306,0.786684193815786914,0.808237972334675536],"hpluv":[168.083008151042208,341.570927955438208,91.0840522607878142],"hsluv":[168.083008151042208,99.9999999999901092,91.0840522607878142]},"#55ffee":{"lch":[91.5144973031429,64.4172738793593,179.746868091755],"luv":[91.5144973031429,-64.4166452130874347,0.284593639433804613],"rgb":[0.333333333333333315,1,0.933333333333333348],"xyz":[0.549356365257480661,0.796209065922256931,0.933648788403198759],"hpluv":[179.746868091755,346.559914030924404,91.5144973031429],"hsluv":[179.746868091755,99.9999999999898108,91.5144973031429]},"#55ffff":{"lch":[91.9836412143362,64.7784688708661918,192.177050630061103],"luv":[91.9836412143362,-63.3209831419883,-13.663935128132529],"rgb":[0.333333333333333315,1,1],"xyz":[0.575527413667312082,0.806677485286189655,1.07148297669498049],"hpluv":[192.177050630061103,370.276433987554753,91.9836412143362],"hsluv":[192.177050630061103,99.9999999999890719,91.9836412143362]},"#007700":{"lch":[43.052730924646589,66.6333343982289534,127.715012949240503],"luv":[43.052730924646589,-40.7618988300426395,52.7111834129681611],"rgb":[0,0.466666666666666674,0],"xyz":[0.0659653690412832505,0.131930738082568333,0.0219884563470937981],"hpluv":[127.715012949240503,196.394882900214441,43.052730924646589],"hsluv":[127.715012949240503,100.000000000002217,43.052730924646589]},"#007711":{"lch":[43.1130460407029,64.6129906803504497,128.830381027920708],"luv":[43.1130460407029,-40.513441406878222,50.333881531534],"rgb":[0,0.466666666666666674,0.0666666666666666657],"xyz":[0.0669770345409203688,0.132335404282423186,0.0273165613118494313],"hpluv":[128.830381027920708,190.173702516526191,43.1130460407029],"hsluv":[128.830381027920708,99.9999999999908908,43.1130460407029]},"#007722":{"lch":[43.2245297597171856,61.038201507507992,131.028383581415682],"luv":[43.2245297597171856,-40.0674788501528809,46.0462721820529381],"rgb":[0,0.466666666666666674,0.133333333333333331],"xyz":[0.0688523926793974,0.133085547537814014,0.0371934475078286239],"hpluv":[131.028383581415682,179.188765673473426,43.2245297597171856],"hsluv":[131.028383581415682,99.9999999999909193,43.2245297597171856]},"#007733":{"lch":[43.4071769639209251,55.6324991773261601,135.049443606961],"luv":[43.4071769639209251,-39.3720497464739694,39.3041558041433419],"rgb":[0,0.466666666666666674,0.2],"xyz":[0.0719401434118551314,0.134320647830797113,0.0534556013654397671],"hpluv":[135.049443606961,162.632131787412106,43.4071769639209251],"hsluv":[135.049443606961,99.9999999999909193,43.4071769639209251]},"#007744":{"lch":[43.6689123670523855,48.8909209361139787,141.845848120172377],"luv":[43.6689123670523855,-38.4454486392046704,30.2038015639029105],"rgb":[0,0.466666666666666674,0.266666666666666663],"xyz":[0.076398138656074,0.136103845928484707,0.0769343763183264],"hpluv":[141.845848120172377,142.067640978907804,43.6689123670523855],"hsluv":[141.845848120172377,99.9999999999910614,43.6689123670523855]},"#007755":{"lch":[44.0154249216106,41.9153980271179,152.953344682219807],"luv":[44.0154249216106,-37.3313854656975224,19.0595973457790286],"rgb":[0,0.466666666666666674,0.333333333333333315],"xyz":[0.082360552695436,0.13848881154422954,0.108336423592300321],"hpluv":[152.953344682219807,120.839250305189026,44.0154249216106],"hsluv":[152.953344682219807,99.9999999999912461,44.0154249216106]},"#007766":{"lch":[44.4505333250062549,36.6388362985735725,170.062665906075836],"luv":[44.4505333250062549,-36.0891470448365865,6.32279929223085357],"rgb":[0,0.466666666666666674,0.4],"xyz":[0.0899455484689441753,0.141522809853632831,0.148284067999444269],"hpluv":[170.062665906075836,104.593337643625588,44.4505333250062549],"hsluv":[170.062665906075836,99.9999999999913314,44.4505333250062549]},"#007777":{"lch":[44.9764013416840669,35.58350047386471,192.17705063006116],"luv":[44.9764013416840669,-34.7828880940388601,-7.50574458738768],"rgb":[0,0.466666666666666674,0.466666666666666674],"xyz":[0.0992595614891461,0.145248415061713654,0.197337869905842178],"hpluv":[192.17705063006116,100.392967527320835,44.9764013416840669],"hsluv":[192.17705063006116,99.9999999999914451,44.9764013416840669]},"#007788":{"lch":[45.5937085159301603,40.0276538709377,213.25546015720218],"luv":[45.5937085159301603,-33.4724811425817,-21.9500815618326577],"rgb":[0,0.466666666666666674,0.533333333333333326],"xyz":[0.110399978591089923,0.149704581902491252,0.256010733309414373],"hpluv":[213.25546015720218,111.402399127386914,45.5937085159301603],"hsluv":[213.25546015720218,99.9999999999916156,45.5937085159301603]},"#007799":{"lch":[46.3018156057360244,48.7595612734022907,228.659125647543163],"luv":[46.3018156057360244,-32.2075160625452597,-36.6083422822662357],"rgb":[0,0.466666666666666674,0.6],"xyz":[0.123456942700162636,0.154927367546120409,0.324777410950532253],"hpluv":[228.659125647543163,133.62911578541167,46.3018156057360244],"hsluv":[228.659125647543163,99.9999999999917577,46.3018156057360244]},"#0077aa":{"lch":[47.0989379645613795,59.8445186957143,238.773531847525192],"luv":[47.0989379645613795,-31.0247207616125031,-51.1745358511991597],"rgb":[0,0.466666666666666674,0.66666666666666663],"xyz":[0.138514635665415164,0.160950444732221504,0.404081260567530853],"hpluv":[238.773531847525192,161.232500989130415,47.0989379645613795],"hsluv":[238.773531847525192,99.999999999991914,47.0989379645613795]},"#0077bb":{"lch":[47.9823278818304146,71.9659744020705432,245.408717039049918],"luv":[47.9823278818304146,-29.9480972873728,-65.4386196408934495],"rgb":[0,0.466666666666666674,0.733333333333333282],"xyz":[0.155652227772751839,0.167805481575156262,0.4943392456661726],"hpluv":[245.408717039049918,190.32034768447943,47.9823278818304146],"hsluv":[245.408717039049918,99.9999999999920561,47.9823278818304146]},"#0077cc":{"lch":[48.9484610491917067,84.4081580704908276,249.9122747909542],"luv":[48.9484610491917067,-28.9906993044602252,-79.2734287305105454],"rgb":[0,0.466666666666666674,0.8],"xyz":[0.174944603216473565,0.175522431752645064,0.595945756336442756],"hpluv":[249.9122747909542,218.818838178067409,48.9484610491917067],"hsluv":[249.9122747909542,99.9999999999922125,48.9484610491917067]},"#0077dd":{"lch":[49.9932200675849,96.8017840095652389,253.089738624096071],"luv":[49.9932200675849,-28.15707849035525,-92.6162206005108715],"rgb":[0,0.466666666666666674,0.866666666666666696],"xyz":[0.196462928767107109,0.184129761972898598,0.709275604236448753],"hpluv":[253.089738624096071,245.70363248193695,49.9932200675849],"hsluv":[253.089738624096071,99.9999999999921272,49.9932200675849]},"#0077ee":{"lch":[51.1120678627821547,108.963279527823246,255.411176145550684],"luv":[51.1120678627821547,-27.4457353077348785,-105.450120430828804],"rgb":[0,0.466666666666666674,0.933333333333333348],"xyz":[0.220275109033281846,0.193654634079368643,0.834686420304972],"hpluv":[255.411176145550684,270.517920771775039,51.1120678627821547],"hsluv":[255.411176145550684,99.9999999999922551,51.1120678627821547]},"#0077ff":{"lch":[52.300205122294,120.810007187166491,257.158195690943],"luv":[52.300205122294,-26.851223719183885,-117.788240590245493],"rgb":[0,0.466666666666666674,1],"xyz":[0.24644615744311324,0.204123053443301339,0.972520608596753822],"hpluv":[257.158195690943,293.11554041762389,52.300205122294],"hsluv":[257.158195690943,99.9999999999991189,52.300205122294]},"#008800":{"lch":[49.0166039301270473,75.8637069146273291,127.71501294924046],"luv":[49.0166039301270473,-46.4084346679225348,60.0129920808956214],"rgb":[0,0.533333333333333326,0],"xyz":[0.0880377387662537,0.176075477532509878,0.0293459129220837445],"hpluv":[127.71501294924046,196.394882900214583,49.0166039301270473],"hsluv":[127.71501294924046,100.000000000002359,49.0166039301270473]},"#008811":{"lch":[49.066374048408079,74.1307167522113133,128.546257021813432],"luv":[49.066374048408079,-46.1942790787678064,57.9780281364371461],"rgb":[0,0.533333333333333326,0.0666666666666666657],"xyz":[0.0890494042658908219,0.17648014373236473,0.0346740178868393742],"hpluv":[128.546257021813432,191.713881645209739,49.066374048408079],"hsluv":[128.546257021813432,99.9999999999908908,49.066374048408079]},"#008822":{"lch":[49.1584337135343503,71.0276132120671,130.159311596065152],"luv":[49.1584337135343503,-45.8067815452400779,54.2831521106656112],"rgb":[0,0.533333333333333326,0.133333333333333331],"xyz":[0.090924762404367851,0.177230286987755559,0.0445509040828185737],"hpluv":[130.159311596065152,183.344763498744726,49.1584337135343503],"hsluv":[130.159311596065152,99.9999999999909335,49.1584337135343503]},"#008833":{"lch":[49.3094443496477197,66.226384742663825,133.033255321350083],"luv":[49.3094443496477197,-45.1943905199784481,48.4086882864121648],"rgb":[0,0.533333333333333326,0.2],"xyz":[0.0940125131368255845,0.178465387280738658,0.060813057940429717],"hpluv":[133.033255321350083,170.427732437953466,49.3094443496477197],"hsluv":[133.033255321350083,99.9999999999909903,49.3094443496477197]},"#008844":{"lch":[49.5262444349700388,59.9709063982634589,137.708745518338219],"luv":[49.5262444349700388,-44.3625073014275202,40.3543995143041],"rgb":[0,0.533333333333333326,0.266666666666666663],"xyz":[0.0984705083810444581,0.180248585378426252,0.0842918328933163485],"hpluv":[137.708745518338219,153.654237765673173,49.5262444349700388],"hsluv":[137.708745518338219,99.9999999999910756,49.5262444349700388]},"#008855":{"lch":[49.8139833497656355,52.876539169604392,145.043769270071607],"luv":[49.8139833497656355,-43.3370811793054074,30.2956397756013871],"rgb":[0,0.533333333333333326,0.333333333333333315],"xyz":[0.104432922420406457,0.182633550994171084,0.115693880167290264],"hpluv":[145.043769270071607,134.694876863850226,49.8139833497656355],"hsluv":[145.043769270071607,99.9999999999911893,49.8139833497656355]},"#008866":{"lch":[50.1764284055384593,46.0546718070978613,156.264738854980266],"luv":[50.1764284055384593,-42.1591397878491918,18.5375221539472825],"rgb":[0,0.533333333333333326,0.4],"xyz":[0.112017918193914628,0.185667549303574375,0.155641524574434226],"hpluv":[156.264738854980266,116.469784961641182,50.1764284055384593],"hsluv":[156.264738854980266,99.9999999999912461,50.1764284055384593]},"#008877":{"lch":[50.6161324463586766,41.2412500498738694,172.391379993232761],"luv":[50.6161324463586766,-40.8781468825216336,5.46056893805106114],"rgb":[0,0.533333333333333326,0.466666666666666674],"xyz":[0.121331931214116548,0.189393154511655198,0.204695326480832135],"hpluv":[172.391379993232761,103.390869865470918,50.6161324463586766],"hsluv":[172.391379993232761,99.9999999999913456,50.6161324463586766]},"#008888":{"lch":[51.1345503085294695,40.4555776108317602,192.177050630061132],"luv":[51.1345503085294695,-39.545345738280993,-8.53342781453345],"rgb":[0,0.533333333333333326,0.533333333333333326],"xyz":[0.132472348316060362,0.193849321352432796,0.263368189884404302],"hpluv":[192.177050630061132,100.392967527320849,51.1345503085294695],"hsluv":[192.177050630061132,99.9999999999914877,51.1345503085294695]},"#008899":{"lch":[51.7321394091786715,44.6308971675799881,211.11913642158629],"luv":[51.7321394091786715,-38.208266400248,-23.066108485628412],"rgb":[0,0.533333333333333326,0.6],"xyz":[0.145529312425133089,0.199072106996061954,0.332134867525522237],"hpluv":[211.11913642158629,109.474886689832829,51.7321394091786715],"hsluv":[211.11913642158629,99.999999999991573,51.7321394091786715]},"#0088aa":{"lch":[52.4084594351014914,52.8385448128107598,225.694192047300788],"luv":[52.4084594351014914,-36.9070805124816346,-37.8124215831333572],"rgb":[0,0.533333333333333326,0.66666666666666663],"xyz":[0.160587005390385618,0.205095184182163048,0.411438717142520782],"hpluv":[225.694192047300788,127.934825585488483,52.4084594351014914],"hsluv":[225.694192047300788,99.9999999999917,52.4084594351014914]},"#0088bb":{"lch":[53.1622766119302952,63.4852929684367,235.812153399491365],"luv":[53.1622766119302952,-35.672889398211332,-52.5150205681309856],"rgb":[0,0.533333333333333326,0.733333333333333282],"xyz":[0.177724597497722292,0.211950221025097807,0.501696702241162584],"hpluv":[235.812153399491365,151.533580059798538,53.1622766119302952],"hsluv":[235.812153399491365,99.9999999999918572,53.1622766119302952]},"#0088cc":{"lch":[53.9916730817088961,75.3609801883338406,242.731381598031476],"luv":[53.9916730817088961,-34.5275961267233455,-66.9859868976812578],"rgb":[0,0.533333333333333326,0.8],"xyz":[0.197016972941444019,0.219667171202586609,0.60330321291143274],"hpluv":[242.731381598031476,177.116523654060018,53.9916730817088961],"hsluv":[242.731381598031476,99.9999999999919282,53.9916730817088961]},"#0088dd":{"lch":[54.894159312243417,87.7409205251226,247.565131731451658],"luv":[54.894159312243417,-33.4848266090853,-81.1001573460580545],"rgb":[0,0.533333333333333326,0.866666666666666696],"xyz":[0.218535298492077562,0.228274501422840143,0.716633060811438738],"hpluv":[247.565131731451658,202.822146488853946,54.894159312243417],"hsluv":[247.565131731451658,99.9999999999921414,54.894159312243417]},"#0088ee":{"lch":[55.8667862779657725,100.217939448335898,251.046181944553609],"luv":[55.8667862779657725,-32.551381555669181,-94.7841914355319091],"rgb":[0,0.533333333333333326,0.933333333333333348],"xyz":[0.242347478758252299,0.237799373529310187,0.842043876879962],"hpluv":[251.046181944553609,227.630842720065772,55.8667862779657725],"hsluv":[251.046181944553609,99.9999999999923261,55.8667862779657725]},"#0088ff":{"lch":[56.9062538959811803,112.568622459607909,253.628629682131134],"luv":[56.9062538959811803,-31.728824885135996,-108.00452043253614],"rgb":[0,0.533333333333333326,1],"xyz":[0.268518527168083665,0.248267792893242883,0.979878065171743806],"hpluv":[253.628629682131134,251.013269675548315,56.9062538959811803],"hsluv":[253.628629682131134,99.9999999999989,56.9062538959811803]},"#009900":{"lch":[54.8465256129575778,84.8867610313905629,127.71501294924046],"luv":[54.8465256129575778,-51.9281467214630865,67.1507987776363677],"rgb":[0,0.6,0],"xyz":[0.11390733921872119,0.227814678437445572,0.037969113072906],"hpluv":[127.71501294924046,196.394882900214611,54.8465256129575778],"hsluv":[127.71501294924046,100.000000000002359,54.8465256129575778]},"#009911":{"lch":[54.8884489227774139,83.3822613920475533,128.355135015114286],"luv":[54.8884489227774139,-51.7415219578455918,65.3866685214771195],"rgb":[0,0.6,0.0666666666666666657],"xyz":[0.114919004718358309,0.228219344637300425,0.0432972180376616292],"hpluv":[128.355135015114286,192.766711025891595,54.8884489227774139],"hsluv":[128.355135015114286,99.9999999999908908,54.8884489227774139]},"#009922":{"lch":[54.9660326693047665,80.6666974094322882,129.584419925030318],"luv":[54.9660326693047665,-51.4019848556742147,62.168738316310943],"rgb":[0,0.6,0.133333333333333331],"xyz":[0.116794362856835338,0.228969487892691254,0.0531741042336408287],"hpluv":[129.584419925030318,186.225526863887183,54.9660326693047665],"hsluv":[129.584419925030318,99.9999999999908766,54.9660326693047665]},"#009933":{"lch":[55.0934048637144826,76.4021664793699529,131.735569901926],"luv":[55.0934048637144826,-50.8604445821364948,57.0132109221080725],"rgb":[0,0.6,0.2],"xyz":[0.119882113589293071,0.230204588185674353,0.0694362580912519789],"hpluv":[131.735569901926,175.972736191316358,55.0934048637144826],"hsluv":[131.735569901926,99.9999999999909903,55.0934048637144826]},"#009944":{"lch":[55.2764995203901321,70.6973886175228614,135.142608572152881],"luv":[55.2764995203901321,-50.1148739946869739,49.8660221176072795],"rgb":[0,0.6,0.266666666666666663],"xyz":[0.124340108833511945,0.231987786283361946,0.0929150330441386174],"hpluv":[135.142608572152881,162.293888564466016,55.2764995203901321],"hsluv":[135.142608572152881,99.9999999999910472,55.2764995203901321]},"#009955":{"lch":[55.5199214835444792,63.9084670453141044,140.311824754994205],"luv":[55.5199214835444792,-49.1795700812718,40.8125231602173173],"rgb":[0,0.6,0.333333333333333315],"xyz":[0.130302522872873944,0.234372751899106779,0.124317080318112519],"hpluv":[140.311824754994205,146.065915008593578,55.5199214835444792],"hsluv":[140.311824754994205,99.999999999991033,55.5199214835444792]},"#009966":{"lch":[55.8272121342916847,56.7002292022714229,147.995210176352344],"luv":[55.8272121342916847,-48.0820094218291771,30.0505634148387166],"rgb":[0,0.6,0.4],"xyz":[0.137887518646382129,0.23740675020851007,0.164264724725256495],"hpluv":[147.995210176352344,128.877825594911201,55.8272121342916847],"hsluv":[147.995210176352344,99.9999999999911893,55.8272121342916847]},"#009977":{"lch":[56.2009899164422393,50.1460500452165832,159.138923639260469],"luv":[56.2009899164422393,-46.85880632633,17.8571723631952],"rgb":[0,0.6,0.466666666666666674],"xyz":[0.147201531666584035,0.241132355416590893,0.213318526631654404],"hpluv":[159.138923639260469,113.222330796973324,56.2009899164422393],"hsluv":[159.138923639260469,99.9999999999912887,56.2009899164422393]},"#009988":{"lch":[56.6430401241061077,45.7780774967248476,174.293450088826631],"luv":[56.6430401241061077,-45.5512109338885409,4.55187453172192669],"rgb":[0,0.6,0.533333333333333326],"xyz":[0.158341948768527863,0.245588522257368491,0.271991390035226543],"hpluv":[174.293450088826631,102.553461073272217,56.6430401241061077],"hsluv":[174.293450088826631,99.9999999999913456,56.6430401241061077]},"#009999":{"lch":[57.1543844255405133,45.2182256610376498,192.177050630061132],"luv":[57.1543844255405133,-44.2008363998384866,-9.53802880511673301],"rgb":[0,0.6,0.6],"xyz":[0.171398912877600562,0.250811307900997649,0.340758067676344478],"hpluv":[192.177050630061132,100.392967527320849,57.1543844255405133],"hsluv":[192.177050630061132,99.9999999999914877,57.1543844255405133]},"#0099aa":{"lch":[57.7353441317496,49.1617433665336065,209.362441333496832],"luv":[57.7353441317496,-42.8462007667450138,-24.1056028900479831],"rgb":[0,0.6,0.66666666666666663],"xyz":[0.186456605842853118,0.256834385087098771,0.420061917293343079],"hpluv":[209.362441333496832,108.050017888493571,57.7353441317496],"hsluv":[209.362441333496832,99.9999999999915872,57.7353441317496]},"#0099bb":{"lch":[58.3856036871333686,56.8846197873520509,223.121526867409756],"luv":[58.3856036871333686,-41.5203973647636531,-38.8833713947714656],"rgb":[0,0.6,0.733333333333333282],"xyz":[0.203594197950189765,0.26368942193003353,0.51031990239198477],"hpluv":[223.121526867409756,123.631292939903787,58.3856036871333686],"hsluv":[223.121526867409756,99.9999999999917151,58.3856036871333686]},"#0099cc":{"lch":[59.1042769117952531,67.0724902608298237,233.123241992210865],"luv":[59.1042769117952531,-40.2499186561976856,-53.6531732328907225],"rgb":[0,0.6,0.8],"xyz":[0.222886573393911491,0.271406372107522331,0.611926413062254926],"hpluv":[233.123241992210865,144.000781521109104,59.1042769117952531],"hsluv":[233.123241992210865,99.9999999999918572,59.1042769117952531]},"#0099dd":{"lch":[59.889976295668248,78.6325369214165448,240.220044999287609],"luv":[59.889976295668248,-39.0544489896310338,-68.2482664747921888],"rgb":[0,0.6,0.866666666666666696],"xyz":[0.244404898944545035,0.280013702327775837,0.725256260962260924],"hpluv":[240.220044999287609,166.60478591483178,59.889976295668248],"hsluv":[240.220044999287609,99.9999999999918288,59.889976295668248]},"#0099ee":{"lch":[60.7408843834734853,90.8542474807105549,245.312254820906361],"luv":[60.7408843834734853,-37.9473430473261288,-82.5499451298106521],"rgb":[0,0.6,0.933333333333333348],"xyz":[0.2682170792107198,0.289538574434245854,0.850667077030784147],"hpluv":[245.312254820906361,189.803165481490907,60.7408843834734853],"hsluv":[245.312254820906361,99.9999999999919424,60.7408843834734853]},"#0099ff":{"lch":[61.6548256470178444,103.309645725501895,249.051296659176671],"luv":[61.6548256470178444,-36.936501733242423,-96.4809708680364082],"rgb":[0,0.6,1],"xyz":[0.294388127620551165,0.300006993798178578,0.988501265322566],"hpluv":[249.051296659176671,212.624411607996194,61.6548256470178444],"hsluv":[249.051296659176671,99.9999999999986926,61.6548256470178444]},"#44aa00":{"lch":[61.6346835386869714,87.655425968627469,122.331376925101353],"luv":[61.6346835386869714,-46.8794507107122556,74.0661245293922],"rgb":[0.266666666666666663,0.66666666666666663,0],"xyz":[0.167579386406696784,0.29977360690638849,0.0490310792412290836],"hpluv":[122.331376925101353,180.464989524422549,61.6346835386869714],"hsluv":[122.331376925101353,100.00000000000226,61.6346835386869714]},"#44aa11":{"lch":[61.6696010074672927,86.3319887480293175,122.80087722620695],"luv":[61.6696010074672927,-46.7678581574140253,72.5670705248452492],"rgb":[0.266666666666666663,0.66666666666666663,0.0666666666666666657],"xyz":[0.168591051906333916,0.300178273106243343,0.0543591842059847133],"hpluv":[122.80087722620695,177.639660035048053,61.6696010074672927],"hsluv":[122.80087722620695,97.7717273205757778,61.6696010074672927]},"#44aa22":{"lch":[61.7342457720645541,83.9245562706402097,123.699102784065559],"luv":[61.7342457720645541,-46.5639790081192,69.8221097085679],"rgb":[0.266666666666666663,0.66666666666666663,0.133333333333333331],"xyz":[0.170466410044810918,0.300928416361634143,0.0642360704019639128],"hpluv":[123.699102784065559,172.505216938407472,61.7342457720645541],"hsluv":[123.699102784065559,93.6968530578778882,61.7342457720645541]},"#44aa33":{"lch":[61.8404488118369784,80.0901636841586111,125.261260913590505],"luv":[61.8404488118369784,-46.2365065380172098,65.3958697634278],"rgb":[0.266666666666666663,0.66666666666666663,0.2],"xyz":[0.173554160777268651,0.30216351665461727,0.080498224259575063],"hpluv":[125.261260913590505,164.340980941234676,61.8404488118369784],"hsluv":[125.261260913590505,87.1410828818075913,61.8404488118369784]},"#44aa44":{"lch":[61.9932720073472,74.8379874444649573,127.71501294923992],"luv":[61.9932720073472,-45.7809668449718501,59.2015830825281526],"rgb":[0.266666666666666663,0.66666666666666663,0.266666666666666663],"xyz":[0.178012156021487539,0.303946714752304836,0.103976999212461702],"hpluv":[127.71501294923992,153.185220958209158,61.9932720073472],"hsluv":[127.71501294923992,77.998580561819125,61.9932720073472]},"#44aa55":{"lch":[62.1967362447927883,68.3415808764166854,131.40733952388851],"luv":[62.1967362447927883,-45.2016647888952292,51.2579864704043118],"rgb":[0.266666666666666663,0.66666666666666663,0.333333333333333315],"xyz":[0.183974570060849552,0.306331680368049697,0.135379046486435617],"hpluv":[131.40733952388851,139.430168232009549,62.1967362447927883],"hsluv":[131.40733952388851,78.575415606985473,62.1967362447927883]},"#44aa66":{"lch":[62.4540496972210377,60.9745995384144,136.885019691281769],"luv":[62.4540496972210377,-44.510458035487396,41.6739836629655684],"rgb":[0.266666666666666663,0.66666666666666663,0.4],"xyz":[0.191559565834357709,0.309365678677453,0.175326690893579551],"hpluv":[136.885019691281769,123.88755407265441,62.4540496972210377],"hsluv":[136.885019691281769,79.2669246679894854,62.4540496972210377]},"#44aa77":{"lch":[62.7677273349888196,53.3862032124370103,144.988299459670287],"luv":[62.7677273349888196,-43.7251633677153,30.629998072253084],"rgb":[0.266666666666666663,0.66666666666666663,0.466666666666666674],"xyz":[0.200873578854559642,0.313091283885533811,0.22438049279997746],"hpluv":[144.988299459670287,107.927460302012818,62.7677273349888196],"hsluv":[144.988299459670287,80.0573307147673603,62.7677273349888196]},"#44aa88":{"lch":[63.1396635168947142,46.6323085826041606,156.819414130132799],"luv":[63.1396635168947142,-42.8676249510766354,18.3558964585511255],"rgb":[0.266666666666666663,0.66666666666666663,0.533333333333333326],"xyz":[0.212013995956503443,0.317547450726311409,0.283053356203549655],"hpluv":[156.819414130132799,93.7182088199909,63.1396635168947142],"hsluv":[156.819414130132799,80.9270306732118456,63.1396635168947142]},"#44aa99":{"lch":[63.5711832083111,42.2713825005608328,173.059905511526438],"luv":[63.5711832083111,-41.9616613239929848,5.10771548142927578],"rgb":[0.266666666666666663,0.66666666666666663,0.6],"xyz":[0.22507096006557617,0.322770236369940566,0.351820033844667535],"hpluv":[173.059905511526438,84.3772726773670598,63.5711832083111],"hsluv":[173.059905511526438,81.8544924931781281,63.5711832083111]},"#44aaaa":{"lch":[64.0630839897801536,41.9755778813547948,192.177050630061],"luv":[64.0630839897801536,-41.03114670244819,-8.85404646225986802],"rgb":[0.266666666666666663,0.66666666666666663,0.66666666666666663],"xyz":[0.240128653030828698,0.328793313556041689,0.431123883461666135],"hpluv":[192.177050630061,83.1434743556685731,64.0630839897801536],"hsluv":[192.177050630061,82.8180264051213868,64.0630839897801536]},"#44aabb":{"lch":[64.6156750410269893,46.3675567205894481,210.140689328835606],"luv":[64.6156750410269893,-40.0984334486196374,-23.2823098339426302],"rgb":[0.266666666666666663,0.66666666666666663,0.733333333333333282],"xyz":[0.257266245138165373,0.335648350398976447,0.521381868560307882],"hpluv":[210.140689328835606,91.0574853549996135,64.6156750410269893],"hsluv":[210.140689328835606,83.7972417316187,64.6156750410269893]},"#44aacc":{"lch":[65.2288162125558131,54.5527176111565382,224.088695054270687],"luv":[65.2288162125558131,-39.1832309762682058,-37.956203827872514],"rgb":[0.266666666666666663,0.66666666666666663,0.8],"xyz":[0.276558620581887071,0.343365300576465249,0.622988379230578],"hpluv":[224.088695054270687,106.124637545316332,65.2288162125558131],"hsluv":[224.088695054270687,84.7740840933985424,65.2288162125558131]},"#44aadd":{"lch":[65.9019585504415772,65.1392687949415574,233.984713087438024],"luv":[65.9019585504415772,-38.3019605797345406,-52.6885581021924381],"rgb":[0.266666666666666663,0.66666666666666663,0.866666666666666696],"xyz":[0.29807694613252067,0.351972630796718755,0.736318227130584],"hpluv":[233.984713087438024,125.424934833645892,65.9019585504415772],"hsluv":[233.984713087438024,85.7334354760652246,65.9019585504415772]},"#44aaee":{"lch":[66.634186587349916,77.0517400481588,240.904642753345257],"luv":[66.634186587349916,-37.4675316968449081,-67.3287064556787698],"rgb":[0.266666666666666663,0.66666666666666663,0.933333333333333348],"xyz":[0.32188912639869538,0.361497502903188772,0.861729043199107259],"hpluv":[240.904642753345257,146.73194579095005,66.634186587349916],"hsluv":[240.904642753345257,86.6633273618325717,66.634186587349916]},"#44aaff":{"lch":[67.4242620727880677,89.6163291450103827,245.832487512483851],"luv":[67.4242620727880677,-36.6894434071527229,-81.7616731231704534],"rgb":[0.266666666666666663,0.66666666666666663,1],"xyz":[0.348060174808526801,0.371965922267121496,0.999563231490889104],"hpluv":[245.832487512483851,168.659292786049974,67.4242620727880677],"hsluv":[245.832487512483851,99.9999999999982094,67.4242620727880677]},"#44bb00":{"lch":[67.1028050092269126,96.9162111575721497,123.392710981560953],"luv":[67.1028050092269126,-53.3402140179528601,80.9170782570533476],"rgb":[0.266666666666666663,0.733333333333333282,0],"xyz":[0.201533884315295564,0.367682602723587049,0.0603492452107617],"hpluv":[123.392710981560953,183.271561122122193,67.1028050092269126],"hsluv":[123.392710981560953,100.00000000000226,67.1028050092269126]},"#44bb11":{"lch":[67.1332810832727347,95.7453830613523138,123.778355355208646],"luv":[67.1332810832727347,-53.2326764896654581,79.5830417319651673],"rgb":[0.266666666666666663,0.733333333333333282,0.0666666666666666657],"xyz":[0.202545549814932696,0.368087268923441902,0.0656773501755173322],"hpluv":[123.778355355208646,180.975295348072393,67.1332810832727347],"hsluv":[123.778355355208646,98.1806384027583334,67.1332810832727347]},"#44bb22":{"lch":[67.1897165718252438,93.6085464076245728,124.511290753684577],"luv":[67.1897165718252438,-53.03566579282883,77.1348048189646391],"rgb":[0.266666666666666663,0.733333333333333282,0.133333333333333331],"xyz":[0.204420907953409697,0.368837412178832702,0.0755542363714965248],"hpluv":[124.511290753684577,176.787689053856155,67.1897165718252438],"hsluv":[124.511290753684577,94.8452524510698538,67.1897165718252438]},"#44bb33":{"lch":[67.2824703298360873,90.1849869824975627,125.771296969252688],"luv":[67.2824703298360873,-52.7177504009765485,73.1721987485246501],"rgb":[0.266666666666666663,0.733333333333333282,0.2],"xyz":[0.207508658685867431,0.370072512471815829,0.091816390229107675],"hpluv":[125.771296969252688,170.087205132927863,67.2824703298360873],"hsluv":[125.771296969252688,89.4565739304913308,67.2824703298360873]},"#44bb44":{"lch":[67.4160218575577375,85.4495691526201284,127.715012949240077],"luv":[67.4160218575577375,-52.2724357759646807,67.5960156105081182],"rgb":[0.266666666666666663,0.733333333333333282,0.266666666666666663],"xyz":[0.211966653930086318,0.371855710569503395,0.115295165181994314],"hpluv":[127.715012949240077,160.837043785954393,67.4160218575577375],"hsluv":[127.715012949240077,81.8947222100884318,67.4160218575577375]},"#44bb55":{"lch":[67.5939766620447813,79.5000401119176,130.566112214394138],"luv":[67.5939766620447813,-51.7008659583180759,60.3926886051327756],"rgb":[0.266666666666666663,0.733333333333333282,0.333333333333333315],"xyz":[0.217929067969448331,0.374240676185248256,0.146697212455968229],"hpluv":[130.566112214394138,149.244617358403957,67.5939766620447813],"hsluv":[130.566112214394138,82.2871698148834412,67.5939766620447813]},"#44bb66":{"lch":[67.8192698910356313,72.5749222232247,134.657948179728322],"luv":[67.8192698910356313,-51.0109407747319139,51.6236695420221778],"rgb":[0.266666666666666663,0.733333333333333282,0.4],"xyz":[0.225514063742956489,0.377274674494651574,0.186644856863112191],"hpluv":[134.657948179728322,135.791565604529097,67.8192698910356313],"hsluv":[134.657948179728322,82.7624878443234451,67.8192698910356313]},"#44bb77":{"lch":[68.0942730594189527,65.0902087481164671,140.487577627549143],"luv":[68.0942730594189527,-50.2162275054035163,41.4133525568618168],"rgb":[0.266666666666666663,0.733333333333333282,0.466666666666666674],"xyz":[0.234828076763158422,0.38100027970273237,0.2356986587695101],"hpluv":[140.487577627549143,121.295420087000366,68.0942730594189527],"hsluv":[140.487577627549143,83.3123735080707206,68.0942730594189527]},"#44bb88":{"lch":[68.4208577329380461,57.7058903955470939,148.752185803016886],"luv":[68.4208577329380461,-49.3345927236295907,29.9343907092910229],"rgb":[0.266666666666666663,0.733333333333333282,0.533333333333333326],"xyz":[0.245968493865102222,0.385456446543509967,0.294371522173082267],"hpluv":[148.752185803016886,107.021481540968693,68.4208577329380461],"hsluv":[148.752185803016886,83.9257037652282776,68.4208577329380461]},"#44bb99":{"lch":[68.8004384509552267,51.4171630403873507,160.23039633414129],"luv":[68.8004384509552267,-48.3866530594068536,17.3912754227620781],"rgb":[0.266666666666666663,0.733333333333333282,0.6],"xyz":[0.259025457974175,0.390679232187139125,0.363138199814200147],"hpluv":[160.23039633414129,94.8322885243955,68.8004384509552267],"hsluv":[160.23039633414129,84.5895330052649683,68.8004384509552267]},"#44bbaa":{"lch":[69.2340056114394571,47.5630236168925,175.171204236910796],"luv":[69.2340056114394571,-47.3942071553531576,4.003791165451279],"rgb":[0.266666666666666663,0.733333333333333282,0.66666666666666663],"xyz":[0.274083150939427478,0.396702309373240247,0.442442049431198747],"hpluv":[175.171204236910796,87.1744714415039113,69.2340056114394571],"hsluv":[175.171204236910796,85.2901010545764251,69.2340056114394571]},"#44bbbb":{"lch":[69.722153945093,47.4463312905994243,192.177050630061103],"luv":[69.722153945093,-46.3788106784417877,-10.0080104411700219],"rgb":[0.266666666666666663,0.733333333333333282,0.733333333333333282],"xyz":[0.291220743046764152,0.403557346216175,0.532700034529840494],"hpluv":[192.177050630061103,86.3517549054621156,69.722153945093],"hsluv":[192.177050630061103,86.0137488036252,69.722153945093]},"#44bbcc":{"lch":[70.265109629848,51.5238495855336254,208.311647260201596],"luv":[70.265109629848,-45.3606162241423405,-24.4360711219862],"rgb":[0.266666666666666663,0.733333333333333282,0.8],"xyz":[0.310513118490485907,0.411274296393663807,0.63430654520011065],"hpluv":[208.311647260201596,93.0481841100277478,70.265109629848],"hsluv":[208.311647260201596,86.7476639801695484,70.265109629848]},"#44bbdd":{"lch":[70.8627576511434683,59.1258582536945,221.390354970453018],"luv":[70.8627576511434683,-44.357542252504274,-39.0931651258026491],"rgb":[0.266666666666666663,0.733333333333333282,0.866666666666666696],"xyz":[0.332031444041119395,0.419881626613917314,0.747636393100116647],"hpluv":[221.390354970453018,105.876295000483495,70.8627576511434683],"hsluv":[221.390354970453018,87.4804162985680449,70.8627576511434683]},"#44bbee":{"lch":[71.5146701379092207,69.1277260896420813,231.126492355228834],"luv":[71.5146701379092207,-43.3847784652122499,-53.8182451576511269],"rgb":[0.266666666666666663,0.733333333333333282,0.933333333333333348],"xyz":[0.35584362430729416,0.429406498720387331,0.873047209168639871],"hpluv":[231.126492355228834,122.65816352572412,71.5146701379092207],"hsluv":[231.126492355228834,88.202277385306985,71.5146701379092207]},"#44bbff":{"lch":[72.2201358507708,80.5712163793027685,238.202407995552562],"luv":[72.2201358507708,-42.4545914747530801,-68.4786723845625573],"rgb":[0.266666666666666663,0.733333333333333282,1],"xyz":[0.382014672717125525,0.439874918084320055,1.01088139746042183],"hpluv":[238.202407995552562,141.566646923483631,72.2201358507708],"hsluv":[238.202407995552562,99.9999999999976694,72.2201358507708]},"#44cc00":{"lch":[72.503692055952385,105.959797206167082,124.178253965335855],"luv":[72.503692055952385,-59.5249745926526543,87.6598883396283384],"rgb":[0.266666666666666663,0.8,0],"xyz":[0.239757627624912484,0.444130089342821943,0.0730904929806336506],"hpluv":[124.178253965335855,185.447217969921951,72.503692055952385],"hsluv":[124.178253965335855,100.000000000002359,72.503692055952385]},"#44cc11":{"lch":[72.5305637479271752,104.914943747871533,124.498982817725434],"luv":[72.5305637479271752,-59.4229434801529877,86.4642076802510928],"rgb":[0.266666666666666663,0.8,0.0666666666666666657],"xyz":[0.240769293124549616,0.444534755542676796,0.0784185979453892873],"hpluv":[124.498982817725434,183.55052269402043,72.5305637479271752],"hsluv":[124.498982817725434,98.4921383302381628,72.5305637479271752]},"#44cc22":{"lch":[72.5803335982668,103.003123626508128,125.105641856618192],"luv":[72.5803335982668,-59.2356349500081265,84.2661440252673088],"rgb":[0.266666666666666663,0.8,0.133333333333333331],"xyz":[0.242644651263026617,0.445284898798067597,0.0882954841413684799],"hpluv":[125.105641856618192,180.082189217111164,72.5803335982668],"hsluv":[125.105641856618192,95.7225658430248387,72.5803335982668]},"#44cc33":{"lch":[72.6621573160580283,99.9260617146724144,126.139923542820412],"luv":[72.6621573160580283,-58.9323161564504758,80.6982027200153],"rgb":[0.266666666666666663,0.8,0.2],"xyz":[0.245732401995484351,0.446519999091050723,0.10455763799897963],"hpluv":[126.139923542820412,174.505777504147545,72.6621573160580283],"hsluv":[126.139923542820412,91.233607132201584,72.6621573160580283]},"#44cc44":{"lch":[72.780026014363628,95.6382843785450518,127.715012949240148],"luv":[72.780026014363628,-58.5052227586060383,75.6559339961998],"rgb":[0.266666666666666663,0.8,0.266666666666666663],"xyz":[0.250190397239703266,0.448303197188738289,0.128036412951866269],"hpluv":[127.715012949240148,166.747333178852926,72.780026014363628],"hsluv":[127.715012949240148,84.9041129363740339,72.780026014363628]},"#44cc55":{"lch":[72.9371837422115732,90.1892610669535912,129.983942971096695],"luv":[72.9371837422115732,-57.9531752136704,69.1052262456084492],"rgb":[0.266666666666666663,0.8,0.333333333333333315],"xyz":[0.256152811279065251,0.45068816280448315,0.159438460225840184],"hpluv":[129.983942971096695,156.908028239254975,72.9371837422115732],"hsluv":[129.983942971096695,85.1779272269293557,72.9371837422115732]},"#44cc66":{"lch":[73.1363103507417236,83.732792729713168,133.164212643981188],"luv":[73.1363103507417236,-57.28090462038152,61.074368962666],"rgb":[0.266666666666666663,0.8,0.4],"xyz":[0.263737807052573436,0.453722161113886469,0.199386104632984118],"hpluv":[133.164212643981188,145.278670258241675,73.1363103507417236],"hsluv":[133.164212643981188,85.5122241677148764,73.1363103507417236]},"#44cc77":{"lch":[73.3796177536812309,76.5464624175537,137.569101073773794],"luv":[73.3796177536812309,-56.4983001604517625,51.6459387330839],"rgb":[0.266666666666666663,0.8,0.466666666666666674],"xyz":[0.273051820072775342,0.457447766321967264,0.248439906539382027],"hpluv":[137.569101073773794,132.369828459728325,73.3796177536812309],"hsluv":[137.569101073773794,85.9026534082125153,73.3796177536812309]},"#44cc88":{"lch":[73.6689069899719442,69.0664605730878378,143.639563525196422],"luv":[73.6689069899719442,-55.6194534086204087,40.9469459010095278],"rgb":[0.266666666666666663,0.8,0.533333333333333326],"xyz":[0.284192237174719142,0.461903933162744862,0.307112769942954222],"hpluv":[143.639563525196422,118.965846887396481,73.6689069899719442],"hsluv":[143.639563525196422,86.3428682965135863,73.6689069899719442]},"#44cc99":{"lch":[74.0056056952011,61.9424628035573548,151.940118655705163],"luv":[74.0056056952011,-54.661526046940331,29.1373689338922652],"rgb":[0.266666666666666663,0.8,0.6],"xyz":[0.297249201283791842,0.467126718806374,0.375879447584072102],"hpluv":[151.940118655705163,106.209454381597496,74.0056056952011],"hsluv":[151.940118655705163,86.8250568088678,74.0056056952011]},"#44ccaa":{"lch":[74.3907954563299256,56.0938540204294327,163.002493202880316],"luv":[74.3907954563299256,-53.6435329798001206,16.3979214631106132],"rgb":[0.266666666666666663,0.8,0.66666666666666663],"xyz":[0.312306894249044398,0.473149795992475142,0.455183297201070702],"hpluv":[163.002493202880316,95.6831366692641581,74.3907954563299256],"hsluv":[163.002493202880316,87.3405106459777727,74.3907954563299256]},"#44ccbb":{"lch":[74.8252340948823331,52.6660587979454959,176.823724318960615],"luv":[74.8252340948823331,-52.5851528012588929,2.91812511330579927],"rgb":[0.266666666666666663,0.8,0.733333333333333282],"xyz":[0.329444486356381072,0.4800048328354099,0.545441282299712449],"hpluv":[176.823724318960615,89.3145186414393493,74.8252340948823331],"hsluv":[176.823724318960615,87.8801809558037235,74.8252340948823331]},"#44cccc":{"lch":[75.3093757141467393,52.6911947618550442,192.177050630061103],"luv":[75.3093757141467393,-51.5056671360628826,-11.1143267137884898],"rgb":[0.266666666666666663,0.8,0.8],"xyz":[0.348736861800102771,0.487721783012898702,0.647047792969982605],"hpluv":[192.177050630061103,88.7826952764381758,75.3093757141467393],"hsluv":[192.177050630061103,88.4351737608208168,75.3093757141467393]},"#44ccdd":{"lch":[75.8433901234223669,56.5143539908888,206.846753698803184],"luv":[75.8433901234223669,-50.423101427505074,-25.5222069860548118],"rgb":[0.266666666666666663,0.8,0.866666666666666696],"xyz":[0.37025518735073637,0.496329113233152208,0.760377640869988602],"hpluv":[206.846753698803184,94.5540981724771257,75.8433901234223669],"hsluv":[206.846753698803184,88.9971515077065334,75.8433901234223669]},"#44ccee":{"lch":[76.4271825186181104,63.6191993934700264,219.125479385679029],"luv":[76.4271825186181104,-49.3536035237008,-40.1450414209705926],"rgb":[0.266666666666666663,0.8,0.933333333333333348],"xyz":[0.39406736761691108,0.505853985339622225,0.885788456938511826],"hpluv":[219.125479385679029,108.248092211119214,76.4271825186181104],"hsluv":[219.125479385679029,89.5586239337052,76.4271825186181104]},"#44ccff":{"lch":[77.0604138316104752,73.087044724203011,228.6232677289035],"luv":[77.0604138316104752,-48.3110621928290342,-54.8430248647743426],"rgb":[0.266666666666666663,0.8,1],"xyz":[0.420238416026742501,0.516322404703555,1.02362264523029367],"hpluv":[228.6232677289035,128.526456918779161,77.0604138316104752],"hsluv":[228.6232677289035,99.9999999999969731,77.0604138316104752]},"#44dd00":{"lch":[77.8394471675691193,114.806757868746558,124.774603647715026],"luv":[77.8394471675691193,-65.4799812263264869,94.3025116894186],"rgb":[0.266666666666666663,0.866666666666666696,0],"xyz":[0.282391618172087688,0.529398070437173462,0.0873018231630249691],"hpluv":[124.774603647715026,210.465861771712326,77.8394471675691193],"hsluv":[124.774603647715026,100.000000000002174,77.8394471675691193]},"#44dd11":{"lch":[77.8633510332093692,113.867279553553601,125.04447057905567],"luv":[77.8633510332093692,-65.3839645843072503,93.2238946202376724],"rgb":[0.266666666666666663,0.866666666666666696,0.0666666666666666657],"xyz":[0.283403283671724793,0.529802736637028371,0.0926299281277806],"hpluv":[125.04447057905567,209.014039294370775,77.8633510332093692],"hsluv":[125.04447057905567,98.7339197526847272,77.8633510332093692]},"#44dd22":{"lch":[77.9076302523257738,112.144788460185168,125.553114236235714],"luv":[77.9076302523257738,-65.2074178024426914,91.2384033306006472],"rgb":[0.266666666666666663,0.866666666666666696,0.133333333333333331],"xyz":[0.28527864181020185,0.530552879892419171,0.102506814323759798],"hpluv":[125.553114236235714,206.347170822894697,77.9076302523257738],"hsluv":[125.553114236235714,96.4050109160080382,77.9076302523257738]},"#44dd33":{"lch":[77.9804445180848802,109.362510567887881,126.41495586461761],"luv":[77.9804445180848802,-64.9207541848309546,88.0082632130877869],"rgb":[0.266666666666666663,0.866666666666666696,0.2],"xyz":[0.288366392542659555,0.531787980185402298,0.118768968181370949],"hpluv":[126.41495586461761,202.025685311970193,77.9804445180848802],"hsluv":[126.41495586461761,92.6208241654068729,77.9804445180848802]},"#44dd44":{"lch":[78.0853727898892345,105.463232003770898,127.715012949240119],"luv":[78.0853727898892345,-64.5154806081751389,83.428089194092081],"rgb":[0.266666666666666663,0.866666666666666696,0.266666666666666663],"xyz":[0.292824387786878471,0.533571178283089864,0.142247743134257587],"hpluv":[127.715012949240119,195.940425098340825,78.0853727898892345],"hsluv":[127.715012949240119,87.2650912217990395,78.0853727898892345]},"#44dd55":{"lch":[78.2253459168282888,100.46502238820301,129.562971792001804],"luv":[78.2253459168282888,-63.9887749627021662,77.4510000079714303],"rgb":[0.266666666666666663,0.866666666666666696,0.333333333333333315],"xyz":[0.298786801826240456,0.535956143898834614,0.173649790408231475],"hpluv":[129.562971792001804,188.090878204767051,78.2253459168282888],"hsluv":[129.562971792001804,87.4605090914447,78.2253459168282888]},"#44dd66":{"lch":[78.4028117957757615,94.4661355921174,132.108441056441876],"luv":[78.4028117957757615,-63.3429373931831776,70.0822592109557],"rgb":[0.266666666666666663,0.866666666666666696,0.4],"xyz":[0.306371797599748641,0.538990142208237932,0.213597434815375464],"hpluv":[132.108441056441876,178.59774401526758,78.4028117957757615],"hsluv":[132.108441056441876,87.7006053461373654,78.4028117957757615]},"#44dd77":{"lch":[78.6198227824069278,87.656024220764337,135.559861003190832],"luv":[78.6198227824069278,-62.584854150819659,61.3735660778470375],"rgb":[0.266666666666666663,0.866666666666666696,0.466666666666666674],"xyz":[0.315685810619950546,0.542715747416318783,0.262651236721773373],"hpluv":[135.559861003190832,167.73117312681623,78.6198227824069278],"hsluv":[135.559861003190832,87.9831439767702221,78.6198227824069278]},"#44dd88":{"lch":[78.8780874692010201,80.3346414261830404,140.206181380764804],"luv":[78.8780874692010201,-61.7253288138421823,51.416324216113189],"rgb":[0.266666666666666663,0.866666666666666696,0.533333333333333326],"xyz":[0.326826227721894347,0.547171914257096326,0.321324100125345513],"hpluv":[140.206181380764804,155.961921377148798,78.8780874692010201],"hsluv":[140.206181380764804,88.3044935606717729,78.8780874692010201]},"#44dd99":{"lch":[79.1790042342924,72.9438114093828602,146.430978952194238],"luv":[79.1790042342924,-60.7782665628728651,40.3336328210091182],"rgb":[0.266666666666666663,0.866666666666666696,0.6],"xyz":[0.339883191830967046,0.552394699900725539,0.390090777766463448],"hpluv":[146.430978952194238,144.047423549525234,79.1790042342924],"hsluv":[146.430978952194238,88.6599152631773109,79.1790042342924]},"#44ddaa":{"lch":[79.5236849812282,66.109750002698334,154.681927012774025],"luv":[79.5236849812282,-59.7597565852220498,28.2713731236083063],"rgb":[0.266666666666666663,0.866666666666666696,0.66666666666666663],"xyz":[0.354940884796219602,0.558417777086826606,0.469394627383462049],"hpluv":[154.681927012774025,133.15854000611057,79.5236849812282],"hsluv":[154.681927012774025,89.0438856180527267,79.5236849812282]},"#44ddbb":{"lch":[79.9129735834354733,60.6712530747818448,165.306614809553963],"luv":[79.9129735834354733,-58.687123678359157,15.3890371376899697],"rgb":[0.266666666666666663,0.866666666666666696,0.733333333333333282],"xyz":[0.372078476903556277,0.565272813929761364,0.55965261248210374],"hpluv":[165.306614809553963,125.005338667233715,79.9129735834354733],"hsluv":[165.306614809553963,89.4504295982059574,79.9129735834354733]},"#44ddcc":{"lch":[80.3474616163736783,57.6077690930220925,178.158710030216184],"luv":[80.3474616163736783,-57.5780241737671616,1.85099760130491053],"rgb":[0.266666666666666663,0.866666666666666696,0.8],"xyz":[0.391370852347278,0.572989764107250221,0.661259123152373895],"hpluv":[178.158710030216184,121.786592068950441,80.3474616163736783],"hsluv":[178.158710030216184,89.8734379183952399,80.3474616163736783]},"#44dddd":{"lch":[80.8275029051271758,57.7489755309586,192.177050630061132],"luv":[80.8275029051271758,-56.4496501662069505,-12.1811810177875159],"rgb":[0.266666666666666663,0.866666666666666696,0.866666666666666696],"xyz":[0.412889177897911575,0.581597094327503727,0.774588971052379893],"hpluv":[192.177050630061132,125.674721736272474,80.8275029051271758],"hsluv":[192.177050630061132,90.3069463225795204,80.8275029051271758]},"#44ddee":{"lch":[81.3532277894993143,61.361693698739991,205.642938459455962],"luv":[81.3532277894993143,-55.3180860243278758,-26.5549771640468073],"rgb":[0.266666666666666663,0.866666666666666696,0.933333333333333348],"xyz":[0.436701358164086284,0.591121966433973745,0.899999787120903116],"hpluv":[205.642938459455962,137.939634766348263,81.3532277894993143],"hsluv":[205.642938459455962,90.7453615563817806,81.3532277894993143]},"#44ddff":{"lch":[81.9245576129038113,68.0382655080336463,217.195369709248553],"luv":[81.9245576129038113,-54.1978382178125813,-41.1314953029609],"rgb":[0.266666666666666663,0.866666666666666696,1],"xyz":[0.462872406573917705,0.601590385797906468,1.03783397541268507],"hpluv":[217.195369709248553,158.576151866946,81.9245576129038113],"hsluv":[217.195369709248553,99.9999999999957367,81.9245576129038113]},"#44ee00":{"lch":[83.112739541513335,123.476763986331008,125.23710114083579],"luv":[83.112739541513335,-71.241317589729718,100.852297507867192],"rgb":[0.266666666666666663,0.933333333333333348,0],"xyz":[0.329570394512602505,0.623755623118204428,0.103028081943196154],"hpluv":[125.23710114083579,311.240798427125753,83.112739541513335],"hsluv":[125.23710114083579,100.000000000002402,83.112739541513335]},"#44ee11":{"lch":[83.1341682891089135,122.626446998812852,125.466600012922257],"luv":[83.1341682891089135,-71.1513320296005674,99.8735873690646656],"rgb":[0.266666666666666663,0.933333333333333348,0.0666666666666666657],"xyz":[0.330582060012239609,0.624160289318059336,0.10835618690795179],"hpluv":[125.466600012922257,309.547675363147619,83.1341682891089135],"hsluv":[125.466600012922257,98.9247180409442279,83.1341682891089135]},"#44ee22":{"lch":[83.1738669889620184,121.064908518289769,125.897986234483838],"luv":[83.1738669889620184,-70.9856689153146192,98.0701120789979],"rgb":[0.266666666666666663,0.933333333333333348,0.133333333333333331],"xyz":[0.332457418150716666,0.624910432573450136,0.118233073103930983],"hpluv":[125.897986234483838,306.432309176179558,83.1738669889620184],"hsluv":[125.897986234483838,96.9444732717922,83.1738669889620184]},"#44ee33":{"lch":[83.2391611795664517,118.535427876706891,126.625494433478437],"luv":[83.2391611795664517,-70.7161072615436694,95.1308563805026921],"rgb":[0.266666666666666663,0.933333333333333348,0.2],"xyz":[0.335545168883174372,0.626145532866433263,0.134495226961542119],"hpluv":[126.625494433478437,301.369067751793693,83.2391611795664517],"hsluv":[126.625494433478437,93.7204451717133651,83.2391611795664517]},"#44ee44":{"lch":[83.3332795320092714,114.974418092600288,127.715012949240275],"luv":[83.3332795320092714,-70.3337997514069855,90.9520391649414],"rgb":[0.266666666666666663,0.933333333333333348,0.266666666666666663],"xyz":[0.340003164127393287,0.627928730964120829,0.157974001914428758],"hpluv":[127.715012949240275,294.205765091151079,83.3332795320092714],"hsluv":[127.715012949240275,89.1439564147074321,83.3332795320092714]},"#44ee55":{"lch":[83.4588814464859183,110.379279114867671,129.248151137931956],"luv":[83.4588814464859183,-69.8347997913980123,85.479155330485213],"rgb":[0.266666666666666663,0.933333333333333348,0.333333333333333315],"xyz":[0.345965578166755272,0.630313696579865579,0.189376049188402673],"hpluv":[129.248151137931956,284.901382538762221,83.4588814464859183],"hsluv":[129.248151137931956,89.2862876088480419,83.4588814464859183]},"#44ee66":{"lch":[83.6182069813856,104.810737833959209,131.33226272314829],"luv":[83.6182069813856,-69.2195888954281,78.7015837099029],"rgb":[0.266666666666666663,0.933333333333333348,0.4],"xyz":[0.353550573940263457,0.633347694889268897,0.229323693595546635],"hpluv":[131.33226272314829,273.53562680177663,83.6182069813856],"hsluv":[131.33226272314829,89.462046779026835,83.6182069813856]},"#44ee77":{"lch":[83.8131566406418642,98.3993759238413759,134.112401675041724],"luv":[83.8131566406418642,-68.4926783274834889,70.6483559449852123],"rgb":[0.266666666666666663,0.933333333333333348,0.466666666666666674],"xyz":[0.362864586960465363,0.637073300097349748,0.278377495501944572],"hpluv":[134.112401675041724,260.333399951005049,83.8131566406418642],"hsluv":[134.112401675041724,89.6701381262035682,83.8131566406418642]},"#44ee88":{"lch":[84.045338735079568,91.3569443918750892,137.785521400150031],"luv":[84.045338735079568,-67.6621349200187439,61.3834406553211949],"rgb":[0.266666666666666663,0.933333333333333348,0.533333333333333326],"xyz":[0.374005004062409163,0.641529466938127291,0.337050358905516712],"hpluv":[137.785521400150031,245.709311488591595,84.045338735079568],"hsluv":[137.785521400150031,89.9084899734552323,84.045338735079568]},"#44ee99":{"lch":[84.3160998906388386,83.9946679616676306,142.613931790318958],"luv":[84.3160998906388386,-66.738995210465,51.0001055321292895],"rgb":[0.266666666666666663,0.933333333333333348,0.6],"xyz":[0.387061968171481863,0.646752252581756504,0.405817036546634591],"hpluv":[142.613931790318958,230.343048149298568,84.3160998906388386],"hsluv":[142.613931790318958,90.1742147406472725,84.3160998906388386]},"#44eeaa":{"lch":[84.626546237332235,76.7502660373389887,148.925817786423067],"luv":[84.626546237332235,-65.7365837009088239,39.6144531722415607],"rgb":[0.266666666666666663,0.933333333333333348,0.66666666666666663],"xyz":[0.402119661136734419,0.652775329767857571,0.485120886163633247],"hpluv":[148.925817786423067,215.298316825794302,84.626546237332235],"hsluv":[148.925817786423067,90.4637941794664897,84.626546237332235]},"#44eebb":{"lch":[84.9775593290447,70.218708007349818,157.069253127653155],"luv":[84.9775593290447,-64.6697768267590618,27.3584889823731068],"rgb":[0.266666666666666663,0.933333333333333348,0.733333333333333282],"xyz":[0.419257253244071093,0.659630366610792329,0.575378871262274938],"hpluv":[157.069253127653155,202.183693696822303,84.9775593290447],"hsluv":[157.069253127653155,90.7732788992861401,84.9775593290447]},"#44eecc":{"lch":[85.3698091329633826,65.1592886039499462,167.256585364158155],"luv":[85.3698091329633826,-63.5542641697608914,14.3731832665241086],"rgb":[0.266666666666666663,0.933333333333333348,0.8],"xyz":[0.438549628687792792,0.667347316788281186,0.676985381932545094],"hpluv":[167.256585364158155,193.290067765431047,85.3698091329633826],"hsluv":[167.256585364158155,91.0984884260964,85.3698091329633826]},"#44eedd":{"lch":[85.803765500838054,62.4110099600490216,179.263728091065275],"luv":[85.803765500838054,-62.4058570040272613,0.801982435119061421],"rgb":[0.266666666666666663,0.933333333333333348,0.866666666666666696],"xyz":[0.460067954238426391,0.675954647008534693,0.790315229832551092],"hpluv":[179.263728091065275,191.499842549603557,85.803765500838054],"hsluv":[179.263728091065275,91.4351983708881875,85.803765500838054]},"#44eeee":{"lch":[86.2797089909746546,62.6494691870182407,192.17705063006116],"luv":[86.2797089909746546,-61.2398849709435922,-13.2148582346064085],"rgb":[0.266666666666666663,0.933333333333333348,0.933333333333333348],"xyz":[0.4838801345046011,0.68547951911500471,0.915726045901074315],"hpluv":[192.17705063006116,199.700166684316315,86.2797089909746546],"hsluv":[192.17705063006116,91.7793037580661775,86.2797089909746546]},"#44eeff":{"lch":[86.7977415696122847,66.0848691943621134,204.633388514668525],"luv":[86.7977415696122847,-60.0707080483631159,-27.5448719547627086],"rgb":[0.266666666666666663,0.933333333333333348,1],"xyz":[0.510051182914432522,0.695947938478937433,1.05356023419285627],"hpluv":[204.633388514668525,219.870556477974674,86.7977415696122847],"hsluv":[204.633388514668525,99.9999999999936904,86.7977415696122847]},"#44ff00":{"lch":[88.3264513606833,131.987460278186802,125.602389702763816],"luv":[88.3264513606833,-76.837408418496949,107.315899745634312],"rgb":[0.266666666666666663,1,0],"xyz":[0.381422766942276337,0.727460367977553535,0.120312206086420265],"hpluv":[125.602389702763816,502.990651378155178,88.3264513606833],"hsluv":[125.602389702763816,100.000000000002331,88.3264513606833]},"#44ff11":{"lch":[88.3457924202418496,131.213348009411362,125.799444038401859],"luv":[88.3457924202418496,-76.7532223203665609,106.423143908077066],"rgb":[0.266666666666666663,1,0.0666666666666666657],"xyz":[0.382434432441913441,0.727865034177408443,0.125640311051175901],"hpluv":[125.799444038401859,500.950310911531346,88.3457924202418496],"hsluv":[125.799444038401859,99.9999999999917577,88.3457924202418496]},"#44ff22":{"lch":[88.3816266358799538,129.789896608084,126.169061428897493],"luv":[88.3816266358799538,-76.5980824061806089,104.776672180562713],"rgb":[0.266666666666666663,1,0.133333333333333331],"xyz":[0.384309790580390498,0.728615177432799244,0.13551719724715508],"hpluv":[126.169061428897493,497.190929074143924,88.3816266358799538],"hsluv":[126.169061428897493,99.9999999999915445,88.3816266358799538]},"#44ff33":{"lch":[88.4405736189592204,127.478814054469,126.790121098902588],"luv":[88.4405736189592204,-76.3452168675528071,102.089450454884],"rgb":[0.266666666666666663,1,0.2],"xyz":[0.387397541312848204,0.72985027772578237,0.15177935110476623],"hpluv":[126.790121098902588,491.06642972530841,88.4405736189592204],"hsluv":[126.790121098902588,99.9999999999916,88.4405736189592204]},"#44ff44":{"lch":[88.5255621746627099,124.213522374992053,127.715012949240247],"luv":[88.5255621746627099,-75.9856771103925,98.2607552122302],"rgb":[0.266666666666666663,1,0.266666666666666663],"xyz":[0.391855536557067119,0.731633475823469936,0.175258126057652869],"hpluv":[127.715012949240247,482.369437382385513,88.5255621746627099],"hsluv":[127.715012949240247,99.9999999999915872,88.5255621746627099]},"#44ff55":{"lch":[88.6390158335401,119.977757557138,129.006344472088813],"luv":[88.6390158335401,-75.5147735105559832,93.2318684253877734],"rgb":[0.266666666666666663,1,0.333333333333333315],"xyz":[0.397817950596429104,0.734018441439214686,0.206660173331626784],"hpluv":[129.006344472088813,471.012302242813519,88.6390158335401],"hsluv":[129.006344472088813,99.9999999999916724,88.6390158335401]},"#44ff66":{"lch":[88.7829895920100256,114.806361082699226,130.743859599912923],"luv":[88.7829895920100256,-74.9316504675157518,86.9813100801842438],"rgb":[0.266666666666666663,1,0.4],"xyz":[0.405402946369937289,0.737052439748618,0.246607817738770746],"hpluv":[130.743859599912923,457.03528250903878,88.7829895920100256],"hsluv":[130.743859599912923,99.999999999991374,88.7829895920100256]},"#44ff77":{"lch":[88.9592430558717524,108.789243130847709,133.032335199193767],"luv":[88.9592430558717524,-74.2389756563468239,79.5215311376676226],"rgb":[0.266666666666666663,1,0.466666666666666674],"xyz":[0.414716959390139195,0.740778044956698856,0.295661619645168683],"hpluv":[133.032335199193767,440.631455855157412,88.9592430558717524],"hsluv":[133.032335199193767,99.999999999991374,88.9592430558717524]},"#44ff88":{"lch":[89.1692840038805343,102.078340317719523,136.01097660716411],"luv":[89.1692840038805343,-73.4425963051882462,70.8955048643657904],"rgb":[0.266666666666666663,1,0.533333333333333326],"xyz":[0.425857376492083,0.745234211797476398,0.354334483048740823],"hpluv":[136.01097660716411,422.1930512248951,89.1692840038805343],"hsluv":[136.01097660716411,99.9999999999912177,89.1692840038805343]},"#44ff99":{"lch":[89.4143964062191117,94.8987049380611438,139.863519733640288],"luv":[89.4143964062191117,-72.5511163277215303,61.1727040314764139],"rgb":[0.266666666666666663,1,0.6],"xyz":[0.43891434060115575,0.750456997441105611,0.423101160689858702],"hpluv":[139.863519733640288,402.3908266141122,89.4143964062191117],"hsluv":[139.863519733640288,99.9999999999912,89.4143964062191117]},"#44ffaa":{"lch":[89.695659684091666,87.5652599917726207,144.82485232612342],"luv":[89.695659684091666,-71.5753927145854192,50.4444042008586777],"rgb":[0.266666666666666663,1,0.66666666666666663],"xyz":[0.453972033566408251,0.756480074627206678,0.502405010306857358],"hpluv":[144.82485232612342,382.304282325397367,89.695659684091666],"hsluv":[144.82485232612342,99.9999999999909335,89.695659684091666]},"#44ffbb":{"lch":[90.0139628620153616,80.5050918065685153,151.171682460988421],"luv":[90.0139628620153616,-70.527972915407986,38.8184858440859557],"rgb":[0.266666666666666663,1,0.733333333333333282],"xyz":[0.471109625673744925,0.763335111470141436,0.592662995405499],"hpluv":[151.171682460988421,363.621116250194575,90.0139628620153616],"hsluv":[151.171682460988421,99.999999999990834,90.0139628620153616]},"#44ffcc":{"lch":[90.3700157308713443,74.2777558665274853,159.169074542576084],"luv":[90.3700157308713443,-69.4225064855060481,26.4140229771485018],"rgb":[0.266666666666666663,1,0.8],"xyz":[0.490402001117466679,0.771052061647630294,0.694269506075769205],"hpluv":[159.169074542576084,348.900804743837909,90.3700157308713443],"hsluv":[159.169074542576084,99.9999999999905924,90.3700157308713443]},"#44ffdd":{"lch":[90.7643583149998,69.56728840997188,168.931262835156701],"luv":[90.7643583149998,-68.2731674827513899,13.3559806299794577],"rgb":[0.266666666666666663,1,0.866666666666666696],"xyz":[0.511920326668100167,0.7796593918678838,0.807599353975775203],"hpluv":[168.931262835156701,341.810509676969502,90.7643583149998],"hsluv":[168.931262835156701,99.9999999999902798,90.7643583149998]},"#44ffee":{"lch":[91.1973694573754869,67.0945142582603182,180.196137266844971],"luv":[91.1973694573754869,-67.094121132442,-0.229680249688981986],"rgb":[0.266666666666666663,1,0.933333333333333348],"xyz":[0.535732506934274877,0.789184263974353817,0.933010170044298426],"hpluv":[180.196137266844971,347.079488330816218,91.1973694573754869],"hsluv":[180.196137266844971,99.999999999989825,91.1973694573754869]},"#44ffff":{"lch":[91.6692750397398726,67.4158875874256,192.177050630061103],"luv":[91.6692750397398726,-65.8990611515587261,-14.2202545175369188],"rgb":[0.266666666666666663,1,1],"xyz":[0.561903555344106298,0.799652683338286541,1.07084435833608027],"hpluv":[192.177050630061103,369.886157390881351,91.6692750397398726],"hsluv":[192.177050630061103,99.9999999999897,91.6692750397398726]},"#33aa00":{"lch":[61.1785977172963129,90.1064171712311435,124.683940112874311],"luv":[61.1785977172963129,-51.2749716142469723,74.09482911373847],"rgb":[0.2,0.66666666666666663,0],"xyz":[0.157393059993970491,0.294521282349826385,0.0485535951906325494],"hpluv":[124.683940112874311,186.894073454811917,61.1785977172963129],"hsluv":[124.683940112874311,100.000000000002302,61.1785977172963129]},"#33aa11":{"lch":[61.2139288108167818,88.7849168066190089,125.171000261233829],"luv":[61.2139288108167818,-51.1417680861379793,72.5760360544852148],"rgb":[0.2,0.66666666666666663,0.0666666666666666657],"xyz":[0.158404725493607623,0.294925948549681238,0.0538817001553881791],"hpluv":[125.171000261233829,184.046797309440706,61.2139288108167818],"hsluv":[125.171000261233829,97.729263879491441,61.2139288108167818]},"#33aa22":{"lch":[61.2793378507832642,86.3832953662584657,126.10140218084841],"luv":[61.2793378507832642,-50.8984310656693708,69.7955831939783593],"rgb":[0.2,0.66666666666666663,0.133333333333333331],"xyz":[0.160280083632084625,0.295676091805072039,0.0637585863513673717],"hpluv":[126.10140218084841,178.877217305585333,61.2793378507832642],"hsluv":[126.10140218084841,93.5778090815338146,61.2793378507832642]},"#33aa33":{"lch":[61.3867923044640946,82.5646745763668548,127.715012949240119],"luv":[61.3867923044640946,-50.5076466968263134,65.3138814728533],"rgb":[0.2,0.66666666666666663,0.2],"xyz":[0.163367834364542386,0.296911192098055166,0.0800207402089785219],"hpluv":[127.715012949240119,170.670578118814461,61.3867923044640946],"hsluv":[127.715012949240119,86.9017438736093339,61.3867923044640946]},"#33aa44":{"lch":[61.5414071550205364,77.3485744588317488,130.237764523164799],"luv":[61.5414071550205364,-49.9641607354037305,59.0456146789935588],"rgb":[0.2,0.66666666666666663,0.266666666666666663],"xyz":[0.167825829608761246,0.298694390195742732,0.10349951516186516],"hpluv":[130.237764523164799,159.486606837004757,61.5414071550205364],"hsluv":[130.237764523164799,87.1702267355774723,61.5414071550205364]},"#33aa55":{"lch":[61.7472402279952775,70.9239260559490106,134.00596147156574],"luv":[61.7472402279952775,-49.2732069613111605,51.0132763399638876],"rgb":[0.2,0.66666666666666663,0.333333333333333315],"xyz":[0.173788243648123231,0.301079355811487592,0.134901562435839062],"hpluv":[134.00596147156574,145.752006815371971,61.7472402279952775],"hsluv":[134.00596147156574,87.512567621072165,61.7472402279952775]},"#33aa66":{"lch":[62.0075227235960824,63.6834089970413046,139.532932917076664],"luv":[62.0075227235960824,-48.4490087982300253,41.3312246123130436],"rgb":[0.2,0.66666666666666663,0.4],"xyz":[0.181373239421631416,0.304113354120890911,0.174849206842983024],"hpluv":[139.532932917076664,130.323054003441854,62.0075227235960824],"hsluv":[139.532932917076664,87.9225345315596769,62.0075227235960824]},"#33aa77":{"lch":[62.3247799262656201,56.2910074750267,147.571074265173024],"luv":[62.3247799262656201,-47.5128361285441727,30.1862207898839152],"rgb":[0.2,0.66666666666666663,0.466666666666666674],"xyz":[0.190687252441833321,0.307838959328971706,0.223903008749380933],"hpluv":[147.571074265173024,114.608702125460667,62.3247799262656201],"hsluv":[147.571074265173024,88.3905588997681519,62.3247799262656201]},"#33aa88":{"lch":[62.7009046876535052,49.786919253891476,159.033972270618222],"luv":[62.7009046876535052,-46.4906641824602147,17.8144736848221363],"rgb":[0.2,0.66666666666666663,0.533333333333333326],"xyz":[0.201827669543777177,0.312295126169749304,0.2825758721529531],"hpluv":[159.033972270618222,100.758286424528237,62.7009046876535052],"hsluv":[159.033972270618222,88.9048289963628804,62.7009046876535052]},"#33aa99":{"lch":[63.1372095297142835,45.6309193537352797,174.368717478757389],"luv":[63.1372095297142835,-45.4107033068770818,4.47759156711236095],"rgb":[0.2,0.66666666666666663,0.6],"xyz":[0.214884633652849877,0.317517911813378462,0.351342549794071035],"hpluv":[174.368717478757389,91.7092542399893631,63.1372095297142835],"hsluv":[174.368717478757389,89.4524406674979,63.1372095297142835]},"#33aaaa":{"lch":[63.6344696573538897,45.3208071547743288,192.17705063006116],"luv":[63.6344696573538897,-44.3011098571894,-9.5596666563997],"rgb":[0.2,0.66666666666666663,0.66666666666666663],"xyz":[0.229942326618102433,0.323540988999479584,0.430646399411069636],"hpluv":[192.17705063006116,90.3742140686623117,63.6344696573538897],"hsluv":[192.17705063006116,90.0204628815860559,63.6344696573538897]},"#33aabb":{"lch":[64.1929631055189844,49.4317459506583177,209.109442205543161],"luv":[64.1929631055189844,-43.188124160558381,-24.0475245965695663],"rgb":[0.2,0.66666666666666663,0.733333333333333282],"xyz":[0.247079918725439052,0.330396025842414343,0.520904384509711327],"hpluv":[209.109442205543161,97.7142389408223835,64.1929631055189844],"hsluv":[209.109442205543161,90.5968047396532228,64.1929631055189844]},"#33aacc":{"lch":[64.8125111239688181,57.2242456540803062,222.641155468482083],"luv":[64.8125111239688181,-42.0947673064025736,-38.7639633693247347],"rgb":[0.2,0.66666666666666663,0.8],"xyz":[0.266372294169160806,0.338112976019903144,0.622510895179981483],"hpluv":[222.641155468482083,112.036763534802631,64.8125111239688181],"hsluv":[222.641155468482083,91.1708232266795875,64.8125111239688181]},"#33aadd":{"lch":[65.4925201274692199,67.4454999587780151,232.519386199289158],"luv":[65.4925201274692199,-41.0401119544032653,-53.5220017886062465],"rgb":[0.2,0.66666666666666663,0.866666666666666696],"xyz":[0.28789061971979435,0.34672030624015665,0.73584074307998748],"hpluv":[232.519386199289158,130.67743538587149,65.4925201274692199],"hsluv":[232.519386199289158,91.7336648454097485,65.4925201274692199]},"#33aaee":{"lch":[66.23202547083838,79.0605595482254,239.573325902293959],"luv":[66.23202547083838,-40.039054494753934,-68.1721804788773],"rgb":[0.2,0.66666666666666663,0.933333333333333348],"xyz":[0.311702799985969059,0.356245178346626667,0.861251559148510704],"hpluv":[239.573325902293959,151.471586303299148,66.23202547083838],"hsluv":[239.573325902293959,92.278374899274425,66.23202547083838]},"#33aaff":{"lch":[67.0297366624436,91.3892467801412778,244.667711773110682],"luv":[67.0297366624436,-39.1024682991195291,-82.6014007142609898],"rgb":[0.2,0.66666666666666663,1],"xyz":[0.33787384839580048,0.366713597710559391,0.999085747440292549],"hpluv":[244.667711773110682,173.00828905748071,67.0297366624436],"hsluv":[244.667711773110682,99.9999999999982094,67.0297366624436]},"#33bb00":{"lch":[66.705199456007648,99.1588934495857757,125.274120260315158],"luv":[66.705199456007648,-57.2631629787864327,80.9531735993793262],"rgb":[0.2,0.733333333333333282,0],"xyz":[0.191347557902569271,0.362430278167024944,0.0598717611601651684],"hpluv":[125.274120260315158,188.630237299381349,66.705199456007648],"hsluv":[125.274120260315158,100.000000000002331,66.705199456007648]},"#33bb11":{"lch":[66.7359690986495764,97.9890755357957914,125.670572132139952],"luv":[66.7359690986495764,-57.1397853669544133,79.6046723036925385],"rgb":[0.2,0.733333333333333282,0.0666666666666666657],"xyz":[0.192359223402206403,0.362834944366879797,0.0651998661249208],"hpluv":[125.670572132139952,186.318944611331347,66.7359690986495764],"hsluv":[125.670572132139952,98.1524285745497451,66.7359690986495764]},"#33bb22":{"lch":[66.7929473545782,95.8553977164860243,126.423299967719473],"luv":[66.7929473545782,-56.9137739802675,77.1302768224563],"rgb":[0.2,0.733333333333333282,0.133333333333333331],"xyz":[0.194234581540683404,0.363585087622270597,0.0750767523209],"hpluv":[126.423299967719473,182.106434833594022,66.7929473545782],"hsluv":[126.423299967719473,94.7659081903439073,66.7929473545782]},"#33bb33":{"lch":[66.8865907457163,92.4406335233364302,127.715012949240233],"luv":[66.8865907457163,-56.5491099236273058,73.126389853740946],"rgb":[0.2,0.733333333333333282,0.2],"xyz":[0.197322332273141166,0.364820187915253724,0.0913389061785111478],"hpluv":[127.715012949240233,175.373180985258983,66.8865907457163],"hsluv":[127.715012949240233,89.2962069049265637,66.8865907457163]},"#33bb44":{"lch":[67.0214179407225572,87.725631811763563,129.70178400392939],"luv":[67.0214179407225572,-56.0384119529137763,67.4943172612971409],"rgb":[0.2,0.733333333333333282,0.266666666666666663],"xyz":[0.201780327517360025,0.36660338601294129,0.114817681131397786],"hpluv":[129.70178400392939,166.093340387543549,67.0214179407225572],"hsluv":[129.70178400392939,89.4761749642590871,67.0214179407225572]},"#33bb55":{"lch":[67.2010629421400552,81.8171313208689099,132.60288320444127],"luv":[67.2010629421400552,-55.3830806540106479,60.2225651632978796],"rgb":[0.2,0.733333333333333282,0.333333333333333315],"xyz":[0.207742741556722,0.368988351628686151,0.146219728405371674],"hpluv":[132.60288320444127,154.492511096020365,67.2010629421400552],"hsluv":[132.60288320444127,89.7076242739581,67.2010629421400552]},"#33bb66":{"lch":[67.4284803792762091,74.9653268862145,136.738510871982356],"luv":[67.4284803792762091,-54.5922668909562248,51.3759148907695788],"rgb":[0.2,0.733333333333333282,0.4],"xyz":[0.215327737330230196,0.372022349938089469,0.186167372812515663],"hpluv":[136.738510871982356,141.07705768332076,67.4284803792762091],"hsluv":[136.738510871982356,89.9877463438330096,67.4284803792762091]},"#33bb77":{"lch":[67.7060530794905446,67.5982244112705,142.572908280802977],"luv":[67.7060530794905446,-53.681598162732449,41.0829156980295878],"rgb":[0.2,0.733333333333333282,0.466666666666666674],"xyz":[0.224641750350432101,0.375747955146170265,0.235221174718913573],"hpluv":[142.572908280802977,126.69139486293237,67.7060530794905446],"hsluv":[142.572908280802977,90.3115397167098,67.7060530794905446]},"#33bb88":{"lch":[68.0356563096068641,60.380187227113133,150.730801091974854],"luv":[68.0356563096068641,-52.67158330257773,29.5206931148449],"rgb":[0.2,0.733333333333333282,0.533333333333333326],"xyz":[0.235782167452375957,0.380204121986947863,0.293894038122485712],"hpluv":[150.730801091974854,112.615249481580875,68.0356563096068641],"hsluv":[150.730801091974854,90.6723452470342437,68.0356563096068641]},"#33bb99":{"lch":[68.4187011865960244,54.2829584497859159,161.862695711717],"luv":[68.4187011865960244,-51.585814888834193,16.8980259295610082],"rgb":[0.2,0.733333333333333282,0.6],"xyz":[0.248839131561448657,0.385426907630577,0.362660715763603647],"hpluv":[161.862695711717,100.676477021468287,68.4187011865960244],"hsluv":[161.862695711717,91.0624469223214,68.4187011865960244]},"#33bbaa":{"lch":[68.8561680799326439,50.5661966451060749,176.101011456941364],"luv":[68.8561680799326439,-50.4491601398581224,3.43838397135738649],"rgb":[0.2,0.733333333333333282,0.66666666666666663],"xyz":[0.263896824526701212,0.391449984816678143,0.441964565380602248],"hpluv":[176.101011456941364,93.1873079321678404,68.8561680799326439],"hsluv":[176.101011456941364,91.473675634614068,68.8561680799326439]},"#33bbbb":{"lch":[69.3486356756669835,50.4205674478029,192.177050630061103],"luv":[69.3486356756669835,-49.286127891295429,-10.635375839212843],"rgb":[0.2,0.733333333333333282,0.733333333333333282],"xyz":[0.281034416634037831,0.398305021659612901,0.532222550479243939],"hpluv":[192.177050630061103,92.2590830970113132,69.3486356756669835],"hsluv":[192.177050630061103,91.8979539795913922,69.3486356756669835]},"#33bbcc":{"lch":[69.8963087653012423,54.2786660468549442,207.559867588447844],"luv":[69.8963087653012423,-48.1195504219082224,-25.1133919457216273],"rgb":[0.2,0.733333333333333282,0.8],"xyz":[0.300326792077759586,0.406021971837101703,0.633829061149514095],"hpluv":[207.559867588447844,98.540384199822455,69.8963087653012423],"hsluv":[207.559867588447844,92.3277362004695306,69.8963087653012423]},"#33bbdd":{"lch":[70.4990463576295241,61.569428837921933,220.28187220447964],"luv":[70.4990463576295241,-46.9696505240293618,-39.807618580850594],"rgb":[0.2,0.733333333333333282,0.866666666666666696],"xyz":[0.321845117628393129,0.414629302057355209,0.747158909049520092],"hpluv":[220.28187220447964,110.820781636478685,70.4990463576295241],"hsluv":[220.28187220447964,92.7563200135089119,70.4990463576295241]},"#33bbee":{"lch":[71.1563908243766576,71.2672074810155181,229.953995552192254],"luv":[71.1563908243766576,-45.8534981630350487,-54.557048750410388],"rgb":[0.2,0.733333333333333282,0.933333333333333348],"xyz":[0.345657297894567894,0.424154174163825226,0.872569725118043316],"hpluv":[229.953995552192254,127.091105244163856,71.1563908243766576],"hsluv":[229.953995552192254,93.1780289437208893,71.1563908243766576]},"#33bbff":{"lch":[71.8675982303626597,82.4526478797043296,237.101125866277243],"luv":[71.8675982303626597,-44.7848112977892,-69.2297610814592161],"rgb":[0.2,0.733333333333333282,1],"xyz":[0.37182834630439926,0.43462259352775795,1.01040391340982527],"hpluv":[237.101125866277243,145.583046200088774,71.8675982303626597],"hsluv":[237.101125866277243,99.9999999999977831,71.8675982303626597]},"#33cc00":{"lch":[72.1534232831706532,108.011475964841438,125.713046635977918],"luv":[72.1534232831706532,-63.0491190384013507,87.6999859098336287],"rgb":[0.2,0.8,0],"xyz":[0.229571301212186191,0.438877764786259839,0.0726130089300371234],"hpluv":[125.713046635977918,189.955680955455,72.1534232831706532],"hsluv":[125.713046635977918,100.000000000002402,72.1534232831706532]},"#33cc11":{"lch":[72.1805088449519,106.967132064598133,126.040754358939225],"luv":[72.1805088449519,-62.9352412435677095,86.493483868665578],"rgb":[0.2,0.8,0.0666666666666666657],"xyz":[0.230582966711823323,0.439282430986114691,0.0779411138947927601],"hpluv":[126.040754358939225,188.048441784684599,72.1805088449519],"hsluv":[126.040754358939225,98.4728126855506645,72.1805088449519]},"#33cc22":{"lch":[72.2306742907645543,105.057034533260762,126.660198785960176],"luv":[72.2306742907645543,-62.7261976516662614,84.2757653960309199],"rgb":[0.2,0.8,0.133333333333333331],"xyz":[0.232458324850300324,0.440032574241505492,0.0878180000907719527],"hpluv":[126.660198785960176,184.562215611711281,72.2306742907645543],"hsluv":[126.660198785960176,95.6680740449206866,72.2306742907645543]},"#33cc33":{"lch":[72.31314692234902,101.984984863208481,127.715012949240304],"luv":[72.31314692234902,-62.3877173898115416,80.6765756365369668],"rgb":[0.2,0.8,0.2],"xyz":[0.235546075582758085,0.441267674534488619,0.104080153948383103],"hpluv":[127.715012949240304,178.960959976488198,72.31314692234902],"hsluv":[127.715012949240304,91.1230258822071306,72.31314692234902]},"#33cc44":{"lch":[72.4319472107582669,97.7091257880760651,129.318260791805528],"luv":[72.4319472107582669,-61.9111863445413135,75.5915224590797123],"rgb":[0.2,0.8,0.266666666666666663],"xyz":[0.240004070826976945,0.443050872632176185,0.127558928901269741],"hpluv":[129.318260791805528,171.176559629977817,72.4319472107582669],"hsluv":[129.318260791805528,91.2471619418673612,72.4319472107582669]},"#33cc55":{"lch":[72.590341240881628,92.2844112105744756,131.621023493746776],"luv":[72.590341240881628,-61.2953573189119396,68.9876200751215407],"rgb":[0.2,0.8,0.333333333333333315],"xyz":[0.24596648486633893,0.445435838247921045,0.158960976175243629],"hpluv":[131.621023493746776,161.32023063104279,72.590341240881628],"hsluv":[131.621023493746776,91.4078622695478,72.590341240881628]},"#33cc66":{"lch":[72.7910248315973405,85.8719567505974197,134.835055825888389],"luv":[72.7910248315973405,-60.5455878238572112,60.8951948123993319],"rgb":[0.2,0.8,0.4],"xyz":[0.253551480639847115,0.448469836557324364,0.198908620582387619],"hpluv":[134.835055825888389,149.696915507144809,72.7910248315973405],"hsluv":[134.835055825888389,91.6039613293452533,72.7910248315973405]},"#33cc77":{"lch":[73.0362204241858421,78.757716060864837,139.259917231121676],"luv":[73.0362204241858421,-59.6729854923348,51.3995393126768079],"rgb":[0.2,0.8,0.466666666666666674],"xyz":[0.262865493660049,0.452195441765405159,0.247962422488785528],"hpluv":[139.259917231121676,136.834039856532058,73.0362204241858421],"hsluv":[139.259917231121676,91.8328510325735294,73.0362204241858421]},"#33cc88":{"lch":[73.3277345291399,71.3846311778678597,145.306874573990314],"luv":[73.3277345291399,-58.6933246064594201,40.6307668527313197],"rgb":[0.2,0.8,0.533333333333333326],"xyz":[0.274005910761992877,0.456651608606182757,0.306635285892357667],"hpluv":[145.306874573990314,123.530949311180805,73.3277345291399],"hsluv":[145.306874573990314,92.0907512285691894,73.3277345291399]},"#33cc99":{"lch":[73.6669954969027714,64.400374936046,153.483372150156],"luv":[73.6669954969027714,-57.6257667092137709,28.7520312861295437],"rgb":[0.2,0.8,0.6],"xyz":[0.287062874871065576,0.461874394249811915,0.375401963533475602],"hpluv":[153.483372150156,110.931469165383049,73.6669954969027714],"hsluv":[153.483372150156,92.3730273510429072,73.6669954969027714]},"#33ccaa":{"lch":[74.0550811623464114,58.6991946004706691,164.236139418897579],"luv":[74.0550811623464114,-56.4914910882685106,15.9470022690160835],"rgb":[0.2,0.8,0.66666666666666663],"xyz":[0.302120567836318132,0.467897471435913037,0.454705813150474203],"hpluv":[164.236139418897579,100.581152280716978,74.0550811623464114],"hsluv":[164.236139418897579,92.6745296641919794,74.0550811623464114]},"#33ccbb":{"lch":[74.4927414449451106,55.3647402049724846,177.507530206592946],"luv":[74.4927414449451106,-55.3123621552270137,2.40770653799565881],"rgb":[0.2,0.8,0.733333333333333282],"xyz":[0.319258159943654751,0.474752508278847796,0.544963798249115894],"hpluv":[177.507530206592946,94.310193436061823,74.4927414449451106],"hsluv":[177.507530206592946,92.9899230693886,74.4927414449451106]},"#33cccc":{"lch":[74.9804187561532416,55.3552144916165361,192.177050630061132],"luv":[74.9804187561532416,-54.1097476482840918,-11.6762571422475752],"rgb":[0.2,0.8,0.8],"xyz":[0.338550535387376506,0.482469458456336597,0.646570308919386],"hpluv":[192.177050630061132,93.6806731785530928,74.9804187561532416],"hsluv":[192.177050630061132,93.3139795405001422,74.9804187561532416]},"#33ccdd":{"lch":[75.5182678303382602,59.0031963362726231,206.282454691493683],"luv":[75.5182678303382602,-52.9035678654544128,-26.1264173778571198],"rgb":[0.2,0.8,0.866666666666666696],"xyz":[0.360068860938010049,0.491076788676590104,0.759900156819392],"hpluv":[206.282454691493683,99.1431801932779564,75.5182678303382602],"hsluv":[206.282454691493683,93.6418135046530296,75.5182678303382602]},"#33ccee":{"lch":[76.106175853756767,65.8577115847402439,218.26062431545347],"luv":[76.106175853756767,-51.7116147040808585,-40.7817003063324606],"rgb":[0.2,0.8,0.933333333333333348],"xyz":[0.383881041204184759,0.500601660783060121,0.885310972887915271],"hpluv":[218.26062431545347,110.229350215344013,76.106175853756767],"hsluv":[218.26062431545347,93.969050662624,76.106175853756767]},"#33ccff":{"lch":[76.7437832939395435,75.0714180144803,227.674056146546604],"luv":[76.7437832939395435,-50.5491406549608,-55.5022718611574248],"rgb":[0.2,0.8,1],"xyz":[0.41005208961401618,0.511070080146992844,1.02314516117969712],"hpluv":[227.674056146546604,129.845560156838474,76.7437832939395435],"hsluv":[227.674056146546604,99.9999999999969731,76.7437832939395435]},"#33dd00":{"lch":[77.5280782787270653,116.686614644285086,126.047543424376144],"luv":[77.5280782787270653,-68.6649809221669187,94.3445092843369508],"rgb":[0.2,0.866666666666666696,0],"xyz":[0.272205291759361367,0.524145745880611358,0.0868243391124284419],"hpluv":[126.047543424376144,210.356208283509261,77.5280782787270653],"hsluv":[126.047543424376144,100.000000000002416,77.5280782787270653]},"#33dd11":{"lch":[77.5521415069474926,115.747372453695789,126.322097671746874],"luv":[77.5521415069474926,-68.5599423432795,93.2576459912042],"rgb":[0.2,0.866666666666666696,0.0666666666666666657],"xyz":[0.273216957258998472,0.524550412080466266,0.0921524440771840786],"hpluv":[126.322097671746874,208.932074165120611,77.5521415069474926],"hsluv":[126.322097671746874,98.7203227917640902,77.5521415069474926]},"#33dd22":{"lch":[77.5967156031793337,114.025807364398673,126.839335004613],"luv":[77.5967156031793337,-68.36681588768,91.2571270119929778],"rgb":[0.2,0.866666666666666696,0.133333333333333331],"xyz":[0.275092315397475529,0.525300555335857067,0.102029330273163271],"hpluv":[126.839335004613,206.31706664059891,77.5967156031793337],"hsluv":[126.839335004613,96.3665979525037102,77.5967156031793337]},"#33dd33":{"lch":[77.670013861504259,111.246421345384377,127.715012949240332],"luv":[77.670013861504259,-68.0532561222895,88.0029578668175247],"rgb":[0.2,0.866666666666666696,0.2],"xyz":[0.278180066129933234,0.526535655628840193,0.118291484130774421],"hpluv":[127.715012949240332,202.082466523340599,77.670013861504259],"hsluv":[127.715012949240332,92.5426273046004439,77.670013861504259]},"#33dd44":{"lch":[77.7756375941771267,107.354265763003397,129.034195217585733],"luv":[77.7756375941771267,-67.6100090567609726,83.3895979895470134],"rgb":[0.2,0.866666666666666696,0.266666666666666663],"xyz":[0.28263806137415215,0.52831885372652776,0.14177025908366106],"hpluv":[129.034195217585733,196.125875311323085,77.7756375941771267],"hsluv":[129.034195217585733,92.6304308505642098,77.7756375941771267]},"#33dd55":{"lch":[77.9165348137244,102.370875286307594,130.905664069221132],"luv":[77.9165348137244,-67.0340391276217105,77.3707548439410431],"rgb":[0.2,0.866666666666666696,0.333333333333333315],"xyz":[0.288600475413514135,0.530703819342272509,0.173172306357634975],"hpluv":[130.905664069221132,188.454179514464698,77.9165348137244],"hsluv":[130.905664069221132,92.7446831943234287,77.9165348137244]},"#33dd66":{"lch":[78.095166356878579,96.3992072274516261,133.476315028685519],"luv":[78.095166356878579,-66.3279238591037767,69.9529389705828777],"rgb":[0.2,0.866666666666666696,0.4],"xyz":[0.29618547118702232,0.533737817651675828,0.213119950764778909],"hpluv":[133.476315028685519,179.196222734944627,78.095166356878579],"hsluv":[133.476315028685519,92.8850067954864187,78.095166356878579]},"#33dd77":{"lch":[78.3135937781308513,89.6343875602499196,136.948304354896891],"luv":[78.3135937781308513,-65.499258897229538,61.1896275296294192],"rgb":[0.2,0.866666666666666696,0.466666666666666674],"xyz":[0.305499484207224226,0.537463422859756679,0.262173752671176818],"hpluv":[136.948304354896891,168.630388284117117,78.3135937781308513],"hsluv":[136.948304354896891,93.050064801238122,78.3135937781308513]},"#33dd88":{"lch":[78.5735314106716487,82.3820261839553609,141.59738099104726],"luv":[78.5735314106716487,-64.5599157920348432,51.1743638074698],"rgb":[0.2,0.866666666666666696,0.533333333333333326],"xyz":[0.316639901309168,0.541919589700534221,0.320846616074749],"hpluv":[141.59738099104726,157.233383580683977,78.5735314106716487],"hsluv":[141.59738099104726,93.2377028740416449,78.5735314106716487]},"#33dd99":{"lch":[78.8763801167060592,75.0869406053615762,147.781507566587862],"luv":[78.8763801167060592,-63.5251386535812799,40.0325543591259105],"rgb":[0.2,0.866666666666666696,0.6],"xyz":[0.329696865418240725,0.547142375344163434,0.389613293715866893],"hpluv":[147.781507566587862,145.760006886720333,78.8763801167060592],"hsluv":[147.781507566587862,93.4451205095912343,78.8763801167060592]},"#33ddaa":{"lch":[79.2232512041385633,68.3697583649377094,155.904677195463563],"luv":[79.2232512041385633,-62.4125308872686801,27.9123601138582131],"rgb":[0.2,0.866666666666666696,0.66666666666666663],"xyz":[0.344754558383493281,0.553165452530264501,0.468917143332865494],"hpluv":[155.904677195463563,135.355769729163313,79.2232512041385633],"hsluv":[155.904677195463563,93.6690625743759,79.2232512041385633]},"#33ddbb":{"lch":[79.6149850527770866,63.045401416642612,166.259028854183981],"luv":[79.6149850527770866,-61.2410113290283604,14.9753521221847095],"rgb":[0.2,0.866666666666666696,0.733333333333333282],"xyz":[0.361892150490829956,0.560020489373199259,0.559175128431507296],"hpluv":[166.259028854183981,127.658944712944631,79.6149850527770866],"hsluv":[166.259028854183981,93.9060163408359614,79.6149850527770866]},"#33ddcc":{"lch":[80.0521670478692613,60.0458591823856054,178.675787060338223],"luv":[80.0521670478692613,-60.0298228841068138,1.3876488942262355],"rgb":[0.2,0.866666666666666696,0.8],"xyz":[0.381184525934551655,0.567737439550688117,0.660781639101777452],"hpluv":[178.675787060338223,124.734340702728062,80.0521670478692613],"hsluv":[178.675787060338223,94.1523985056595905,80.0521670478692613]},"#33dddd":{"lch":[80.5351423549551555,60.1510343961145963,192.177050630061245],"luv":[80.5351423549551555,-58.7976638126828,-12.6878551809710149],"rgb":[0.2,0.866666666666666696,0.866666666666666696],"xyz":[0.402702851485185254,0.576344769770941623,0.774111487001783449],"hpluv":[192.177050630061245,128.603021497070955,80.5351423549551555],"hsluv":[192.177050630061245,94.4047190696773271,80.5351423549551555]},"#33ddee":{"lch":[81.0640304387754,63.6213092914002303,205.209077734070348],"luv":[81.0640304387754,-57.5619892131040913,-27.0977562499646396],"rgb":[0.2,0.866666666666666696,0.933333333333333348],"xyz":[0.426515031751359963,0.58586964187741164,0.899522303070306672],"hpluv":[205.209077734070348,140.476637056352985,81.0640304387754],"hsluv":[205.209077734070348,94.6597131799347835,81.0640304387754]},"#33ddff":{"lch":[81.6387398294900208,70.0938175080633528,216.50946924270437],"luv":[81.6387398294900208,-56.3385046754299452,-41.7027114680837769],"rgb":[0.2,0.866666666666666696,1],"xyz":[0.452686080161191384,0.596338061241344364,1.03735649136208852],"hpluv":[216.50946924270437,160.421433033358312,81.6387398294900208],"hsluv":[216.50946924270437,99.999999999996,81.6387398294900208]},"#33ee00":{"lch":[82.833762600699373,125.203353646442437,126.3077634478595],"luv":[82.833762600699373,-74.1357070958390239,100.894879442497455],"rgb":[0.2,0.933333333333333348,0],"xyz":[0.319384068099876184,0.618503298561642323,0.102550597892599626],"hpluv":[126.3077634478595,309.713105305240845,82.833762600699373],"hsluv":[126.3077634478595,100.000000000002302,82.833762600699373]},"#33ee11":{"lch":[82.85531245284119,124.353122892884315,126.540515263097504],"luv":[82.85531245284119,-74.0387382831010541,99.9097813362598544],"rgb":[0.2,0.933333333333333348,0.0666666666666666657],"xyz":[0.320395733599513288,0.618907964761497231,0.107878702857355263],"hpluv":[126.540515263097504,308.054239915702169,82.85531245284119],"hsluv":[126.540515263097504,98.9149262576223833,82.85531245284119]},"#33ee22":{"lch":[82.8952353009988,122.792060636983948,126.977870705292972],"luv":[82.8952353009988,-73.860225327277135,98.0946342573363808],"rgb":[0.2,0.933333333333333348,0.133333333333333331],"xyz":[0.322271091737990345,0.619658108016888,0.117755589053334456],"hpluv":[126.977870705292972,305.002845011722627,82.8952353009988],"hsluv":[126.977870705292972,96.9167682151396264,82.8952353009988]},"#33ee33":{"lch":[82.9608975691188846,120.264250910780831,127.715012949240375],"luv":[82.9608975691188846,-73.5697721383487391,95.1366316128687259],"rgb":[0.2,0.933333333333333348,0.2],"xyz":[0.325358842470448051,0.620893208309871159,0.134017742910945592],"hpluv":[127.715012949240375,300.046240285686,82.9608975691188846],"hsluv":[127.715012949240375,93.6639064416312834,82.9608975691188846]},"#33ee44":{"lch":[83.0555452014946241,116.707569363843,128.817932535493583],"luv":[83.0555452014946241,-73.1578713419028,90.9317469728687513],"rgb":[0.2,0.933333333333333348,0.266666666666666663],"xyz":[0.329816837714666966,0.622676406407558725,0.157496517863832231],"hpluv":[128.817932535493583,293.039720989359807,83.0555452014946241],"hsluv":[128.817932535493583,93.7274034182796356,83.0555452014946241]},"#33ee55":{"lch":[83.1818510898783643,112.121671621867506,130.367812557605703],"luv":[83.1818510898783643,-72.6203079673681202,85.4257579305358092],"rgb":[0.2,0.933333333333333348,0.333333333333333315],"xyz":[0.335779251754028951,0.625061372023303474,0.188898565137806146],"hpluv":[130.367812557605703,283.950089878719211,83.1818510898783643],"hsluv":[130.367812557605703,93.8103653792530139,83.1818510898783643]},"#33ee66":{"lch":[83.3420657578551,106.5703857928128,132.470647679843353],"luv":[83.3420657578551,-71.9576476395269,78.6088040502757224],"rgb":[0.2,0.933333333333333348,0.4],"xyz":[0.343364247527537136,0.628095370332706793,0.228846209544950108],"hpluv":[132.470647679843353,272.865433725808,83.3420657578551],"hsluv":[132.470647679843353,93.912785079345241,83.3420657578551]},"#33ee77":{"lch":[83.5380975272703523,100.188150337510052,135.268396470867572],"luv":[83.5380975272703523,-71.1748024762597851,70.5110839550557387],"rgb":[0.2,0.933333333333333348,0.466666666666666674],"xyz":[0.352678260547739042,0.631820975540787644,0.277900011451348],"hpluv":[135.268396470867572,260.019238129472967,83.5380975272703523],"hsluv":[135.268396470867572,94.0340074276028304,83.5380975272703523]},"#33ee88":{"lch":[83.7715600973053682,93.1909370684561651,138.951686086792108],"luv":[83.7715600973053682,-70.2805135444840801,61.1980405537673],"rgb":[0.2,0.933333333333333348,0.533333333333333326],"xyz":[0.363818677649682842,0.636277142381565186,0.336572874854920157],"hpluv":[138.951686086792108,245.83342468256393,83.7715600973053682],"hsluv":[138.951686086792108,94.1728069818675237,83.7715600973053682]},"#33ee99":{"lch":[84.0438031984902807,85.8935006436990278,143.770719305914184],"luv":[84.0438031984902807,-69.2867121669879822,50.7646035138469784],"rgb":[0.2,0.933333333333333348,0.6],"xyz":[0.376875641758755542,0.641499928025194399,0.405339552496038091],"hpluv":[143.770719305914184,230.989810482694878,84.0438031984902807],"hsluv":[143.770719305914184,94.3274826341768886,84.0438031984902807]},"#33eeaa":{"lch":[84.3559338989094698,78.7339796376561907,150.032255922422308],"luv":[84.3559338989094698,-68.2077782157370223,39.328596980513943],"rgb":[0.2,0.933333333333333348,0.66666666666666663],"xyz":[0.391933334724008098,0.647523005211295466,0.484643402113036692],"hpluv":[150.032255922422308,216.540119706931335,84.3559338989094698],"hsluv":[150.032255922422308,94.495967075681591,84.3559338989094698]},"#33eebb":{"lch":[84.7088326356722,72.2999891840671,158.051587623557367],"luv":[84.7088326356722,-67.0597412553262,27.0236847743774931],"rgb":[0.2,0.933333333333333348,0.733333333333333282],"xyz":[0.409070926831344772,0.654378042054230225,0.574901387211678383],"hpluv":[158.051587623557367,204.04938686040532,84.7088326356722],"hsluv":[158.051587623557367,94.6759444498571838,84.7088326356722]},"#33eecc":{"lch":[85.1031663228954,67.3294619946068451,168.005441410177127],"luv":[85.1031663228954,-65.8594808644086,13.992327638881461],"rgb":[0.2,0.933333333333333348,0.8],"xyz":[0.428363302275066471,0.662094992231719082,0.676507897881948539],"hpluv":[168.005441410177127,195.708498626929867,85.1031663228954],"hsluv":[168.005441410177127,94.8649680125767389,85.1031663228954]},"#33eedd":{"lch":[85.539399954776755,64.6250931348259314,179.663789762776076],"luv":[85.539399954776755,-64.6239805156479861,0.37921629457989664],"rgb":[0.2,0.933333333333333348,0.866666666666666696],"xyz":[0.44988162782570007,0.670702322451972588,0.789837745781954537],"hpluv":[179.663789762776076,194.233009793031641,85.539399954776755],"hsluv":[179.663789762776076,95.0605698730458926,85.539399954776755]},"#33eeee":{"lch":[86.0178075751720286,64.8282855412949601,192.177050630061217],"luv":[86.0178075751720286,-63.3696789602654533,-13.6744431219908602],"rgb":[0.2,0.933333333333333348,0.933333333333333348],"xyz":[0.47369380809187478,0.680227194558442605,0.91524856185047776],"hpluv":[192.177050630061217,202.327515221469156,86.0178075751720286],"hsluv":[192.177050630061217,95.2603564020327127,86.0178075751720286]},"#33eeff":{"lch":[86.538483142230433,68.1460620684978124,204.293044736593487],"luv":[86.538483142230433,-62.1119480142598803,-28.035543321245509],"rgb":[0.2,0.933333333333333348,1],"xyz":[0.499864856501706201,0.690695613922375329,1.05308275014225972],"hpluv":[204.293044736593487,221.878852364873978,86.538483142230433],"hsluv":[204.293044736593487,99.999999999993932,86.538483142230433]},"#33ff00":{"lch":[88.074762753062231,133.577745567808222,126.513803819973305],"luv":[88.074762753062231,-79.4809541468946,107.358241597361044],"rgb":[0.2,1,0],"xyz":[0.37123644052955,0.72220804342099143,0.119834722035823737],"hpluv":[126.513803819973305,497.272976699974663,88.074762753062231],"hsluv":[126.513803819973305,100.00000000000226,88.074762753062231]},"#33ff11":{"lch":[88.0941974462199,132.80363803677966,126.71317891025123],"luv":[88.0941974462199,-79.3912833442141448,106.460464045403725],"rgb":[0.2,1,0.0666666666666666657],"xyz":[0.37224810602918712,0.722612709620846339,0.125162827000579374],"hpluv":[126.71317891025123,495.277769978645495,88.0941974462199],"hsluv":[126.71317891025123,99.9999999999917861,88.0941974462199]},"#33ff22":{"lch":[88.1302050034733355,131.38040615815558,127.087058789859782],"luv":[88.1302050034733355,-79.2260405323659285,104.804797713872986],"rgb":[0.2,1,0.133333333333333331],"xyz":[0.374123464167664177,0.723362852876237139,0.135039713196558553],"hpluv":[127.087058789859782,491.602558840386564,88.1302050034733355],"hsluv":[127.087058789859782,99.9999999999915161,88.1302050034733355]},"#33ff33":{"lch":[88.1894367416410745,129.070276381710187,127.715012949240347],"luv":[88.1894367416410745,-78.9567203165017162,102.10275491931047],"rgb":[0.2,1,0.2],"xyz":[0.377211214900121883,0.724597953169220266,0.151301867054169703],"hpluv":[127.715012949240347,485.618062737129037,88.1894367416410745],"hsluv":[127.715012949240347,99.9999999999917577,88.1894367416410745]},"#33ff44":{"lch":[88.2748349985884,125.807640063387211,128.649544439126117],"luv":[88.2748349985884,-78.5738101086462137,98.2533391968394909],"rgb":[0.2,1,0.266666666666666663],"xyz":[0.381669210144340798,0.726381151266907832,0.174780642007056342],"hpluv":[128.649544439126117,477.126267833886629,88.2748349985884],"hsluv":[128.649544439126117,99.9999999999917151,88.2748349985884]},"#33ff55":{"lch":[88.3888340150102181,121.57774004888698,129.95306271607248],"luv":[88.3888340150102181,-78.0723424240601,93.1979410921456122],"rgb":[0.2,1,0.333333333333333315],"xyz":[0.387631624183702783,0.728766116882652581,0.206182689281030257],"hpluv":[129.95306271607248,466.04908765344419,88.3888340150102181],"hsluv":[129.95306271607248,99.999999999991644,88.3888340150102181]},"#33ff66":{"lch":[88.5334972733264,116.417510431790106,131.704600668064415],"luv":[88.5334972733264,-77.4514410423726929,86.9155395518881],"rgb":[0.2,1,0.4],"xyz":[0.395216619957210968,0.7318001151920559,0.246130333688174219],"hpluv":[131.704600668064415,452.43688525451455,88.5334972733264],"hsluv":[131.704600668064415,99.9999999999913882,88.5334972733264]},"#33ff77":{"lch":[88.7105909437740081,110.419515958012653,134.007319384137503],"luv":[88.7105909437740081,-76.7139872603015505,79.419353202025647],"rgb":[0.2,1,0.466666666666666674],"xyz":[0.404530632977412874,0.735525720400136751,0.295184135594572128],"hpluv":[134.007319384137503,436.493157669178117,88.7105909437740081],"hsluv":[134.007319384137503,99.9999999999915,88.7105909437740081]},"#33ff88":{"lch":[88.9216276204312379,103.738746998712813,136.99719245927011],"luv":[88.9216276204312379,-75.8662497359534882,70.7533729221786558],"rgb":[0.2,1,0.533333333333333326],"xyz":[0.415671050079356674,0.739981887240914293,0.353856998998144268],"hpluv":[136.99719245927011,418.619650658891032,88.9216276204312379],"hsluv":[136.99719245927011,99.9999999999912603,88.9216276204312379]},"#33ff99":{"lch":[89.1678944508512359,96.6032590942606788,140.85189111032139],"luv":[89.1678944508512359,-74.9174292298428242,60.9882649796200695],"rgb":[0.2,1,0.6],"xyz":[0.428728014188429429,0.745204672884543506,0.422623676639262202],"hpluv":[140.85189111032139,399.492483487252343,89.1678944508512359],"hsluv":[140.85189111032139,99.9999999999913456,89.1678944508512359]},"#33ffaa":{"lch":[89.4504724790268426,89.3298939826383105,145.795546705853383],"luv":[89.4504724790268426,-73.8791171714821,50.2165909327964926],"rgb":[0.2,1,0.66666666666666663],"xyz":[0.44378570715368193,0.751227750070644573,0.501927526256260803],"hpluv":[145.795546705853383,380.184928602968114,89.4504724790268426],"hsluv":[145.795546705853383,99.9999999999912,89.4504724790268426]},"#33ffbb":{"lch":[89.7702508712150262,82.3444719603705,152.087330110215447],"luv":[89.7702508712150262,-72.7646918614874494,38.5475249625060314],"rgb":[0.2,1,0.733333333333333282],"xyz":[0.460923299261018604,0.758082786913579332,0.592185511354902605],"hpluv":[152.087330110215447,362.351543222333419,89.7702508712150262],"hsluv":[152.087330110215447,99.9999999999909761,89.7702508712150262]},"#33ffcc":{"lch":[90.127938152783571,76.1985663634222,159.968053619612647],"luv":[90.127938152783571,-71.5886883295869723,26.1013643147272063],"rgb":[0.2,1,0.8],"xyz":[0.480215674704740358,0.765799737091068189,0.693792022025172761],"hpluv":[159.968053619612647,348.464440630653087,90.127938152783571],"hsluv":[159.968053619612647,99.999999999990834,90.127938152783571]},"#33ffdd":{"lch":[90.5240717550146314,71.5577226375514357,169.529475161807255],"luv":[90.5240717550146314,-70.3661811113599924,13.0041618290463337],"rgb":[0.2,1,0.866666666666666696],"xyz":[0.501734000255373846,0.774407067311321695,0.807121869925178759],"hpluv":[169.529475161807255,342.013155745428833,90.5240717550146314],"hsluv":[169.529475161807255,99.9999999999904077,90.5240717550146314]},"#33ffee":{"lch":[90.9590266887802,69.1149718308150511,180.51167449693034],"luv":[90.9590266887802,-69.1122158161064561,-0.61721646306864264],"rgb":[0.2,1,0.933333333333333348],"xyz":[0.525546180521548667,0.783931939417791712,0.932532685993702],"hpluv":[180.51167449693034,347.442342228089899,90.9590266887802],"hsluv":[180.51167449693034,99.9999999999901519,90.9590266887802]},"#33ffff":{"lch":[91.4330238629877243,69.4028497051403122,192.177050630061132],"luv":[91.4330238629877243,-67.8413175363212702,-14.6393709608822622],"rgb":[0.2,1,1],"xyz":[0.55171722893138,0.794400358781724436,1.07036687428548372],"hpluv":[192.177050630061132,369.590917988860895,91.4330238629877243],"hsluv":[192.177050630061132,99.9999999999897256,91.4330238629877243]},"#22aa00":{"lch":[60.8595101229647923,91.9296409673314656,126.268252023172565],"luv":[60.8595101229647923,-54.3824975763784053,74.1188427172042594],"rgb":[0.133333333333333331,0.66666666666666663,0],"xyz":[0.150337683054585614,0.290883353615456,0.0482228743965988915],"hpluv":[126.268252023172565,191.675426474830772,60.8595101229647923],"hsluv":[126.268252023172565,100.000000000002288,60.8595101229647923]},"#22aa11":{"lch":[60.8951349805759605,90.6090655032342482,126.765726538166419],"luv":[60.8951349805759605,-54.2335583573106,72.5859759132132893],"rgb":[0.133333333333333331,0.66666666666666663,0.0666666666666666657],"xyz":[0.151349348554222746,0.291288019815310828,0.0535509793613545212],"hpluv":[126.765726538166419,188.811473003651798,60.8951349805759605],"hsluv":[126.765726538166419,97.6988909499644365,60.8951349805759605]},"#22aa22":{"lch":[60.9610867967894592,88.21068058626,127.715012949240347],"luv":[60.9610867967894592,-53.9615024560723953,69.7802294505720226],"rgb":[0.133333333333333331,0.66666666666666663,0.133333333333333331],"xyz":[0.153224706692699747,0.292038163070701628,0.0634278655573337208],"hpluv":[127.715012949240347,183.614848439340193,60.9610867967894592],"hsluv":[127.715012949240347,93.4926845994439475,60.9610867967894592]},"#22aa33":{"lch":[61.0694299105106495,84.4016098893730629,129.358188857231823],"luv":[61.0694299105106495,-53.5246691509727626,65.259034196016259],"rgb":[0.133333333333333331,0.66666666666666663,0.2],"xyz":[0.156312457425157481,0.293273263363684755,0.0796900194149448571],"hpluv":[129.358188857231823,175.374397166590711,61.0694299105106495],"hsluv":[129.358188857231823,93.5882360519160699,61.0694299105106495]},"#22aa44":{"lch":[61.2253168994486145,79.2082340196825214,131.918899994809664],"luv":[61.2253168994486145,-52.917281977470445,58.938150671985575],"rgb":[0.133333333333333331,0.66666666666666663,0.266666666666666663],"xyz":[0.160770452669376368,0.295056461461372321,0.103168794367831496],"hpluv":[131.918899994809664,164.164260791814144,61.2253168994486145],"hsluv":[131.918899994809664,93.7213426507132397,61.2253168994486145]},"#22aa55":{"lch":[61.4328316402448422,72.8294169380228169,135.724592815827151],"luv":[61.4328316402448422,-52.1453123372646488,50.8428005993127883],"rgb":[0.133333333333333331,0.66666666666666663,0.333333333333333315],"xyz":[0.166732866708738381,0.297441427077117182,0.134570841641805411],"hpluv":[135.724592815827151,150.433869175471955,61.4328316402448422],"hsluv":[135.724592815827151,93.8909627694616802,61.4328316402448422]},"#22aa66":{"lch":[61.695221435526193,65.6694032551541511,141.26425661379642],"luv":[61.695221435526193,-51.2247747289881588,41.0912761769754056],"rgb":[0.133333333333333331,0.66666666666666663,0.4],"xyz":[0.174317862482246538,0.3004754253865205,0.174518486048949373],"hpluv":[141.26425661379642,135.067502346464636,61.695221435526193],"hsluv":[141.26425661379642,94.0939374356695737,61.695221435526193]},"#22aa77":{"lch":[62.015018576984005,58.3994247120946,149.232117680428786],"luv":[62.015018576984005,-50.1795183581889,29.8748848373309741],"rgb":[0.133333333333333331,0.66666666666666663,0.466666666666666674],"xyz":[0.183631875502448472,0.304201030594601296,0.223572287955347282],"hpluv":[149.232117680428786,119.495353216490457,62.015018576984005],"hsluv":[149.232117680428786,94.3254538020573534,62.015018576984005]},"#22aa88":{"lch":[62.3941144695078265,52.0455462506657582,160.428514439052776],"luv":[62.3941144695078265,-49.0385773736463904,17.4343572780611709],"rgb":[0.133333333333333331,0.66666666666666663,0.533333333333333326],"xyz":[0.194772292604392272,0.308657197435378894,0.282245151358919477],"hpluv":[160.428514439052776,105.847175197261592,62.3941144695078265],"hsluv":[160.428514439052776,94.5795977554836753,62.3941144695078265]},"#22aa99":{"lch":[62.8338123759312168,48.0032947436357915,175.177921691935865],"luv":[62.8338123759312168,-47.8333890460383486,4.03524455451089725],"rgb":[0.133333333333333331,0.66666666666666663,0.6],"xyz":[0.207829256713465,0.313879983079008051,0.351011829000037356],"hpluv":[175.177921691935865,96.9431131493944918,62.8338123759312168],"hsluv":[175.177921691935865,94.8499327714938119,62.8338123759312168]},"#22aaaa":{"lch":[63.334871160235295,47.6677335272966047,192.177050630061132],"luv":[63.334871160235295,-46.595231466735612,-10.0547115418935782],"rgb":[0.133333333333333331,0.66666666666666663,0.66666666666666663],"xyz":[0.222886949678717528,0.319903060265109174,0.430315678617035957],"hpluv":[192.177050630061132,95.5038628742744748,63.334871160235295],"hsluv":[192.177050630061132,95.1300327368807075,63.334871160235295]},"#22aabb":{"lch":[63.8975462810157211,51.5875561200845425,208.460106210027732],"luv":[63.8975462810157211,-45.3531553267970224,-24.5838818811491713],"rgb":[0.133333333333333331,0.66666666666666663,0.733333333333333282],"xyz":[0.240024541786054202,0.326758097108043932,0.520573663715677704],"hpluv":[208.460106210027732,102.447201536891086,63.8975462810157211],"hsluv":[208.460106210027732,95.4139121453229393,63.8975462810157211]},"#22aacc":{"lch":[64.5216311304052681,59.1142282054053112,221.706391964203618],"luv":[64.5216311304052681,-44.1325525375176184,-39.3295027027292079],"rgb":[0.133333333333333331,0.66666666666666663,0.8],"xyz":[0.259316917229775901,0.334475047285532734,0.62218017438594786],"hpluv":[221.706391964203618,116.258847224370101,64.5216311304052681],"hsluv":[221.706391964203618,95.6963242429470853,64.5216311304052681]},"#22aadd":{"lch":[65.2065000175346796,69.0826091468118619,231.553565124642319],"luv":[65.2065000175346796,-42.9543721979751538,-54.1047945713593279],"rgb":[0.133333333333333331,0.66666666666666663,0.866666666666666696],"xyz":[0.2808352427804095,0.34308237750578624,0.735510022285953857],"hpluv":[231.553565124642319,134.436491082611866,65.2065000175346796],"hsluv":[231.553565124642319,95.9729250289437,65.2065000175346796]},"#22aaee":{"lch":[65.951153016283925,80.4876559434330687,238.683318882444183],"luv":[65.951153016283925,-41.8348964739996418,-68.7612114224159825],"rgb":[0.133333333333333331,0.66666666666666663,0.933333333333333348],"xyz":[0.304647423046584209,0.352607249612256257,0.86092083835447708],"hpluv":[238.683318882444183,154.862481256054423,65.951153016283925],"hsluv":[238.683318882444183,96.2403212652285305,65.951153016283925]},"#22aaff":{"lch":[66.7542622474436911,92.6475815050926741,243.881654723446388],"luv":[66.7542622474436911,-40.785937465112724,-83.187028218555227],"rgb":[0.133333333333333331,0.66666666666666663,1],"xyz":[0.33081847145641563,0.363075668976189,0.998755026646258925],"hpluv":[243.881654723446388,176.114215620682756,66.7542622474436911],"hsluv":[243.881654723446388,99.9999999999982521,66.7542622474436911]},"#22bb00":{"lch":[66.4275479271698117,100.802558180890344,126.547308547849156],"luv":[66.4275479271698117,-60.0265444602621798,80.9812922592122533],"rgb":[0.133333333333333331,0.733333333333333282,0],"xyz":[0.184292180963184393,0.358792349432654534,0.0595410403661315105],"hpluv":[126.547308547849156,192.558484368086766,66.4275479271698117],"hsluv":[126.547308547849156,100.000000000002402,66.4275479271698117]},"#22bb11":{"lch":[66.4585250929908682,99.6331665050874449,126.950333401467461],"luv":[66.4585250929908682,-59.891738470658936,79.6225315522727612],"rgb":[0.133333333333333331,0.733333333333333282,0.0666666666666666657],"xyz":[0.185303846462821525,0.359197015632509387,0.0648691453308871402],"hpluv":[126.950333401467461,190.235936561387632,66.4585250929908682],"hsluv":[126.950333401467461,98.1323711753334464,66.4585250929908682]},"#22bb22":{"lch":[66.5158870179191553,97.5011623585143496,127.715012949240375],"luv":[66.5158870179191553,-59.6448091899021904,77.1295883430057785],"rgb":[0.133333333333333331,0.733333333333333282,0.133333333333333331],"xyz":[0.187179204601298527,0.359947158887900187,0.0747460315268663328],"hpluv":[127.715012949240375,186.004620566556611,66.5158870179191553],"hsluv":[127.715012949240375,94.7095045552014341,66.5158870179191553]},"#22bb33":{"lch":[66.6101592341861561,94.091611241079562,129.025604662043349],"luv":[66.6101592341861561,-59.2464412491434089,73.0964465979998721],"rgb":[0.133333333333333331,0.733333333333333282,0.2],"xyz":[0.19026695533375626,0.361182259180883314,0.091008185384477483],"hpluv":[129.025604662043349,179.246118589082698,66.6101592341861561],"hsluv":[129.025604662043349,94.7728361420699628,66.6101592341861561]},"#22bb44":{"lch":[66.7458880420052907,89.3893698914418735,131.03732282887168],"luv":[66.7458880420052907,-58.6886365964374903,67.424797990356],"rgb":[0.133333333333333331,0.733333333333333282,0.266666666666666663],"xyz":[0.194724950577975148,0.36296545727857088,0.114486960337364121],"hpluv":[131.03732282887168,169.941985039444177,66.7458880420052907],"hsluv":[131.03732282887168,94.8616428317247511,66.7458880420052907]},"#22bb55":{"lch":[66.9267274999506,83.5071173210959472,133.96576260666626],"luv":[66.9267274999506,-57.9730125462468777,60.1046459068846488],"rgb":[0.133333333333333331,0.733333333333333282,0.333333333333333315],"xyz":[0.200687364617337161,0.365350422894315741,0.145889007611338023],"hpluv":[133.96576260666626,158.330006142604873,66.9267274999506],"hsluv":[133.96576260666626,94.9758066387206128,66.9267274999506]},"#22bb66":{"lch":[67.1556458878222315,76.7025221245859541,138.121353671725132],"luv":[67.1556458878222315,-57.1096598103208919,51.2031606116460054],"rgb":[0.133333333333333331,0.733333333333333282,0.4],"xyz":[0.208272360390845318,0.368384421203719059,0.185836652018481985],"hpluv":[138.121353671725132,144.932719296840418,67.1556458878222315],"hsluv":[138.121353671725132,95.1139083236691363,67.1556458878222315]},"#22bb77":{"lch":[67.4350338747947831,69.4107315991336407,143.945643371462126],"luv":[67.4350338747947831,-56.1157304677756557,40.8518598743670935],"rgb":[0.133333333333333331,0.733333333333333282,0.466666666666666674],"xyz":[0.217586373411047251,0.372110026411799855,0.234890453924879894],"hpluv":[143.945643371462126,130.611184627207962,67.4350338747947831],"hsluv":[143.945643371462126,95.2734443978328471,67.4350338747947831]},"#22bb88":{"lch":[67.7667691572368653,62.2973404800357571,152.016434409622292],"luv":[67.7667691572368653,-55.0136735570032656,29.2310511724943218],"rgb":[0.133333333333333331,0.733333333333333282,0.533333333333333326],"xyz":[0.228726790512991052,0.376566193252577452,0.293563317328452089],"hpluv":[152.016434409622292,116.65196328010299,67.7667691572368653],"hsluv":[152.016434409622292,95.4510958201536823,67.7667691572368653]},"#22bb99":{"lch":[68.1522602188863402,56.3167420179958214,162.907285030510934],"luv":[68.1522602188863402,-53.8292536917802948,16.552549003324323],"rgb":[0.133333333333333331,0.733333333333333282,0.6],"xyz":[0.241783754622063779,0.38178897889620661,0.362329994969569968],"hpluv":[162.907285030510934,104.856796539193,68.1522602188863402],"hsluv":[162.907285030510934,95.6430286983925555,68.1522602188863402]},"#22bbaa":{"lch":[68.5924801056558238,52.6774965449754617,176.68900923381463],"luv":[68.5924801056558238,-52.5895649511659542,3.04241688349887474],"rgb":[0.133333333333333331,0.733333333333333282,0.66666666666666663],"xyz":[0.256841447587316307,0.387812056082307732,0.441633844586568569],"hpluv":[176.68900923381463,97.4513697523019,68.5924801056558238],"hsluv":[176.68900923381463,95.8451953079369616,68.5924801056558238]},"#22bbbb":{"lch":[69.087995915136645,52.5025293878432677,192.177050630061075],"luv":[69.087995915136645,-51.3212466461144174,-11.0745309069971647],"rgb":[0.133333333333333331,0.733333333333333282,0.733333333333333282],"xyz":[0.273979039694653,0.394667092925242491,0.531891829685210316],"hpluv":[192.177050630061075,96.4310638968393903,69.087995915136645],"hsluv":[192.177050630061075,96.05360442262905,69.087995915136645]},"#22bbcc":{"lch":[69.6389970716796824,56.2104265974936,207.07804051519031],"luv":[69.6389970716796824,-50.0490518690675117,-25.5871933841835393],"rgb":[0.133333333333333331,0.733333333333333282,0.8],"xyz":[0.293271415138374736,0.402384043102731292,0.633498340355480472],"hpluv":[207.07804051519031,102.424464009042,69.6389970716796824],"hsluv":[207.07804051519031,96.2645382772070519,69.6389970716796824]},"#22bbdd":{"lch":[70.2453239794146924,63.2897284454122868,219.558412279776348],"luv":[70.2453239794146924,-48.7948432782897541,-40.3069844585422956],"rgb":[0.133333333333333331,0.733333333333333282,0.866666666666666696],"xyz":[0.314789740689008224,0.410991373322984799,0.746828188255486469],"hpluv":[219.558412279776348,114.328666738486675,70.2453239794146924],"hsluv":[219.558412279776348,96.4747049793171101,70.2453239794146924]},"#22bbee":{"lch":[70.9064977498674409,72.7777709471329644,229.176572531806158],"luv":[70.9064977498674409,-47.5770176148035588,-55.072963774560229],"rgb":[0.133333333333333331,0.733333333333333282,0.933333333333333348],"xyz":[0.338601920955183,0.420516245429454816,0.872239004324009692],"hpluv":[229.176572531806158,130.242295294742263,70.9064977498674409],"hsluv":[229.176572531806158,96.6813261778791286,70.9064977498674409]},"#22bbff":{"lch":[71.621751136046143,83.782469360031385,236.362391595167765],"luv":[71.621751136046143,-46.4103062114400586,-69.7537500742789121],"rgb":[0.133333333333333331,0.733333333333333282,1],"xyz":[0.364772969365014355,0.43098466479338754,1.01007319261579154],"hpluv":[236.362391595167765,148.438838585801221,71.621751136046143],"hsluv":[236.362391595167765,99.9999999999977405,71.621751136046143]},"#22cc00":{"lch":[71.9091745039523431,109.499123564337054,126.755635680122666],"luv":[71.9091745039523431,-65.5246489265194185,87.7301455852794732],"rgb":[0.133333333333333331,0.8,0],"xyz":[0.222515924272801313,0.435239836051889428,0.0722822881360034586],"hpluv":[126.755635680122666,193.226045742870838,71.9091745039523431],"hsluv":[126.755635680122666,100.000000000002288,71.9091745039523431]},"#22cc11":{"lch":[71.9364107151438077,108.454952609175663,127.087674169957992],"luv":[71.9364107151438077,-65.4022833696805,86.5159989567857508],"rgb":[0.133333333333333331,0.8,0.0666666666666666657],"xyz":[0.223527589772438445,0.435644502251744281,0.0776103931007591],"hpluv":[127.087674169957992,191.311003889673145,71.9364107151438077],"hsluv":[127.087674169957992,98.4591341389350418,71.9364107151438077]},"#22cc22":{"lch":[71.9868548113652196,106.54571101335867,127.715012949240403],"luv":[71.9868548113652196,-65.1776701905061771,84.2843985793322332],"rgb":[0.133333333333333331,0.8,0.133333333333333331],"xyz":[0.225402947910915447,0.436394645507135082,0.0874872792967382878],"hpluv":[127.715012949240403,187.811464536348922,71.9868548113652196],"hsluv":[127.715012949240403,95.6295101801496,71.9868548113652196]},"#22cc33":{"lch":[72.0697845089905229,103.47656324227728,128.782383231673776],"luv":[72.0697845089905229,-64.8140104316899084,80.6631464312780224],"rgb":[0.133333333333333331,0.8,0.2],"xyz":[0.22849069864337318,0.437629745800118208,0.103749433154349424],"hpluv":[128.782383231673776,182.191494825933376,72.0697845089905229],"hsluv":[128.782383231673776,95.6728206524347,72.0697845089905229]},"#22cc44":{"lch":[72.1892409305665126,99.2080881077430092,130.402545810446583],"luv":[72.1892409305665126,-64.3020931154350563,75.5479024657046381],"rgb":[0.133333333333333331,0.8,0.266666666666666663],"xyz":[0.232948693887592068,0.439412943897805774,0.127228208107236063],"hpluv":[130.402545810446583,174.38692971209278,72.1892409305665126],"hsluv":[130.402545810446583,95.7338579762306807,72.1892409305665126]},"#22cc55":{"lch":[72.3485056391290584,93.798910065649892,132.724941359454647],"luv":[72.3485056391290584,-63.6406395178356732,68.9064912128369116],"rgb":[0.133333333333333331,0.8,0.333333333333333315],"xyz":[0.23891110792695408,0.441797909513550635,0.158630255381209978],"hpluv":[132.724941359454647,164.515777124050715,72.3485056391290584],"hsluv":[132.724941359454647,95.8128514989610665,72.3485056391290584]},"#22cc66":{"lch":[72.5502856399570106,87.4149553130202577,135.957009780349864],"luv":[72.5502856399570106,-62.8354766726053597,60.7706942835425821],"rgb":[0.133333333333333331,0.8,0.4],"xyz":[0.246496103700462238,0.444831907822953954,0.19857789978835394],"hpluv":[135.957009780349864,152.89241471165704,72.5502856399570106],"hsluv":[135.957009780349864,95.9092114165347454,72.5502856399570106]},"#22cc77":{"lch":[72.7968107106438,80.347487444586676,140.388595454497391],"luv":[72.7968107106438,-61.8986076052927601,51.2277377519640922],"rgb":[0.133333333333333331,0.8,0.466666666666666674],"xyz":[0.255810116720664171,0.448557513031034749,0.247631701694751849],"hpluv":[140.388595454497391,140.055211607516185,72.7968107106438],"hsluv":[140.388595454497391,96.0216367005683651,72.7968107106438]},"#22cc88":{"lch":[73.0898911189871399,73.0433057087839899,146.410934307510047],"luv":[73.0898911189871399,-60.8470337434031379,40.4099368162836328],"rgb":[0.133333333333333331,0.8,0.533333333333333326],"xyz":[0.266950533822607972,0.453013679871812347,0.306304565098324044],"hpluv":[146.410934307510047,126.812607157634474,73.0898911189871399],"hsluv":[146.410934307510047,96.1482500942118463,73.0898911189871399]},"#22cc99":{"lch":[73.4309556061454316,66.1476907411168,154.494840416347301],"luv":[73.4309556061454316,-59.7013675833161201,28.4826912187770667],"rgb":[0.133333333333333331,0.8,0.6],"xyz":[0.280007497931680671,0.458236465515441505,0.375071242739441923],"hpluv":[154.494840416347301,114.307528246897718,73.4309556061454316],"hsluv":[154.494840416347301,96.2867563581127826,73.4309556061454316]},"#22ccaa":{"lch":[73.8210792378530272,60.5373530055450857,165.03572853292485],"luv":[73.8210792378530272,-58.4843517505691963,15.631753236079188],"rgb":[0.133333333333333331,0.8,0.66666666666666663],"xyz":[0.295065190896933227,0.464259542701542627,0.454375092356440524],"hpluv":[165.03572853292485,104.059650734936554,73.8210792378530272],"hsluv":[165.03572853292485,96.4346108423233233,73.8210792378530272]},"#22ccbb":{"lch":[74.2610062314211916,57.2561659312404601,177.947236116536601],"luv":[74.2610062314211916,-57.2194225987583565,2.05090580243043252],"rgb":[0.133333333333333331,0.8,0.733333333333333282],"xyz":[0.312202783004269901,0.471114579544477385,0.544633077455082271],"hpluv":[177.947236116536601,97.8364666306377302,74.2610062314211916],"hsluv":[177.947236116536601,96.5891828531354406,74.2610062314211916]},"#22cccc":{"lch":[74.7511706210643467,57.2167927817266,192.177050630061132],"luv":[74.7511706210643467,-55.9294412838427633,-12.0689259631595149],"rgb":[0.133333333333333331,0.8,0.8],"xyz":[0.3314951584479916,0.478831529721966187,0.646239588125352427],"hpluv":[192.177050630061132,97.128087782713564,74.7511706210643467],"hsluv":[192.177050630061132,96.747899952527,74.7511706210643467]},"#22ccdd":{"lch":[75.2917163799825602,60.7443465218384091,205.915913497891523],"luv":[75.2917163799825602,-54.6356779140553357,-26.5484148912282159],"rgb":[0.133333333333333331,0.8,0.866666666666666696],"xyz":[0.353013483998625199,0.487438859942219693,0.759569436025358424],"hpluv":[205.915913497891523,102.375961416692178,75.2917163799825602],"hsluv":[205.915913497891523,96.9083635301369,75.2917163799825602]},"#22ccee":{"lch":[75.8825178700112843,67.4282526949852894,217.691288579377613],"luv":[75.8825178700112843,-53.3570890727704779,-41.2260877015904583],"rgb":[0.133333333333333331,0.8,0.933333333333333348],"xyz":[0.376825664264799909,0.49696373204868971,0.884980252093881647],"hpluv":[217.691288579377613,112.755958051566466,75.8825178700112843],"hsluv":[217.691288579377613,97.0684311053177851,75.8825178700112843]},"#22ccff":{"lch":[76.5232010138481,76.4669756721874165,227.041443142980768],"luv":[76.5232010138481,-52.1098871667616095,-55.9621124325938553],"rgb":[0.133333333333333331,0.8,1],"xyz":[0.40299671267463133,0.507432151412622434,1.02281444038566338],"hpluv":[227.041443142980768,130.754689276117347,76.5232010138481],"hsluv":[227.041443142980768,99.999999999997,76.5232010138481]},"#22dd00":{"lch":[77.3111928538645543,118.038829613749726,126.914864539429317],"luv":[77.3111928538645543,-70.8973873693031607,94.3754510494695],"rgb":[0.133333333333333331,0.866666666666666696,0],"xyz":[0.265149914819976518,0.520507817146241,0.0864936183183947771],"hpluv":[126.914864539429317,210.347075729226248,77.3111928538645543],"hsluv":[126.914864539429317,100.000000000002288,77.3111928538645543]},"#22dd11":{"lch":[77.3353680300965323,117.099630973594756,127.192375056145337],"luv":[77.3353680300965323,-70.7859197567446756,93.2827805028547346],"rgb":[0.133333333333333331,0.866666666666666696,0.0666666666666666657],"xyz":[0.266161580319613622,0.520912483346095856,0.0918217232831504138],"hpluv":[127.192375056145337,208.941659016378082,77.3353680300965323],"hsluv":[127.192375056145337,98.7107326231664217,77.3353680300965323]},"#22dd22":{"lch":[77.3801492665193535,115.37848303888174,127.715012949240432],"luv":[77.3801492665193535,-70.5809801545768636,91.2716801027172409],"rgb":[0.133333333333333331,0.866666666666666696,0.133333333333333331],"xyz":[0.268036938458090679,0.521662626601486656,0.101698609479129606],"hpluv":[127.715012949240432,206.361699793513822,77.3801492665193535],"hsluv":[127.715012949240432,96.3395071146262154,77.3801492665193535]},"#22dd33":{"lch":[77.4537875025684315,112.600723810091978,128.59932725776207],"luv":[77.4537875025684315,-70.24826089977104,88.0005956974969195],"rgb":[0.133333333333333331,0.866666666666666696,0.2],"xyz":[0.271124689190548385,0.522897726894469783,0.117960763336740743],"hpluv":[128.59932725776207,202.185786680839726,77.4537875025684315],"hsluv":[128.59932725776207,96.3699377868481122,77.4537875025684315]},"#22dd44":{"lch":[77.5598997380018,108.71293616133481,129.930302741787841],"luv":[77.5598997380018,-69.7779723132927217,83.3638834787812],"rgb":[0.133333333333333331,0.866666666666666696,0.266666666666666663],"xyz":[0.2755826844347673,0.524680924992157349,0.141439538289627381],"hpluv":[129.930302741787841,196.316024449944422,77.5598997380018],"hsluv":[129.930302741787841,96.4129906320409162,77.5598997380018]},"#22dd55":{"lch":[77.7014460191091416,103.73899221962921,131.815952634500974],"luv":[77.7014460191091416,-69.1669361195931,77.3156740549574266],"rgb":[0.133333333333333331,0.866666666666666696,0.333333333333333315],"xyz":[0.281545098474129285,0.527065890607902099,0.172841585563601297],"hpluv":[131.815952634500974,188.764163413831653,77.7014460191091416],"hsluv":[131.815952634500974,96.4690009350202189,77.7014460191091416]},"#22dd66":{"lch":[77.880896240080375,97.784990294992113,134.401120560320578],"luv":[77.880896240080375,-68.4179393254247117,69.8633659756971923],"rgb":[0.133333333333333331,0.866666666666666696,0.4],"xyz":[0.28913009424763747,0.530099888917305417,0.212789229970745258],"hpluv":[134.401120560320578,179.664283635232721,77.880896240080375],"hsluv":[134.401120560320578,96.5377748783722467,77.880896240080375]},"#22dd77":{"lch":[78.1003183749745205,91.0497694522495635,137.883451987021573],"luv":[78.1003183749745205,-67.5390964016577584,61.0616980975421],"rgb":[0.133333333333333331,0.866666666666666696,0.466666666666666674],"xyz":[0.298444107267839376,0.533825494125386268,0.261843031877143195],"hpluv":[137.883451987021573,169.299836923025936,78.1003183749745205],"hsluv":[137.883451987021573,96.6186469084632478,78.1003183749745205]},"#22dd88":{"lch":[78.3614307373917285,83.8424849668191143,142.529576014285681],"luv":[78.3614307373917285,-66.5430534683674608,51.0057283108209205],"rgb":[0.133333333333333331,0.866666666666666696,0.533333333333333326],"xyz":[0.309584524369783176,0.538281660966163811,0.320515895280715335],"hpluv":[142.529576014285681,158.150702843881334,78.3614307373917285],"hsluv":[142.529576014285681,96.7105501690208,78.3614307373917285]},"#22dd99":{"lch":[78.665635872828048,76.6094810635621144,148.680389056502293],"luv":[78.665635872828048,-65.4460211356496586,39.8224924677044854],"rgb":[0.133333333333333331,0.866666666666666696,0.6],"xyz":[0.322641488478855876,0.543504446609793,0.389282572921833214],"hpluv":[148.680389056502293,146.968629494944878,78.665635872828048],"hsluv":[148.680389056502293,96.8121015046769884,78.665635872828048]},"#22ddaa":{"lch":[79.0140446006893882,69.96699558248838,156.711923446039975],"luv":[79.0140446006893882,-64.2666918031728613,27.6617569130368608],"rgb":[0.133333333333333331,0.866666666666666696,0.66666666666666663],"xyz":[0.337699181444108432,0.549527523795894091,0.46858642253883187],"hpluv":[156.711923446039975,136.880679993502099,79.0140446006893882],"hsluv":[156.711923446039975,96.9216963326973513,79.0140446006893882]},"#22ddbb":{"lch":[79.4074947696843196,64.7136880558744849,166.88262774299784],"luv":[79.4074947696843196,-63.0251268096233161,14.6865520944819572],"rgb":[0.133333333333333331,0.866666666666666696,0.733333333333333282],"xyz":[0.354836773551445106,0.556382560638828849,0.558844407637473561],"hpluv":[166.88262774299784,129.476815865977585,79.4074947696843196],"hsluv":[166.88262774299784,97.0376060255481,79.4074947696843196]},"#22ddcc":{"lch":[79.8465673347569123,61.7508733998812431,179.012513434233142],"luv":[79.8465673347569123,-61.7417023409151184,1.06421693934889783],"rgb":[0.133333333333333331,0.866666666666666696,0.8],"xyz":[0.374129148995166805,0.564099510816317706,0.660450918307743717],"hpluv":[179.012513434233142,126.735630147597362,79.8465673347569123],"hsluv":[179.012513434233142,97.1580701030331824,79.8465673347569123]},"#22dddd":{"lch":[80.3316012938198867,61.8272738566169,192.177050630061245],"luv":[80.3316012938198867,-60.4361886569793,-13.0414298740249546],"rgb":[0.133333333333333331,0.866666666666666696,0.866666666666666696],"xyz":[0.395647474545800404,0.572706841036571213,0.773780766207749715],"hpluv":[192.177050630061245,130.583134255532286,80.3316012938198867],"hsluv":[192.177050630061245,97.2813767637234434,80.3316012938198867]},"#22ddee":{"lch":[80.8627083873859078,65.1993477029452606,204.924336649163848],"luv":[80.8627083873859078,-59.1270126845314579,-27.4763773429615092],"rgb":[0.133333333333333331,0.866666666666666696,0.933333333333333348],"xyz":[0.419459654811975113,0.58223171314304123,0.899191582276272938],"hpluv":[204.924336649163848,142.193638870282854,80.8627083873859078],"hsluv":[204.924336649163848,97.405927410883,80.8627083873859078]},"#22ddff":{"lch":[81.4397880620905141,71.5324096951162574,216.054756332513932],"luv":[81.4397880620905141,-57.8307265123863,-42.1009822669203544],"rgb":[0.133333333333333331,0.866666666666666696,1],"xyz":[0.445630703221806534,0.592700132506974,1.03702577056805478],"hpluv":[216.054756332513932,161.676156351457934,81.4397880620905141],"hsluv":[216.054756332513932,99.9999999999961,81.4397880620905141]},"#22ee00":{"lch":[82.639607109796458,126.437751030410212,127.039022267349651],"luv":[82.639607109796458,-76.1608929793909368,100.92583052028732],"rgb":[0.133333333333333331,0.933333333333333348,0],"xyz":[0.312328691160491334,0.614865369827271913,0.102219877098565962],"hpluv":[127.039022267349651,308.746810598848469,82.639607109796458],"hsluv":[127.039022267349651,100.000000000002203,82.639607109796458]},"#22ee11":{"lch":[82.6612418520526262,125.587498690937579,127.273852876359626],"luv":[82.6612418520526262,-76.0589691017437,99.9362449095734462],"rgb":[0.133333333333333331,0.933333333333333348,0.0666666666666666657],"xyz":[0.313340356660128438,0.615270036027126821,0.107547982063321598],"hpluv":[127.273852876359626,307.111076239802628,82.6612418520526262],"hsluv":[127.273852876359626,98.9080389542438638,82.6612418520526262]},"#22ee22":{"lch":[82.7013218186993271,124.026614606467561,127.715012949240375],"luv":[82.7013218186993271,-75.8713392100017643,98.112899341636421],"rgb":[0.133333333333333331,0.933333333333333348,0.133333333333333331],"xyz":[0.315215714798605495,0.616020179282517621,0.117424868259300791],"hpluv":[127.715012949240375,304.102865014696874,82.7013218186993271],"hsluv":[127.715012949240375,96.8972824334497176,82.7013218186993271]},"#22ee33":{"lch":[82.7672420886773921,121.499708898279266,128.458265706389938],"luv":[82.7672420886773921,-75.5660658728233443,95.1417308591278754],"rgb":[0.133333333333333331,0.933333333333333348,0.2],"xyz":[0.318303465531063201,0.617255279575500748,0.133687022116911941],"hpluv":[128.458265706389938,299.21821405622444,82.7672420886773921],"hsluv":[128.458265706389938,96.9191735237910308,82.7672420886773921]},"#22ee44":{"lch":[82.8622607061112575,117.945648419515081,129.569612755667265],"luv":[82.8622607061112575,-75.1331770294334,90.918544261133448],"rgb":[0.133333333333333331,0.933333333333333348,0.266666666666666663],"xyz":[0.322761460775282116,0.619038477673188314,0.15716579706979858],"hpluv":[129.569612755667265,292.317409010606752,82.8622607061112575],"hsluv":[129.569612755667265,96.9502397298715692,82.8622607061112575]},"#22ee55":{"lch":[82.9890600071846194,113.365618159982461,131.129866929811442],"luv":[82.9890600071846194,-74.5682726576598185,85.3893207236587],"rgb":[0.133333333333333331,0.933333333333333348,0.333333333333333315],"xyz":[0.328723874814644101,0.621423443288933064,0.188567844343772495],"hpluv":[131.129866929811442,283.372415217622233,82.9890600071846194],"hsluv":[131.129866929811442,96.9908233877961266,82.9890600071846194]},"#22ee66":{"lch":[83.1498978333136,107.825536766413322,133.243989823694022],"luv":[83.1498978333136,-73.8719849852999175,78.5447402013449647],"rgb":[0.133333333333333331,0.933333333333333348,0.4],"xyz":[0.336308870588152287,0.624457441598336382,0.228515488750916429],"hpluv":[133.243989823694022,272.476761047092111,83.1498978333136],"hsluv":[133.243989823694022,97.0409162623008683,83.1498978333136]},"#22ee77":{"lch":[83.3466879629012709,101.462411308546436,136.05169958656856],"luv":[83.3466879629012709,-73.0495185954435726,70.415827350948561],"rgb":[0.133333333333333331,0.933333333333333348,0.466666666666666674],"xyz":[0.345622883608354192,0.628183046806417233,0.277569290657314338],"hpluv":[136.05169958656856,259.869348467080897,83.3466879629012709],"hsluv":[136.05169958656856,97.1001922741487391,83.3466879629012709]},"#22ee88":{"lch":[83.5810478428977746,94.494960715205238,139.739189865999265],"luv":[83.5810478428977746,-72.1101014829990277,61.0690663485185681],"rgb":[0.133333333333333331,0.933333333333333348,0.533333333333333326],"xyz":[0.356763300710298,0.632639213647194776,0.336242154060886533],"hpluv":[139.739189865999265,245.976403795765407,83.5810478428977746],"hsluv":[139.739189865999265,97.1680458209452098,83.5810478428977746]},"#22ee99":{"lch":[83.8543293451422187,87.2401092672494514,144.548413258572367],"luv":[83.8543293451422187,-71.0663081347816,50.6005584263049286],"rgb":[0.133333333333333331,0.933333333333333348,0.6],"xyz":[0.369820264819370692,0.637861999290824,0.405008831702004413],"hpluv":[144.548413258572367,231.480208097577446,83.8543293451422187],"hsluv":[144.548413258572367,97.2436385928483844,83.8543293451422187]},"#22eeaa":{"lch":[84.1676401551603846,80.1359348037682508,150.771943883792943],"luv":[84.1676401551603846,-69.9332745317766324,39.1293388665967328],"rgb":[0.133333333333333331,0.933333333333333348,0.66666666666666663],"xyz":[0.384877957784623248,0.643885076476925056,0.484312681319003],"hpluv":[150.771943883792943,217.42312560604816,84.1676401551603846],"hsluv":[150.771943883792943,97.3259536357082311,84.1676401551603846]},"#22eebb":{"lch":[84.5218598825754697,73.7647249619211181,158.704077932293842],"luv":[84.5218598825754697,-68.7278540770417834,26.7902355844945639],"rgb":[0.133333333333333331,0.933333333333333348,0.733333333333333282],"xyz":[0.402015549891959922,0.650740113319859814,0.57457066641764476],"hpluv":[158.704077932293842,205.339796192481117,84.5218598825754697],"hsluv":[158.704077932293842,97.4138533690930331,84.5218598825754697]},"#22eecc":{"lch":[84.9176532530853621,68.8500130904050422,168.499772582144715],"luv":[84.9176532530853621,-67.467774257192545,13.7267526869778429],"rgb":[0.133333333333333331,0.933333333333333348,0.8],"xyz":[0.421307925335681621,0.658457063497348671,0.676177177087914916],"hpluv":[168.499772582144715,197.354512375483154,84.9176532530853621],"hsluv":[168.499772582144715,97.5061375012374896,84.9176532530853621]},"#22eedd":{"lch":[85.3554818050158275,66.1709053937965166,179.926877690260085],"luv":[85.3554818050158275,-66.170851505859261,0.0844489448895467398],"rgb":[0.133333333333333331,0.933333333333333348,0.866666666666666696],"xyz":[0.44282625088631522,0.667064393717602178,0.789507024987920913],"hpluv":[179.926877690260085,196.075052309852396,85.3554818050158275],"hsluv":[179.926877690260085,97.6015969291830174,85.3554818050158275]},"#22eeee":{"lch":[85.8356149635753667,66.3470894225537648,192.177050630061245],"luv":[85.8356149635753667,-64.8543104533760868,-13.9948094114017536],"rgb":[0.133333333333333331,0.933333333333333348,0.933333333333333348],"xyz":[0.46663843115248993,0.676589265824072195,0.914917841056444137],"hpluv":[192.177050630061245,204.089886920334152,85.8356149635753667],"hsluv":[192.177050630061245,97.6990604766853608,85.8356149635753667]},"#22eeff":{"lch":[86.35814102124138,69.583621560973242,204.067857145017655],"luv":[86.35814102124138,-63.5342376580599435,-28.377474072755291],"rgb":[0.133333333333333331,0.933333333333333348,1],"xyz":[0.492809479562321351,0.687057685188004919,1.05275202934822598],"hpluv":[204.067857145017655,223.225826840448832,86.35814102124138],"hsluv":[204.067857145017655,99.9999999999940883,86.35814102124138]},"#22ff00":{"lch":[87.8997189713237361,134.70927246092154,127.137510750393233],"luv":[87.8997189713237361,-81.328032504319566,107.388729464162736],"rgb":[0.133333333333333331,1,0],"xyz":[0.364181063590165166,0.718570114686621,0.119504001241790073],"hpluv":[127.137510750393233,493.515561032875894,87.8997189713237361],"hsluv":[127.137510750393233,100.000000000002359,87.8997189713237361]},"#22ff11":{"lch":[87.9192191859362708,133.935112153716517,127.338384986715198],"luv":[87.9192191859362708,-81.2344832365115792,106.487431187561],"rgb":[0.133333333333333331,1,0.0666666666666666657],"xyz":[0.36519272908980227,0.718974780886475928,0.124832106206545709],"hpluv":[127.338384986715198,491.550771148457443,87.9192191859362708],"hsluv":[127.338384986715198,99.9999999999918572,87.9192191859362708]},"#22ff22":{"lch":[87.9553480404818089,132.511927889398493,127.71501294924046],"luv":[87.9553480404818089,-81.0620967295481449,104.825319015849075],"rgb":[0.133333333333333331,1,0.133333333333333331],"xyz":[0.367068087228279327,0.719724924141866729,0.134708992402524902],"hpluv":[127.71501294924046,487.932270281505453,87.9553480404818089],"hsluv":[127.71501294924046,99.9999999999918,87.9553480404818089]},"#22ff33":{"lch":[88.0147790356886,130.202284180175667,128.347396099003475],"luv":[88.0147790356886,-80.7811428723405101,102.112887345201102],"rgb":[0.133333333333333331,1,0.2],"xyz":[0.370155837960737033,0.720960024434849855,0.150971146260136052],"hpluv":[128.347396099003475,482.0420586134328,88.0147790356886],"hsluv":[128.347396099003475,99.9999999999918572,88.0147790356886]},"#22ff44":{"lch":[88.1004639745127349,126.941230298117631,129.288082018787549],"luv":[88.1004639745127349,-80.3817123888383,98.2489504424236486],"rgb":[0.133333333333333331,1,0.266666666666666663],"xyz":[0.374613833204955948,0.722743222532537422,0.174449921213022691],"hpluv":[129.288082018787549,473.688351575452941,88.1004639745127349],"hsluv":[129.288082018787549,99.9999999999917719,88.1004639745127349]},"#22ff55":{"lch":[88.2148445849976497,122.715034192366474,130.599301535876663],"luv":[88.2148445849976497,-79.8586444797792865,93.1749779645044498],"rgb":[0.133333333333333331,1,0.333333333333333315],"xyz":[0.380576247244317933,0.725128188148282171,0.205851968486996606],"hpluv":[130.599301535876663,462.799362736769183,88.2148445849976497],"hsluv":[130.599301535876663,99.9999999999917,88.2148445849976497]},"#22ff66":{"lch":[88.3599902775167863,117.562049147645283,132.359544385640646],"luv":[88.3599902775167863,-79.2110524978463104,86.8702743288911279],"rgb":[0.133333333333333331,1,0.4],"xyz":[0.388161243017826119,0.72816218645768549,0.24579961289414054],"hpluv":[132.359544385640646,449.432018335727776,88.3599902775167863],"hsluv":[132.359544385640646,99.999999999991644,88.3599902775167863]},"#22ff77":{"lch":[88.5376718023346427,111.576626717172417,134.67079586388752],"luv":[88.5376718023346427,-78.441973739162,79.3486004003085839],"rgb":[0.133333333333333331,1,0.466666666666666674],"xyz":[0.397475256038028,0.731887791665766341,0.294853414800538449],"hpluv":[134.67079586388752,433.796433649144,88.5376718023346427],"hsluv":[134.67079586388752,99.9999999999914593,88.5376718023346427]},"#22ff88":{"lch":[88.7494051061703,104.915784817642518,137.666744209541747],"luv":[88.7494051061703,-77.5579802767934581,70.6546643845003786],"rgb":[0.133333333333333331,1,0.533333333333333326],"xyz":[0.408615673139971824,0.736343958506543883,0.353526278204110644],"hpluv":[137.666744209541747,416.300130961303353,88.7494051061703],"hsluv":[137.666744209541747,99.9999999999915161,88.7494051061703]},"#22ff99":{"lch":[88.996479539624346,97.8095196496336143,141.520869213027311],"luv":[88.996479539624346,-76.5687003963823827,60.8599725082183696],"rgb":[0.133333333333333331,1,0.6],"xyz":[0.42167263724904458,0.741566744150173096,0.422292955845228524],"hpluv":[141.520869213027311,397.621886071746928,88.996479539624346],"hsluv":[141.520869213027311,99.9999999999913882,88.996479539624346]},"#22ffaa":{"lch":[89.2799772586324281,90.5758041558366784,146.450029989774293],"luv":[89.2799772586324281,-75.4862499862398,50.057989986528554],"rgb":[0.133333333333333331,1,0.66666666666666663],"xyz":[0.43673033021429708,0.747589821336274163,0.50159680546222718],"hpluv":[146.450029989774293,378.829469872945424,89.2799772586324281],"hsluv":[146.450029989774293,99.9999999999911893,89.2799772586324281]},"#22ffbb":{"lch":[89.6007875020334552,83.6393655876379825,152.701818689515648],"luv":[89.6007875020334552,-74.3245992165371661,38.3587985630895787],"rgb":[0.133333333333333331,1,0.733333333333333282],"xyz":[0.453867922321633754,0.754444858179208921,0.591854790560868871],"hpluv":[152.701818689515648,361.553698033539774,89.6007875020334552],"hsluv":[152.701818689515648,99.9999999999909903,89.6007875020334552]},"#22ffcc":{"lch":[89.9596178804745,77.5461751086222,160.50148390925915],"luv":[89.9596178804745,-73.0989125181650223,25.8835519710636532],"rgb":[0.133333333333333331,1,0.8],"xyz":[0.473160297765355509,0.762161808356697779,0.693461301231139],"hpluv":[160.50148390925915,348.207300802542932,89.9596178804745],"hsluv":[160.50148390925915,99.999999999990834,89.9596178804745]},"#22ffdd":{"lch":[90.3570039795250466,72.9493687180361,169.926987012389134],"luv":[90.3570039795250466,-71.8249031216737421,12.7590629719491808],"rgb":[0.133333333333333331,1,0.866666666666666696],"xyz":[0.494678623315989,0.770769138576951285,0.806791149131145],"hpluv":[169.926987012389134,342.16275562632859,90.3570039795250466],"hsluv":[169.926987012389134,99.9999999999906,90.3570039795250466]},"#22ffee":{"lch":[90.793318095908873,70.5238201303846637,180.720785562676866],"luv":[90.793318095908873,-70.5182397089352,-0.887171987837557796],"rgb":[0.133333333333333331,1,0.933333333333333348],"xyz":[0.518490803582163817,0.780294010683421302,0.932201965199668248],"hpluv":[180.720785562676866,347.681124246536797,90.793318095908873],"hsluv":[180.720785562676866,99.9999999999901661,90.793318095908873]},"#22ffff":{"lch":[91.2687776254429082,70.7867026205843786,192.177050630061217],"luv":[91.2687776254429082,-69.1940343982234225,-14.9312715999851058],"rgb":[0.133333333333333331,1,1],"xyz":[0.544661851991995127,0.790762430047354,1.0700361534914502],"hpluv":[192.177050630061217,369.384676987995,91.2687776254429082],"hsluv":[192.177050630061217,99.9999999999901803,91.2687776254429082]},"#11aa00":{"lch":[60.6644104521350869,93.0873160838275,127.211890667698796],"luv":[60.6644104521350869,-56.2958954857129186,74.1351506854346241],"rgb":[0.0666666666666666657,0.66666666666666663,0],"xyz":[0.146052570780394131,0.288673842599075969,0.0480220097587461675],"hpluv":[127.211890667698796,194.713406103753528,60.6644104521350869],"hsluv":[127.211890667698796,100.000000000002444,60.6644104521350869]},"#11aa11":{"lch":[60.7002167335786424,91.7670835597914447,127.715012949240375],"luv":[60.7002167335786424,-56.1370762813229547,72.5935692169401],"rgb":[0.0666666666666666657,0.66666666666666663,0.0666666666666666657],"xyz":[0.147064236280031263,0.289078508798930822,0.0533501147235018],"hpluv":[127.715012949240375,191.838607973199288,60.7002167335786424],"hsluv":[127.715012949240375,97.6800439707354826,60.7002167335786424]},"#11aa22":{"lch":[60.7665037483511696,89.3702510768545153,128.6744569519864],"luv":[60.7665037483511696,-55.8469935821418844,69.7721655488506229],"rgb":[0.0666666666666666657,0.66666666666666663,0.133333333333333331],"xyz":[0.148939594418508264,0.289828652054321623,0.063227000919481],"hpluv":[128.6744569519864,186.624241227076766,60.7665037483511696],"hsluv":[128.6744569519864,97.7012125574833163,60.7665037483511696]},"#11aa33":{"lch":[60.8753956347493101,85.5662665428975799,130.333267948257316],"luv":[60.8753956347493101,-55.3812688292774595,65.2265362636212274],"rgb":[0.0666666666666666657,0.66666666666666663,0.2],"xyz":[0.152027345150966,0.291063752347304749,0.0794891547770921469],"hpluv":[130.333267948257316,178.361088002118152,60.8753956347493101],"hsluv":[130.333267948257316,97.7352371443594876,60.8753956347493101]},"#11aa44":{"lch":[61.0320681383245898,80.3855440613202603,132.913331110856149],"luv":[61.0320681383245898,-54.7338170014505394,58.8731260464924233],"rgb":[0.0666666666666666657,0.66666666666666663,0.266666666666666663],"xyz":[0.156485340395184885,0.292846950444992316,0.102967929729978785],"hpluv":[132.913331110856149,167.131840298358668,61.0320681383245898],"hsluv":[132.913331110856149,97.7826211010278428,61.0320681383245898]},"#11aa55":{"lch":[61.2406211479126199,74.0326893716562466,136.73626291081149],"luv":[61.2406211479126199,-53.9110982897111626,50.7388665304739064],"rgb":[0.0666666666666666657,0.66666666666666663,0.333333333333333315],"xyz":[0.162447754434546898,0.295231916060737176,0.134369977003952701],"hpluv":[136.73626291081149,153.399260409180499,61.2406211479126199],"hsluv":[136.73626291081149,97.8429805383323412,61.2406211479126199]},"#11aa66":{"lch":[61.5043118059827236,66.9183608277608926,142.276062400218507],"luv":[61.5043118059827236,-52.9302802927860938,40.944504442006675],"rgb":[0.0666666666666666657,0.66666666666666663,0.4],"xyz":[0.170032750208055056,0.298265914370140495,0.174317621411096635],"hpluv":[142.276062400218507,138.063556785316223,61.5043118059827236],"hsluv":[142.276062400218507,97.9151756761398246,61.5043118059827236]},"#11aa77":{"lch":[61.8256765996828648,59.7171413308715628,150.193024237310198],"luv":[61.8256765996828648,-51.8168585560505335,29.6841731923518672],"rgb":[0.0666666666666666657,0.66666666666666663,0.466666666666666674],"xyz":[0.179346763228257,0.30199151957822129,0.223371423317494544],"hpluv":[150.193024237310198,122.565843528602272,61.8256765996828648],"hsluv":[150.193024237310198,97.9974781059027578,61.8256765996828648]},"#11aa88":{"lch":[62.2066058842594,53.445591933814967,161.225226782668472],"luv":[62.2066058842594,-50.6018085779820197,17.201403018159084],"rgb":[0.0666666666666666657,0.66666666666666663,0.533333333333333326],"xyz":[0.190487180330200789,0.306447686418998888,0.282044286721066739],"hpluv":[161.225226782668472,109.022142353571084,62.2066058842594],"hsluv":[161.225226782668472,98.0877698343988698,62.2066058842594]},"#11aa99":{"lch":[62.6483970296267643,49.4620441969123803,175.635441576327452],"luv":[62.6483970296267643,-49.3186051456987613,3.76417356400704],"rgb":[0.0666666666666666657,0.66666666666666663,0.6],"xyz":[0.203544144439273517,0.311670472062628046,0.350810964362184619],"hpluv":[175.635441576327452,100.184705161952,62.6483970296267643],"hsluv":[175.635441576327452,98.1837511724305756,62.6483970296267643]},"#11aaaa":{"lch":[63.1517986220979424,49.10533458105958,192.177050630061103],"luv":[63.1517986220979424,-48.0004871585874326,-10.3579494522848794],"rgb":[0.0666666666666666657,0.66666666666666663,0.66666666666666663],"xyz":[0.218601837404526045,0.317693549248729168,0.430114813979183219],"hpluv":[192.177050630061103,98.6693521766944741,63.1517986220979424],"hsluv":[192.177050630061103,98.283131385506934,63.1517986220979424]},"#11aabb":{"lch":[63.7170519890822931,52.9100997091116483,208.088870357104184],"luv":[63.7170519890822931,-46.6782604891356812,-24.9122188681885817],"rgb":[0.0666666666666666657,0.66666666666666663,0.733333333333333282],"xyz":[0.235739429511862719,0.324548586091663926,0.520372799077825],"hpluv":[208.088870357104184,105.371274370578277,63.7170519890822931],"hsluv":[208.088870357104184,98.3837818799450474,63.7170519890822931]},"#11aacc":{"lch":[64.3439331362496603,60.2774830024396,221.163749704229559],"luv":[64.3439331362496603,-45.3787880982832661,-39.6754401089704345],"rgb":[0.0666666666666666657,0.66666666666666663,0.8],"xyz":[0.255031804955584418,0.332265536269152728,0.621979309748095122],"hpluv":[221.163749704229559,118.873987633214512,64.3439331362496603],"hsluv":[221.163749704229559,98.4838416101877385,64.3439331362496603]},"#11aadd":{"lch":[65.0317963778061738,70.0923801470555,230.985682804055784],"luv":[65.0317963778061738,-44.1241742926816372,-54.4609860144708762],"rgb":[0.0666666666666666657,0.66666666666666663,0.866666666666666696],"xyz":[0.276550130506218,0.340872866489406234,0.735309157648101119],"hpluv":[230.985682804055784,136.767964522831733,65.0317963778061738],"hsluv":[230.985682804055784,98.5817742563244,65.0317963778061738]},"#11aaee":{"lch":[65.7796198544585877,81.3683973110580325,238.155251398024461],"luv":[65.7796198544585877,-42.9315457639956293,-69.1208974137644248],"rgb":[0.0666666666666666657,0.66666666666666663,0.933333333333333348],"xyz":[0.300362310772392727,0.350397738595876251,0.860719973716624343],"hpluv":[238.155251398024461,156.965326989669,65.7796198544585877],"hsluv":[238.155251398024461,98.676383948407647,65.7796198544585877]},"#11aaff":{"lch":[66.5860524818013317,93.423779787985481,243.412392023658668],"luv":[66.5860524818013317,-41.8132782993845566,-83.5443139162218529],"rgb":[0.0666666666666666657,0.66666666666666663,1],"xyz":[0.326533359182224148,0.360866157959809,0.998554162008406188],"hpluv":[243.412392023658668,178.038321821181739,66.5860524818013317],"hsluv":[243.412392023658668,99.9999999999982805,66.5860524818013317]},"#11bb00":{"lch":[66.2579979425279788,101.837028338191359,127.308350947248712],"luv":[66.2579979425279788,-61.7238643700190792,80.9996599251199285],"rgb":[0.0666666666666666657,0.733333333333333282,0],"xyz":[0.180007068688992911,0.356582838416274528,0.0593401757282787864],"hpluv":[127.308350947248712,195.032386644097869,66.2579979425279788],"hsluv":[127.308350947248712,100.000000000002416,66.2579979425279788]},"#11bb11":{"lch":[66.2891028676776,100.667761827005108,127.715012949240403],"luv":[66.2891028676776,-61.5819268253258301,79.6345688739434507],"rgb":[0.0666666666666666657,0.733333333333333282,0.0666666666666666657],"xyz":[0.181018734188630043,0.356987504616129381,0.0646682806930344162],"hpluv":[127.715012949240403,192.702610495025482,66.2891028676776],"hsluv":[127.715012949240403,98.1199752505464318,66.2891028676776]},"#11bb22":{"lch":[66.3467009890152895,98.5365229927559199,128.48627008521666],"luv":[66.3467009890152895,-61.3219466901703356,77.130183570569983],"rgb":[0.0666666666666666657,0.733333333333333282,0.133333333333333331],"xyz":[0.182894092327107044,0.357737647871520181,0.0745451668890136088],"hpluv":[128.48627008521666,188.459149582366734,66.3467009890152895],"hsluv":[128.48627008521666,98.1339007760711155,66.3467009890152895]},"#11bb33":{"lch":[66.4413603116689586,95.1297105779412107,129.807139434656818],"luv":[66.4413603116689586,-60.9025570517959949,73.0790009455219121],"rgb":[0.0666666666666666657,0.733333333333333282,0.2],"xyz":[0.185981843059564778,0.358972748164503308,0.0908073207466247589],"hpluv":[129.807139434656818,181.684126992490178,66.4413603116689586],"hsluv":[129.807139434656818,98.1563849168539093,66.4413603116689586]},"#11bb44":{"lch":[66.5776441235544,90.4345556189602888,131.832147550242752],"luv":[66.5776441235544,-60.3153845158839061,67.3829595721343679],"rgb":[0.0666666666666666657,0.733333333333333282,0.266666666666666663],"xyz":[0.190439838303783665,0.360755946262190874,0.114286095699511397],"hpluv":[131.832147550242752,172.363503065423913,66.5776441235544],"hsluv":[131.832147550242752,98.1879073212924567,66.5776441235544]},"#11bb55":{"lch":[66.7592187944261,84.5672269635890501,134.774448398028227],"luv":[66.7592187944261,-59.5621947933412841,60.0329978237906374],"rgb":[0.0666666666666666657,0.733333333333333282,0.333333333333333315],"xyz":[0.196402252343145678,0.363140911877935735,0.145688142973485313],"hpluv":[134.774448398028227,160.742297130584,66.7592187944261],"hsluv":[134.774448398028227,98.2284201297941451,66.7592187944261]},"#11bb66":{"lch":[66.9890609579081513,77.7896938122995749,138.938350400658521],"luv":[66.9890609579081513,-58.6536805127572336,51.0977712402284752],"rgb":[0.0666666666666666657,0.733333333333333282,0.4],"xyz":[0.203987248116653835,0.366174910187339053,0.185635787380629275],"hpluv":[138.938350400658521,147.352496635070423,66.9890609579081513],"hsluv":[138.938350400658521,98.2774122804504486,66.9890609579081513]},"#11bb77":{"lch":[67.2695660469751573,70.5410036497719375,144.751753478195667],"luv":[67.2695660469751573,-57.6079608572489548,40.7106379437464625],"rgb":[0.0666666666666666657,0.733333333333333282,0.466666666666666674],"xyz":[0.213301261136855769,0.369900515395419849,0.234689589287027184],"hpluv":[144.751753478195667,133.064539371584743,67.2695660469751573],"hsluv":[144.751753478195667,98.33398740837616,67.2695660469751573]},"#11bb88":{"lch":[67.6026131767386289,63.4868829762913904,152.765342955174589],"luv":[67.6026131767386289,-56.44870944299889,29.0538725863731493],"rgb":[0.0666666666666666657,0.733333333333333282,0.533333333333333326],"xyz":[0.224441678238799569,0.374356682236197447,0.293362452690599351],"hpluv":[152.765342955174589,119.168054047142519,67.6026131767386289],"hsluv":[152.765342955174589,98.3969602233376293,67.6026131767386289]},"#11bb99":{"lch":[67.9896091217093357,57.5709210660889568,163.510238814203348],"luv":[67.9896091217093357,-55.2030563361408468,16.3411604100414145],"rgb":[0.0666666666666666657,0.733333333333333282,0.6],"xyz":[0.237498642347872296,0.379579467879826604,0.362129130331717231],"hpluv":[163.510238814203348,107.448401728013394,67.9896091217093357],"hsluv":[163.510238814203348,98.464964167861,67.9896091217093357]},"#11bbaa":{"lch":[68.431522322705149,53.97217733059707,177.026074660918823],"luv":[68.431522322705149,-53.8994902384006807,2.80015675382041573],"rgb":[0.0666666666666666657,0.733333333333333282,0.66666666666666663],"xyz":[0.252556335313124825,0.385602545065927726,0.441432979948715831],"hpluv":[177.026074660918823,100.081328983600983,68.431522322705149],"hsluv":[177.026074660918823,98.5365589333087684,68.431522322705149]},"#11bbbb":{"lch":[68.9289126417652511,53.7759127589290102,192.177050630061103],"luv":[68.9289126417652511,-52.5659794775517426,-11.3431298424003177],"rgb":[0.0666666666666666657,0.733333333333333282,0.733333333333333282],"xyz":[0.269693927420461499,0.392457581908862485,0.531690965047357578],"hpluv":[192.177050630061103,98.9978332941913095,68.9289126417652511],"hsluv":[192.177050630061103,98.6103267315429122,68.9289126417652511]},"#11bbcc":{"lch":[69.4819599404948463,57.3930965266865485,206.799543430538137],"luv":[69.4819599404948463,-51.2284702417124365,-25.8768499940688805],"rgb":[0.0666666666666666657,0.733333333333333282,0.8],"xyz":[0.288986302864183253,0.400174532086351287,0.633297475717627734],"hpluv":[206.799543430538137,104.81584090136549,69.4819599404948463],"hsluv":[206.799543430538137,98.6849492658553658,69.4819599404948463]},"#11bbdd":{"lch":[70.0904930703520535,64.3454332007566876,219.135570681285316],"luv":[70.0904930703520535,-49.9098388382008054,-40.6121011637893901],"rgb":[0.0666666666666666657,0.733333333333333282,0.866666666666666696],"xyz":[0.310504628414816741,0.408781862306604793,0.746627323617633731],"hpluv":[219.135570681285316,116.492493254234162,70.0904930703520535],"hsluv":[219.135570681285316,98.7592614999562244,70.0904930703520535]},"#11bbee":{"lch":[70.7540199625255184,73.7064384587933858,228.717665412779098],"luv":[70.7540199625255184,-48.6292974270947838,-55.3879996211006826],"rgb":[0.0666666666666666657,0.733333333333333282,0.933333333333333348],"xyz":[0.334316808680991506,0.41830673441307481,0.872038139686157],"hpluv":[228.717665412779098,132.188487390259695,70.7540199625255184],"hsluv":[228.717665412779098,98.8322822642660412,70.7540199625255184]},"#11bbff":{"lch":[71.471758937406932,84.600620314641418,235.923069973878228],"luv":[71.471758937406932,-47.4021956671632836,-70.0735099988154246],"rgb":[0.0666666666666666657,0.733333333333333282,1],"xyz":[0.360487857090822872,0.428775153777007534,1.00987232797793891],"hpluv":[235.923069973878228,150.202929688167188,71.471758937406932],"hsluv":[235.923069973878228,99.9999999999978115,71.471758937406932]},"#11cc00":{"lch":[71.760164015117,110.429324102022079,127.380540485202317],"luv":[71.760164015117,-67.042304751477019,87.7494444155603617],"rgb":[0.0666666666666666657,0.8,0],"xyz":[0.21823081199860983,0.433030325035509422,0.0720814234981507346],"hpluv":[127.380540485202317,195.272154443078705,71.760164015117],"hsluv":[127.380540485202317,100.000000000002245,71.760164015117]},"#11cc11":{"lch":[71.7874927519263366,109.385174124956521,127.715012949240432],"luv":[71.7874927519263366,-66.9146672826053219,86.5305935539869466],"rgb":[0.0666666666666666657,0.8,0.0666666666666666657],"xyz":[0.219242477498246963,0.433434991235364275,0.0774095284629063712],"hpluv":[127.715012949240432,193.352149077988855,71.7874927519263366],"hsluv":[127.715012949240432,98.4507061603193563,71.7874927519263366]},"#11cc22":{"lch":[71.8381079866900905,107.476295008714118,128.346772012349533],"luv":[71.8381079866900905,-66.680384726115463,84.2904519004221129],"rgb":[0.0666666666666666657,0.8,0.133333333333333331],"xyz":[0.221117835636723964,0.434185134490755076,0.0872864146588855638],"hpluv":[128.346772012349533,189.84411001864018,71.8381079866900905],"hsluv":[128.346772012349533,98.4601754700601361,71.8381079866900905]},"#11cc33":{"lch":[71.9213183931711626,104.40864440796355,129.421122123890029],"luv":[71.9213183931711626,-66.3010906987881441,80.6556284412913556],"rgb":[0.0666666666666666657,0.8,0.2],"xyz":[0.224205586369181697,0.435420234783738203,0.103548568516496714],"hpluv":[129.421122123890029,184.212095875088124,71.9213183931711626],"hsluv":[129.421122123890029,98.4755168761512749,71.9213183931711626]},"#11cc44":{"lch":[72.0411777660314669,100.144250866202455,131.050559631523186],"luv":[72.0411777660314669,-65.7672084530810395,75.5218198525557085],"rgb":[0.0666666666666666657,0.8,0.266666666666666663],"xyz":[0.228663581613400585,0.437203432881425769,0.127027343469383353],"hpluv":[131.050559631523186,176.394298837834185,72.0411777660314669],"hsluv":[131.050559631523186,98.4971346697200261,72.0411777660314669]},"#11cc55":{"lch":[72.2009771566369523,94.7439152050601621,133.383427271112737],"luv":[72.2009771566369523,-65.077446685205,68.8573554627095],"rgb":[0.0666666666666666657,0.8,0.333333333333333315],"xyz":[0.234625995652762598,0.439588398497170629,0.158429390743357268],"hpluv":[133.383427271112737,166.512782767528847,72.2009771566369523],"hsluv":[133.383427271112737,98.5251071985599225,72.2009771566369523]},"#11cc66":{"lch":[72.4034304155724,88.37638367841096,136.624435218533876],"luv":[72.4034304155724,-64.2379326004453333,60.6949191225620339],"rgb":[0.0666666666666666657,0.8,0.4],"xyz":[0.242210991426270755,0.442622396806573948,0.198377035150501202],"hpluv":[136.624435218533876,154.887514188688357,72.4034304155724],"hsluv":[136.624435218533876,98.5592219307307289,72.4034304155724]},"#11cc77":{"lch":[72.6507717937069657,81.3359578844494422,141.057484765247835],"luv":[72.6507717937069657,-63.261234579889333,51.1229326663597],"rgb":[0.0666666666666666657,0.8,0.466666666666666674],"xyz":[0.251525004446472689,0.446348002014654743,0.247430837056899111],"hpluv":[141.057484765247835,142.063228414279422,72.6507717937069657],"hsluv":[141.057484765247835,98.5990140248714795,72.6507717937069657]},"#11cc88":{"lch":[72.9448138267759703,74.0714793913140284,147.061910762632237],"luv":[72.9448138267759703,-62.1651250648783815,40.2750702654370087],"rgb":[0.0666666666666666657,0.8,0.533333333333333326],"xyz":[0.262665421548416489,0.450804168855432341,0.306103700460471306],"hpluv":[147.061910762632237,128.853412583983044,72.9448138267759703],"hsluv":[147.061910762632237,98.6438145792393755,72.9448138267759703]},"#11cc99":{"lch":[73.286985449663689,67.2264361640895203,155.087429558943455],"luv":[73.286985449663689,-60.9711251229010074,28.3181147072320734],"rgb":[0.0666666666666666657,0.8,0.6],"xyz":[0.275722385657489188,0.456026954499061499,0.374870378101589186],"hpluv":[155.087429558943455,116.399886643338576,73.286985449663689],"hsluv":[155.087429558943455,98.6928071276572609,73.286985449663689]},"#11ccaa":{"lch":[73.6783599756885224,61.6669147974486336,165.501022011161467],"luv":[73.6783599756885224,-59.7029534543248275,15.4390974304365383],"rgb":[0.0666666666666666657,0.8,0.66666666666666663],"xyz":[0.290780078622741744,0.462050031685162621,0.454174227718587786],"hpluv":[165.501022011161467,106.206622375239988,73.6783599756885224],"hsluv":[165.501022011161467,98.7450877264532494,73.6783599756885224]},"#11ccbb":{"lch":[74.1196780643846864,58.4137876130139801,178.201908682105085],"luv":[74.1196780643846864,-58.3850250256368426,1.83287644266177074],"rgb":[0.0666666666666666657,0.8,0.733333333333333282],"xyz":[0.307917670730078419,0.46890506852809738,0.544432212817229533],"hpluv":[178.201908682105085,100.004874571957387,74.1196780643846864],"hsluv":[178.201908682105085,98.7997230732590452,74.1196780643846864]},"#11cccc":{"lch":[74.6113685470067,58.3540675645504,192.177050630061103],"luv":[74.6113685470067,-57.0411279075965751,-12.3088150671508707],"rgb":[0.0666666666666666657,0.8,0.8],"xyz":[0.327210046173800118,0.476622018705586181,0.646038723487499689],"hpluv":[192.177050630061103,99.244272920381249,74.6113685470067],"hsluv":[192.177050630061103,98.8558017207376167,74.6113685470067]},"#11ccdd":{"lch":[75.1535687293590087,61.8087365466066316,205.702276410621693],"luv":[75.1535687293590087,-55.6933672323303881,-26.8061328768737823],"rgb":[0.0666666666666666657,0.8,0.866666666666666696],"xyz":[0.348728371724433717,0.485229348925839687,0.759368571387505686],"hpluv":[205.702276410621693,104.361325002032586,75.1535687293590087],"hsluv":[205.702276410621693,98.9124749687685352,75.1535687293590087]},"#11ccee":{"lch":[75.7461450403856418,68.3900229325434168,217.356690237772426],"luv":[75.7461450403856418,-54.3614174191380712,-41.4973677827407],"rgb":[0.0666666666666666657,0.8,0.933333333333333348],"xyz":[0.372540551990608426,0.494754221032309704,0.88477938745602891],"hpluv":[217.356690237772426,114.570165581500433,75.7461450403856418],"hsluv":[217.356690237772426,98.968985855810871,75.7461450403856418]},"#11ccff":{"lch":[76.3887144168947714,77.3228649101567811,226.666757851513921],"luv":[76.3887144168947714,-53.0620799518220849,-56.2426982736496726],"rgb":[0.0666666666666666657,0.8,1],"xyz":[0.398711600400439847,0.505222640396242428,1.02261357574781075],"hpluv":[226.666757851513921,131.304642630845649,76.3887144168947714],"hsluv":[226.666757851513921,99.9999999999969162,76.3887144168947714]},"#11dd00":{"lch":[77.1789729208637851,118.880191052714352,127.435820588671049],"luv":[77.1789729208637851,-72.2639845338074,94.3950017957916572],"rgb":[0.0666666666666666657,0.866666666666666696,0],"xyz":[0.260864802545785,0.518298306129860942,0.0862927536805420531],"hpluv":[127.435820588671049,210.367240137055802,77.1789729208637851],"hsluv":[127.435820588671049,100.000000000002302,77.1789729208637851]},"#11dd11":{"lch":[77.2032167276219,117.940964566200989,127.715012949240474],"luv":[77.2032167276219,-72.148538100067,93.2987651195291],"rgb":[0.0666666666666666657,0.866666666666666696,0.0666666666666666657],"xyz":[0.261876468045422084,0.51870297232971585,0.0916208586452976897],"hpluv":[127.715012949240474,208.973000844217893,77.2032167276219],"hsluv":[127.715012949240474,98.7048375113237739,77.2032167276219]},"#11dd22":{"lch":[77.2481249515021773,116.219968574506154,128.240715222563949],"luv":[77.2481249515021773,-71.936288170647174,91.2811674974022509],"rgb":[0.0666666666666666657,0.866666666666666696,0.133333333333333331],"xyz":[0.263751826183899141,0.519453115585106651,0.101497744841276882],"hpluv":[128.240715222563949,206.413967447437244,77.2481249515021773],"hsluv":[128.240715222563949,98.7114617332334348,77.2481249515021773]},"#11dd33":{"lch":[77.3219716074714114,113.443027450646795,129.129905575085218],"luv":[77.3219716074714114,-71.591714193384675,87.9996984996024],"rgb":[0.0666666666666666657,0.866666666666666696,0.2],"xyz":[0.266839576916356847,0.520688215878089777,0.117759898698888033],"hpluv":[129.129905575085218,202.273081507843187,77.3219716074714114],"hsluv":[129.129905575085218,98.7222220245650419,77.3219716074714114]},"#11dd44":{"lch":[77.4283833065767,109.557638087167803,130.467479357182611],"luv":[77.4283833065767,-71.1046976382296378,83.3486534805139],"rgb":[0.0666666666666666657,0.866666666666666696,0.266666666666666663],"xyz":[0.271297572160575762,0.522471413975777343,0.141238673651774671],"hpluv":[130.467479357182611,196.45511110559741,77.4283833065767],"hsluv":[130.467479357182611,98.737444128486942,77.4283833065767]},"#11dd55":{"lch":[77.5703274630482156,104.589066335953675,132.360930841179908],"luv":[77.5703274630482156,-70.4719757705036471,77.2824263854860192],"rgb":[0.0666666666666666657,0.866666666666666696,0.333333333333333315],"xyz":[0.277259986199937747,0.524856379591522093,0.172640720925748559],"hpluv":[132.360930841179908,188.974657198429043,77.5703274630482156],"hsluv":[132.360930841179908,98.7572451358875583,77.5703274630482156]},"#11dd66":{"lch":[77.7502795105496176,98.645271303892585,134.953797592355841],"luv":[77.7502795105496176,-69.6964700953403167,69.8089650895062732],"rgb":[0.0666666666666666657,0.866666666666666696,0.4],"xyz":[0.284844981973445932,0.527890377900925412,0.212588365332892548],"hpluv":[134.953797592355841,179.968822287066047,77.7502795105496176],"hsluv":[134.953797592355841,98.7815546318288114,77.7502795105496176]},"#11dd77":{"lch":[77.9703113413929714,91.9272626112809377,138.440937564009943],"luv":[77.9703113413929714,-68.7866216277350588,60.9837871589344616],"rgb":[0.0666666666666666657,0.866666666666666696,0.466666666666666674],"xyz":[0.294158994993647838,0.531615983109006263,0.261642167239290457],"hpluv":[138.440937564009943,169.723893920939275,77.9703113413929714],"hsluv":[138.440937564009943,98.8101351189296,77.9703113413929714]},"#11dd88":{"lch":[78.2321436880382919,84.7462074021241705,143.083472555296623],"luv":[78.2321436880382919,-67.7555613828794492,50.90288371727776],"rgb":[0.0666666666666666657,0.866666666666666696,0.533333333333333326],"xyz":[0.305299412095591638,0.536072149949783805,0.320315030642862597],"hpluv":[143.083472555296623,158.721324423216174,78.2321436880382919],"hsluv":[143.083472555296623,98.842607114853692,78.2321436880382919]},"#11dd99":{"lch":[78.5371801027425,77.5491781494168748,149.212222309724666],"luv":[78.5371801027425,-66.6201031545698,39.6942928810235145],"rgb":[0.0666666666666666657,0.866666666666666696,0.6],"xyz":[0.318356376204664393,0.541294935593413,0.389081708283980532],"hpluv":[149.212222309724666,147.710574340426348,78.5371801027425],"hsluv":[149.212222309724666,98.8784794246756746,78.5371801027425]},"#11ddaa":{"lch":[78.8865310768390771,70.9495750262721288,157.187121587348372],"luv":[78.8865310768390771,-65.3996173248364414,27.5087667875819264],"rgb":[0.0666666666666666657,0.866666666666666696,0.66666666666666663],"xyz":[0.333414069169916893,0.547318012779514085,0.468385557900979133],"hpluv":[157.187121587348372,137.807232739715857,78.8865310768390771],"hsluv":[157.187121587348372,98.9171828916172728,78.8865310768390771]},"#11ddbb":{"lch":[79.2810328759594398,65.7363215025974483,167.247861929956969],"luv":[79.2810328759594398,-64.1148749316804611,14.5102300873497096],"rgb":[0.0666666666666666657,0.866666666666666696,0.733333333333333282],"xyz":[0.350551661277253568,0.554173049622448843,0.558643542999620824],"hpluv":[167.247861929956969,130.572542181043048,79.2810328759594398],"hsluv":[167.247861929956969,98.9581049946704496,79.2810328759594398]},"#11ddcc":{"lch":[79.7212637056701396,62.7929370759791,179.209087927276954],"luv":[79.7212637056701396,-62.7869545437069903,0.866767416521026846],"rgb":[0.0666666666666666657,0.866666666666666696,0.8],"xyz":[0.369844036720975322,0.561889999799937701,0.660250053669891],"hpluv":[179.209087927276954,127.935201467087722,79.7212637056701396],"hsluv":[179.209087927276954,99.0006225499112,79.7212637056701396]},"#11dddd":{"lch":[80.2075587483664378,62.8503941808937796,192.177050630061132],"luv":[80.2075587483664378,-61.4362892449526,-13.2572400032679489],"rgb":[0.0666666666666666657,0.866666666666666696,0.866666666666666696],"xyz":[0.39136236227160881,0.570497330020191207,0.773579901569897],"hpluv":[192.177050630061132,131.767009082741112,80.2075587483664378],"hsluv":[192.177050630061132,99.0441302201931109,80.2075587483664378]},"#11ddee":{"lch":[80.7400249746916643,66.1629514334268691,204.757295278220823],"luv":[80.7400249746916643,-60.0819052998990202,-27.707414132610225],"rgb":[0.0666666666666666657,0.866666666666666696,0.933333333333333348],"xyz":[0.415174542537783575,0.580022202126661224,0.8989907176384202],"hpluv":[204.757295278220823,143.22067561241397,80.7400249746916643],"hsluv":[204.757295278220823,99.0880633014724594,80.7400249746916643]},"#11ddff":{"lch":[81.3185562290371848,72.4120095186264194,215.786316478612605],"luv":[81.3185562290371848,-58.7408753400219084,-42.3439332940817934],"rgb":[0.0666666666666666657,0.866666666666666696,1],"xyz":[0.441345590947614941,0.590490621490594,1.03682490593020216],"hpluv":[215.786316478612605,162.428807277722512,81.3185562290371848],"hsluv":[215.786316478612605,99.9999999999959925,81.3185562290371848]}} \ No newline at end of file diff --git a/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go b/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go new file mode 100644 index 00000000..d19fb644 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/hsluv.go @@ -0,0 +1,207 @@ +package colorful + +import "math" + +// Source: https://github.com/hsluv/hsluv-go +// Under MIT License +// Modified so that Saturation and Luminance are in [0..1] instead of [0..100]. + +// HSLuv uses a rounded version of the D65. This has no impact on the final RGB +// values, but to keep high levels of accuracy for internal operations and when +// comparing to the test values, this modified white reference is used internally. +// +// See this GitHub thread for details on these values: +// https://github.com/hsluv/hsluv/issues/79 +var hSLuvD65 = [3]float64{0.95045592705167, 1.0, 1.089057750759878} + +func LuvLChToHSLuv(l, c, h float64) (float64, float64, float64) { + // [-1..1] but the code expects it to be [-100..100] + c *= 100.0 + l *= 100.0 + + var s, max float64 + if l > 99.9999999 || l < 0.00000001 { + s = 0.0 + } else { + max = maxChromaForLH(l, h) + s = c / max * 100.0 + } + return h, clamp01(s / 100.0), clamp01(l / 100.0) +} + +func HSLuvToLuvLCh(h, s, l float64) (float64, float64, float64) { + l *= 100.0 + s *= 100.0 + + var c, max float64 + if l > 99.9999999 || l < 0.00000001 { + c = 0.0 + } else { + max = maxChromaForLH(l, h) + c = max / 100.0 * s + } + + // c is [-100..100], but for LCh it's supposed to be almost [-1..1] + return clamp01(l / 100.0), c / 100.0, h +} + +func LuvLChToHPLuv(l, c, h float64) (float64, float64, float64) { + // [-1..1] but the code expects it to be [-100..100] + c *= 100.0 + l *= 100.0 + + var s, max float64 + if l > 99.9999999 || l < 0.00000001 { + s = 0.0 + } else { + max = maxSafeChromaForL(l) + s = c / max * 100.0 + } + return h, s / 100.0, l / 100.0 +} + +func HPLuvToLuvLCh(h, s, l float64) (float64, float64, float64) { + // [-1..1] but the code expects it to be [-100..100] + l *= 100.0 + s *= 100.0 + + var c, max float64 + if l > 99.9999999 || l < 0.00000001 { + c = 0.0 + } else { + max = maxSafeChromaForL(l) + c = max / 100.0 * s + } + return l / 100.0, c / 100.0, h +} + +// HSLuv creates a new Color from values in the HSLuv color space. +// Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1]. +// +// The returned color values are clamped (using .Clamped), so this will never output +// an invalid color. +func HSLuv(h, s, l float64) Color { + // HSLuv -> LuvLCh -> CIELUV -> CIEXYZ -> Linear RGB -> sRGB + l, u, v := LuvLChToLuv(HSLuvToLuvLCh(h, s, l)) + return LinearRgb(XyzToLinearRgb(LuvToXyzWhiteRef(l, u, v, hSLuvD65))).Clamped() +} + +// HPLuv creates a new Color from values in the HPLuv color space. +// Hue in [0..360], a Saturation [0..1], and a Luminance (lightness) in [0..1]. +// +// The returned color values are clamped (using .Clamped), so this will never output +// an invalid color. +func HPLuv(h, s, l float64) Color { + // HPLuv -> LuvLCh -> CIELUV -> CIEXYZ -> Linear RGB -> sRGB + l, u, v := LuvLChToLuv(HPLuvToLuvLCh(h, s, l)) + return LinearRgb(XyzToLinearRgb(LuvToXyzWhiteRef(l, u, v, hSLuvD65))).Clamped() +} + +// HSLuv returns the Hue, Saturation and Luminance of the color in the HSLuv +// color space. Hue in [0..360], a Saturation [0..1], and a Luminance +// (lightness) in [0..1]. +func (col Color) HSLuv() (h, s, l float64) { + // sRGB -> Linear RGB -> CIEXYZ -> CIELUV -> LuvLCh -> HSLuv + return LuvLChToHSLuv(col.LuvLChWhiteRef(hSLuvD65)) +} + +// HPLuv returns the Hue, Saturation and Luminance of the color in the HSLuv +// color space. Hue in [0..360], a Saturation [0..1], and a Luminance +// (lightness) in [0..1]. +// +// Note that HPLuv can only represent pastel colors, and so the Saturation +// value could be much larger than 1 for colors it can't represent. +func (col Color) HPLuv() (h, s, l float64) { + return LuvLChToHPLuv(col.LuvLChWhiteRef(hSLuvD65)) +} + +// DistanceHSLuv calculates Euclidan distance in the HSLuv colorspace. No idea +// how useful this is. +// +// The Hue value is divided by 100 before the calculation, so that H, S, and L +// have the same relative ranges. +func (c1 Color) DistanceHSLuv(c2 Color) float64 { + h1, s1, l1 := c1.HSLuv() + h2, s2, l2 := c2.HSLuv() + return math.Sqrt(sq((h1-h2)/100.0) + sq(s1-s2) + sq(l1-l2)) +} + +// DistanceHPLuv calculates Euclidean distance in the HPLuv colorspace. No idea +// how useful this is. +// +// The Hue value is divided by 100 before the calculation, so that H, S, and L +// have the same relative ranges. +func (c1 Color) DistanceHPLuv(c2 Color) float64 { + h1, s1, l1 := c1.HPLuv() + h2, s2, l2 := c2.HPLuv() + return math.Sqrt(sq((h1-h2)/100.0) + sq(s1-s2) + sq(l1-l2)) +} + +var m = [3][3]float64{ + {3.2409699419045214, -1.5373831775700935, -0.49861076029300328}, + {-0.96924363628087983, 1.8759675015077207, 0.041555057407175613}, + {0.055630079696993609, -0.20397695888897657, 1.0569715142428786}, +} + +const kappa = 903.2962962962963 +const epsilon = 0.0088564516790356308 + +func maxChromaForLH(l, h float64) float64 { + hRad := h / 360.0 * math.Pi * 2.0 + minLength := math.MaxFloat64 + for _, line := range getBounds(l) { + length := lengthOfRayUntilIntersect(hRad, line[0], line[1]) + if length > 0.0 && length < minLength { + minLength = length + } + } + return minLength +} + +func getBounds(l float64) [6][2]float64 { + var sub2 float64 + var ret [6][2]float64 + sub1 := math.Pow(l+16.0, 3.0) / 1560896.0 + if sub1 > epsilon { + sub2 = sub1 + } else { + sub2 = l / kappa + } + for i := range m { + for k := 0; k < 2; k++ { + top1 := (284517.0*m[i][0] - 94839.0*m[i][2]) * sub2 + top2 := (838422.0*m[i][2]+769860.0*m[i][1]+731718.0*m[i][0])*l*sub2 - 769860.0*float64(k)*l + bottom := (632260.0*m[i][2]-126452.0*m[i][1])*sub2 + 126452.0*float64(k) + ret[i*2+k][0] = top1 / bottom + ret[i*2+k][1] = top2 / bottom + } + } + return ret +} + +func lengthOfRayUntilIntersect(theta, x, y float64) (length float64) { + length = y / (math.Sin(theta) - x*math.Cos(theta)) + return +} + +func maxSafeChromaForL(l float64) float64 { + minLength := math.MaxFloat64 + for _, line := range getBounds(l) { + m1 := line[0] + b1 := line[1] + x := intersectLineLine(m1, b1, -1.0/m1, 0.0) + dist := distanceFromPole(x, b1+x*m1) + if dist < minLength { + minLength = dist + } + } + return minLength +} + +func intersectLineLine(x1, y1, x2, y2 float64) float64 { + return (y1 - y2) / (x2 - x1) +} + +func distanceFromPole(x, y float64) float64 { + return math.Sqrt(math.Pow(x, 2.0) + math.Pow(y, 2.0)) +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go new file mode 100644 index 00000000..9f7bf6f7 --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/soft_palettegen.go @@ -0,0 +1,185 @@ +// Largely inspired by the descriptions in http://lab.medialab.sciences-po.fr/iwanthue/ +// but written from scratch. + +package colorful + +import ( + "fmt" + "math" + "math/rand" +) + +// The algorithm works in L*a*b* color space and converts to RGB in the end. +// L* in [0..1], a* and b* in [-1..1] +type lab_t struct { + L, A, B float64 +} + +type SoftPaletteSettings struct { + // A function which can be used to restrict the allowed color-space. + CheckColor func(l, a, b float64) bool + + // The higher, the better quality but the slower. Usually two figures. + Iterations int + + // Use up to 160000 or 8000 samples of the L*a*b* space (and thus calls to CheckColor). + // Set this to true only if your CheckColor shapes the Lab space weirdly. + ManySamples bool +} + +// Yeah, windows-stype Foo, FooEx, screw you golang... +// Uses K-means to cluster the color-space and return the means of the clusters +// as a new palette of distinctive colors. Falls back to K-medoid if the mean +// happens to fall outside of the color-space, which can only happen if you +// specify a CheckColor function. +func SoftPaletteEx(colorsCount int, settings SoftPaletteSettings) ([]Color, error) { + + // Checks whether it's a valid RGB and also fulfills the potentially provided constraint. + check := func(col lab_t) bool { + c := Lab(col.L, col.A, col.B) + return c.IsValid() && (settings.CheckColor == nil || settings.CheckColor(col.L, col.A, col.B)) + } + + // Sample the color space. These will be the points k-means is run on. + dl := 0.05 + dab := 0.1 + if settings.ManySamples { + dl = 0.01 + dab = 0.05 + } + + samples := make([]lab_t, 0, int(1.0/dl*2.0/dab*2.0/dab)) + for l := 0.0; l <= 1.0; l += dl { + for a := -1.0; a <= 1.0; a += dab { + for b := -1.0; b <= 1.0; b += dab { + if check(lab_t{l, a, b}) { + samples = append(samples, lab_t{l, a, b}) + } + } + } + } + + // That would cause some infinite loops down there... + if len(samples) < colorsCount { + return nil, fmt.Errorf("palettegen: more colors requested (%v) than samples available (%v). Your requested color count may be wrong, you might want to use many samples or your constraint function makes the valid color space too small", colorsCount, len(samples)) + } else if len(samples) == colorsCount { + return labs2cols(samples), nil // Oops? + } + + // We take the initial means out of the samples, so they are in fact medoids. + // This helps us avoid infinite loops or arbitrary cutoffs with too restrictive constraints. + means := make([]lab_t, colorsCount) + for i := 0; i < colorsCount; i++ { + for means[i] = samples[rand.Intn(len(samples))]; in(means, i, means[i]); means[i] = samples[rand.Intn(len(samples))] { + } + } + + clusters := make([]int, len(samples)) + samples_used := make([]bool, len(samples)) + + // The actual k-means/medoid iterations + for i := 0; i < settings.Iterations; i++ { + // Reassing the samples to clusters, i.e. to their closest mean. + // By the way, also check if any sample is used as a medoid and if so, mark that. + for isample, sample := range samples { + samples_used[isample] = false + mindist := math.Inf(+1) + for imean, mean := range means { + dist := lab_dist(sample, mean) + if dist < mindist { + mindist = dist + clusters[isample] = imean + } + + // Mark samples which are used as a medoid. + if lab_eq(sample, mean) { + samples_used[isample] = true + } + } + } + + // Compute new means according to the samples. + for imean := range means { + // The new mean is the average of all samples belonging to it.. + nsamples := 0 + newmean := lab_t{0.0, 0.0, 0.0} + for isample, sample := range samples { + if clusters[isample] == imean { + nsamples++ + newmean.L += sample.L + newmean.A += sample.A + newmean.B += sample.B + } + } + if nsamples > 0 { + newmean.L /= float64(nsamples) + newmean.A /= float64(nsamples) + newmean.B /= float64(nsamples) + } else { + // That mean doesn't have any samples? Get a new mean from the sample list! + var inewmean int + for inewmean = rand.Intn(len(samples_used)); samples_used[inewmean]; inewmean = rand.Intn(len(samples_used)) { + } + newmean = samples[inewmean] + samples_used[inewmean] = true + } + + // But now we still need to check whether the new mean is an allowed color. + if nsamples > 0 && check(newmean) { + // It does, life's good (TM) + means[imean] = newmean + } else { + // New mean isn't an allowed color or doesn't have any samples! + // Switch to medoid mode and pick the closest (unused) sample. + // This should always find something thanks to len(samples) >= colorsCount + mindist := math.Inf(+1) + for isample, sample := range samples { + if !samples_used[isample] { + dist := lab_dist(sample, newmean) + if dist < mindist { + mindist = dist + newmean = sample + } + } + } + } + } + } + return labs2cols(means), nil +} + +// A wrapper which uses common parameters. +func SoftPalette(colorsCount int) ([]Color, error) { + return SoftPaletteEx(colorsCount, SoftPaletteSettings{nil, 50, false}) +} + +func in(haystack []lab_t, upto int, needle lab_t) bool { + for i := 0; i < upto && i < len(haystack); i++ { + if haystack[i] == needle { + return true + } + } + return false +} + +const LAB_DELTA = 1e-6 + +func lab_eq(lab1, lab2 lab_t) bool { + return math.Abs(lab1.L-lab2.L) < LAB_DELTA && + math.Abs(lab1.A-lab2.A) < LAB_DELTA && + math.Abs(lab1.B-lab2.B) < LAB_DELTA +} + +// That's faster than using colorful's DistanceLab since we would have to +// convert back and forth for that. Here is no conversion. +func lab_dist(lab1, lab2 lab_t) float64 { + return math.Sqrt(sq(lab1.L-lab2.L) + sq(lab1.A-lab2.A) + sq(lab1.B-lab2.B)) +} + +func labs2cols(labs []lab_t) (cols []Color) { + cols = make([]Color, len(labs)) + for k, v := range labs { + cols[k] = Lab(v.L, v.A, v.B) + } + return cols +} diff --git a/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go b/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go new file mode 100644 index 00000000..00f42a5c --- /dev/null +++ b/vendor/github.com/lucasb-eyer/go-colorful/warm_palettegen.go @@ -0,0 +1,25 @@ +package colorful + +import ( + "math/rand" +) + +// Uses the HSV color space to generate colors with similar S,V but distributed +// evenly along their Hue. This is fast but not always pretty. +// If you've got time to spare, use Lab (the non-fast below). +func FastWarmPalette(colorsCount int) (colors []Color) { + colors = make([]Color, colorsCount) + + for i := 0; i < colorsCount; i++ { + colors[i] = Hsv(float64(i)*(360.0/float64(colorsCount)), 0.55+rand.Float64()*0.2, 0.35+rand.Float64()*0.2) + } + return +} + +func WarmPalette(colorsCount int) ([]Color, error) { + warmy := func(l, a, b float64) bool { + _, c, _ := LabToHcl(l, a, b) + return 0.1 <= c && c <= 0.4 && 0.2 <= l && l <= 0.5 + } + return SoftPaletteEx(colorsCount, SoftPaletteSettings{warmy, 50, true}) +} diff --git a/vendor/github.com/mattn/go-localereader/README.md b/vendor/github.com/mattn/go-localereader/README.md new file mode 100644 index 00000000..9e109532 --- /dev/null +++ b/vendor/github.com/mattn/go-localereader/README.md @@ -0,0 +1,23 @@ +# go-localereader + +CodePage decoder for Windows + +## Usage + +``` +io.Copy(os.Stdout, localereader.NewAcpReader(bytes.Reader(bytesSjis))) +``` + +## Installation + +``` +$ go get github.com/mattn/go-localereader +``` + +## License + +MIT + +## Author + +Yasuhiro Matsumoto (a.k.a. mattn) diff --git a/vendor/github.com/mattn/go-localereader/localereader.go b/vendor/github.com/mattn/go-localereader/localereader.go new file mode 100644 index 00000000..47a31375 --- /dev/null +++ b/vendor/github.com/mattn/go-localereader/localereader.go @@ -0,0 +1,19 @@ +package localereader + +import ( + "bytes" + "io" +) + +func NewReader(r io.Reader) io.Reader { + return newReader(r) +} + +func UTF8(b []byte) ([]byte, error) { + var buf bytes.Buffer + n, err := io.Copy(&buf, newReader(bytes.NewReader(b))) + if err != nil { + return nil, err + } + return buf.Bytes()[:n], nil +} diff --git a/vendor/github.com/mattn/go-localereader/localereader_unix.go b/vendor/github.com/mattn/go-localereader/localereader_unix.go new file mode 100644 index 00000000..d85e12e4 --- /dev/null +++ b/vendor/github.com/mattn/go-localereader/localereader_unix.go @@ -0,0 +1,11 @@ +// +build !windows + +package localereader + +import ( + "io" +) + +func newReader(r io.Reader) io.Reader { + return r +} diff --git a/vendor/github.com/mattn/go-localereader/localereader_windows.go b/vendor/github.com/mattn/go-localereader/localereader_windows.go new file mode 100644 index 00000000..57c238fe --- /dev/null +++ b/vendor/github.com/mattn/go-localereader/localereader_windows.go @@ -0,0 +1,85 @@ +// +build windows + +package localereader + +import ( + "io" + "syscall" + "unicode/utf8" + "unsafe" + + "golang.org/x/text/transform" +) + +const ( + CP_ACP = 0 + MB_ERR_INVALID_CHARS = 8 +) + +var ( + modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procMultiByteToWideChar = modkernel32.NewProc("MultiByteToWideChar") + procIsDBCSLeadByte = modkernel32.NewProc("IsDBCSLeadByte") +) + +type codepageDecoder struct { + transform.NopResetter + + cp int +} + +func (codepageDecoder) Transform(dst, src []byte, atEOF bool) (nDst, nSrc int, err error) { + r, size := rune(0), 0 +loop: + for ; nSrc < len(src); nSrc += size { + switch c0 := src[nSrc]; { + case c0 < utf8.RuneSelf: + r, size = rune(c0), 1 + + default: + br, _, _ := procIsDBCSLeadByte.Call(uintptr(src[nSrc])) + if br == 0 { + r = rune(src[nSrc]) + size = 1 + break + } + if nSrc >= len(src)-1 { + r = rune(src[nSrc]) + size = 1 + break + } + n, _, _ := procMultiByteToWideChar.Call(CP_ACP, 0, uintptr(unsafe.Pointer(&src[nSrc])), uintptr(2), uintptr(0), 0) + if n <= 0 { + err = syscall.GetLastError() + break + } + var us [1]uint16 + rc, _, _ := procMultiByteToWideChar.Call(CP_ACP, 0, uintptr(unsafe.Pointer(&src[nSrc])), uintptr(2), uintptr(unsafe.Pointer(&us[0])), 1) + if rc == 0 { + size = 1 + break + } + r = rune(us[0]) + size = 2 + } + if nDst+utf8.RuneLen(r) > len(dst) { + err = transform.ErrShortDst + break loop + } + nDst += utf8.EncodeRune(dst[nDst:], r) + } + return nDst, nSrc, err + +} + +func newReader(r io.Reader) io.Reader { + return transform.NewReader(r, NewAcpDecoder()) +} + +func NewCodePageDecoder(cp int) transform.Transformer { + return &codepageDecoder{cp: cp} +} + +func NewAcpDecoder() transform.Transformer { + return &codepageDecoder{cp: CP_ACP} +} diff --git a/vendor/github.com/muesli/ansi/.gitignore b/vendor/github.com/muesli/ansi/.gitignore new file mode 100644 index 00000000..66fd13c9 --- /dev/null +++ b/vendor/github.com/muesli/ansi/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/muesli/ansi/.golangci.yml b/vendor/github.com/muesli/ansi/.golangci.yml new file mode 100644 index 00000000..cd299e2b --- /dev/null +++ b/vendor/github.com/muesli/ansi/.golangci.yml @@ -0,0 +1,27 @@ +run: + tests: false + +issues: + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - bodyclose + - dupl + - exportloopref + - goconst + - godot + - godox + - goimports + - golint + - goprintffuncname + - gosec + - ifshort + - misspell + - prealloc + - rowserrcheck + - sqlclosecheck + - unconvert + - unparam + - whitespace diff --git a/vendor/github.com/muesli/ansi/LICENSE b/vendor/github.com/muesli/ansi/LICENSE new file mode 100644 index 00000000..bd9cdc6f --- /dev/null +++ b/vendor/github.com/muesli/ansi/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Christian Muehlhaeuser + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/muesli/ansi/README.md b/vendor/github.com/muesli/ansi/README.md new file mode 100644 index 00000000..f9d0fe9a --- /dev/null +++ b/vendor/github.com/muesli/ansi/README.md @@ -0,0 +1,31 @@ +# ansi + +[![Latest Release](https://img.shields.io/github/release/muesli/ansi.svg)](https://github.com/muesli/ansi/releases) +[![Build Status](https://github.com/muesli/ansi/workflows/build/badge.svg)](https://github.com/muesli/ansi/actions) +[![Coverage Status](https://coveralls.io/repos/github/muesli/ansi/badge.svg?branch=master)](https://coveralls.io/github/muesli/ansi?branch=master) +[![Go ReportCard](https://goreportcard.com/badge/muesli/ansi)](https://goreportcard.com/report/muesli/ansi) +[![GoDoc](https://godoc.org/github.com/golang/gddo?status.svg)](https://pkg.go.dev/github.com/muesli/ansi) + +Raw ANSI sequence helpers + +## ANSI Writer + +```go +import "github.com/muesli/ansi" + +w := ansi.Writer{Forward: os.Stdout} +w.Write([]byte("\x1b[31mHello, world!\x1b[0m")) +w.Close() +``` + +## Compressor + +The ANSI compressor eliminates unnecessary/redundant ANSI sequences. + +```go +import "github.com/muesli/ansi/compressor" + +w := compressor.Writer{Forward: os.Stdout} +w.Write([]byte("\x1b[31mHello, world!\x1b[0m")) +w.Close() +``` diff --git a/vendor/github.com/muesli/ansi/ansi.go b/vendor/github.com/muesli/ansi/ansi.go new file mode 100644 index 00000000..f3d0700a --- /dev/null +++ b/vendor/github.com/muesli/ansi/ansi.go @@ -0,0 +1,7 @@ +package ansi + +const Marker = '\x1B' + +func IsTerminator(c rune) bool { + return (c >= 0x40 && c <= 0x5a) || (c >= 0x61 && c <= 0x7a) +} diff --git a/vendor/github.com/muesli/ansi/buffer.go b/vendor/github.com/muesli/ansi/buffer.go new file mode 100644 index 00000000..471bcaf7 --- /dev/null +++ b/vendor/github.com/muesli/ansi/buffer.go @@ -0,0 +1,40 @@ +package ansi + +import ( + "bytes" + + "github.com/mattn/go-runewidth" +) + +// Buffer is a buffer aware of ANSI escape sequences. +type Buffer struct { + bytes.Buffer +} + +// PrintableRuneWidth returns the cell width of all printable runes in the +// buffer. +func (w Buffer) PrintableRuneWidth() int { + return PrintableRuneWidth(w.String()) +} + +// PrintableRuneWidth returns the cell width of the given string. +func PrintableRuneWidth(s string) int { + var n int + var ansi bool + + for _, c := range s { + if c == Marker { + // ANSI escape sequence + ansi = true + } else if ansi { + if IsTerminator(c) { + // ANSI sequence terminated + ansi = false + } + } else { + n += runewidth.RuneWidth(c) + } + } + + return n +} diff --git a/vendor/github.com/muesli/ansi/compressor/writer.go b/vendor/github.com/muesli/ansi/compressor/writer.go new file mode 100644 index 00000000..98c54829 --- /dev/null +++ b/vendor/github.com/muesli/ansi/compressor/writer.go @@ -0,0 +1,132 @@ +package compressor + +import ( + "bytes" + "io" + "unicode/utf8" + + "github.com/muesli/ansi" +) + +type Writer struct { + Forward io.Writer + + ansi bool + ansiseq bytes.Buffer + lastseq bytes.Buffer + prevlastseq bytes.Buffer + resetreq bool + runeBuf []byte + compressed int + uncompressed int +} + +// Bytes is shorthand for declaring a new default compressor instance, +// used to immediately compress a byte slice. +func Bytes(b []byte) []byte { + var buf bytes.Buffer + f := Writer{ + Forward: &buf, + } + _, _ = f.Write(b) + _ = f.Close() + + return buf.Bytes() +} + +// String is shorthand for declaring a new default compressor instance, +// used to immediately compress a string. +func String(s string) string { + return string(Bytes([]byte(s))) +} + +// Write is used to write content to the ANSI buffer. +func (w *Writer) Write(b []byte) (int, error) { + w.uncompressed += len(b) + + for _, c := range string(b) { + if c == ansi.Marker { + // ANSI escape sequence + w.ansi = true + _, _ = w.ansiseq.WriteRune(c) + } else if w.ansi { + _, _ = w.ansiseq.WriteRune(c) + if ansi.IsTerminator(c) { + // ANSI sequence terminated + w.ansi = false + + terminated := false + if bytes.HasSuffix(w.ansiseq.Bytes(), []byte("[0m")) { + // reset sequence + w.prevlastseq.Reset() + w.prevlastseq.Write(w.lastseq.Bytes()) + + w.lastseq.Reset() + terminated = true + w.resetreq = true + } else if c == 'm' { + // color code + _, _ = w.lastseq.Write(w.ansiseq.Bytes()) + } + + if !terminated { + // did we reset the sequence just to restore it again? + if bytes.Equal(w.ansiseq.Bytes(), w.prevlastseq.Bytes()) { + w.resetreq = false + w.ansiseq.Reset() + } + + w.prevlastseq.Reset() + + if w.resetreq { + w.ResetAnsi() + } + + _, _ = w.Forward.Write(w.ansiseq.Bytes()) + w.compressed += w.ansiseq.Len() + } + + w.ansiseq.Reset() + } + } else { + if w.resetreq { + w.ResetAnsi() + } + + _, err := w.writeRune(c) + if err != nil { + return 0, err + } + } + } + + return len(b), nil +} + +func (w *Writer) writeRune(r rune) (int, error) { + if w.runeBuf == nil { + w.runeBuf = make([]byte, utf8.UTFMax) + } + n := utf8.EncodeRune(w.runeBuf, r) + w.compressed += n + return w.Forward.Write(w.runeBuf[:n]) +} + +// Close finishes the compression operation. Always call it before trying to +// retrieve the final result. +func (w *Writer) Close() error { + if w.resetreq { + w.ResetAnsi() + } + + // log.Println("Written uncompressed: ", w.uncompressed) + // log.Println("Written compressed: ", w.compressed) + + return nil +} + +func (w *Writer) ResetAnsi() { + w.prevlastseq.Reset() + _, _ = w.Forward.Write([]byte("\x1b[0m")) + w.resetreq = false +} diff --git a/vendor/github.com/muesli/ansi/writer.go b/vendor/github.com/muesli/ansi/writer.go new file mode 100644 index 00000000..a6aaa1ec --- /dev/null +++ b/vendor/github.com/muesli/ansi/writer.go @@ -0,0 +1,76 @@ +package ansi + +import ( + "bytes" + "io" + "unicode/utf8" +) + +type Writer struct { + Forward io.Writer + + ansi bool + ansiseq bytes.Buffer + lastseq bytes.Buffer + seqchanged bool + runeBuf []byte +} + +// Write is used to write content to the ANSI buffer. +func (w *Writer) Write(b []byte) (int, error) { + for _, c := range string(b) { + if c == Marker { + // ANSI escape sequence + w.ansi = true + w.seqchanged = true + _, _ = w.ansiseq.WriteRune(c) + } else if w.ansi { + _, _ = w.ansiseq.WriteRune(c) + if IsTerminator(c) { + // ANSI sequence terminated + w.ansi = false + + if bytes.HasSuffix(w.ansiseq.Bytes(), []byte("[0m")) { + // reset sequence + w.lastseq.Reset() + w.seqchanged = false + } else if c == 'm' { + // color code + _, _ = w.lastseq.Write(w.ansiseq.Bytes()) + } + + _, _ = w.ansiseq.WriteTo(w.Forward) + } + } else { + _, err := w.writeRune(c) + if err != nil { + return 0, err + } + } + } + + return len(b), nil +} + +func (w *Writer) writeRune(r rune) (int, error) { + if w.runeBuf == nil { + w.runeBuf = make([]byte, utf8.UTFMax) + } + n := utf8.EncodeRune(w.runeBuf, r) + return w.Forward.Write(w.runeBuf[:n]) +} + +func (w *Writer) LastSequence() string { + return w.lastseq.String() +} + +func (w *Writer) ResetAnsi() { + if !w.seqchanged { + return + } + _, _ = w.Forward.Write([]byte("\x1b[0m")) +} + +func (w *Writer) RestoreAnsi() { + _, _ = w.Forward.Write(w.lastseq.Bytes()) +} diff --git a/vendor/github.com/muesli/cancelreader/.gitignore b/vendor/github.com/muesli/cancelreader/.gitignore new file mode 100644 index 00000000..66fd13c9 --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/muesli/cancelreader/.golangci-soft.yml b/vendor/github.com/muesli/cancelreader/.golangci-soft.yml new file mode 100644 index 00000000..ef456e06 --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/.golangci-soft.yml @@ -0,0 +1,47 @@ +run: + tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + # - dupl + - exhaustive + # - exhaustivestruct + - goconst + - godot + - godox + - gomnd + - gomoddirectives + - goprintffuncname + - ifshort + # - lll + - misspell + - nakedret + - nestif + - noctx + - nolintlint + - prealloc + - wrapcheck + + # disable default linters, they are already enabled in .golangci.yml + disable: + - deadcode + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - structcheck + - typecheck + - unused + - varcheck diff --git a/vendor/github.com/muesli/cancelreader/.golangci.yml b/vendor/github.com/muesli/cancelreader/.golangci.yml new file mode 100644 index 00000000..a5a91d0d --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/.golangci.yml @@ -0,0 +1,29 @@ +run: + tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - bodyclose + - exportloopref + - goimports + - gosec + - nilerr + - predeclared + - revive + - rowserrcheck + - sqlclosecheck + - tparallel + - unconvert + - unparam + - whitespace diff --git a/vendor/github.com/muesli/cancelreader/LICENSE b/vendor/github.com/muesli/cancelreader/LICENSE new file mode 100644 index 00000000..4b19b92d --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Erik Geiser and Christian Muehlhaeuser + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/muesli/cancelreader/README.md b/vendor/github.com/muesli/cancelreader/README.md new file mode 100644 index 00000000..83609fbc --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/README.md @@ -0,0 +1,64 @@ +# CancelReader + +[![Latest Release](https://img.shields.io/github/release/muesli/cancelreader.svg?style=for-the-badge)](https://github.com/muesli/cancelreader/releases) +[![Go Doc](https://img.shields.io/badge/godoc-reference-blue.svg?style=for-the-badge)](https://pkg.go.dev/github.com/muesli/cancelreader) +[![Software License](https://img.shields.io/badge/license-MIT-blue.svg?style=for-the-badge)](/LICENSE) +[![Build Status](https://img.shields.io/github/workflow/status/muesli/cancelreader/build?style=for-the-badge)](https://github.com/muesli/cancelreader/actions) +[![Go ReportCard](https://goreportcard.com/badge/github.com/muesli/cancelreader?style=for-the-badge)](https://goreportcard.com/report/muesli/cancelreader) + +A cancelable reader for Go + +This package is based on the fantastic work of [Erik Geiser](https://github.com/erikgeiser) +in Charm's [Bubble Tea](https://github.com/charmbracelet/bubbletea) framework. + +## Usage + +`NewReader` returns a reader with a `Cancel` function. If the input reader is a +`File`, the cancel function can be used to interrupt a blocking `Read` call. +In this case, the cancel function returns true if the call was canceled +successfully. If the input reader is not a `File`, the cancel function does +nothing and always returns false. + +```go +r, err := cancelreader.NewReader(file) +if err != nil { + // handle error + ... +} + +// cancel after five seconds +go func() { + time.Sleep(5 * time.Second) + r.Cancel() +}() + +// keep reading +for { + var buf [1024]byte + _, err := r.Read(buf[:]) + + if errors.Is(err, cancelreader.ErrCanceled) { + fmt.Println("canceled!") + break + } + if err != nil { + // handle other errors + ... + } + + // handle data + ... +} +``` + +## Implementations + +- The Linux implementation is based on the epoll mechanism +- The BSD and macOS implementation is based on the kqueue mechanism +- The generic Unix implementation is based on the posix select syscall + +## Caution + +The Windows implementation is based on WaitForMultipleObject with overlapping +reads from CONIN$. At this point it only supports canceling reads from +`os.Stdin`. diff --git a/vendor/github.com/muesli/cancelreader/cancelreader.go b/vendor/github.com/muesli/cancelreader/cancelreader.go new file mode 100644 index 00000000..18d38255 --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/cancelreader.go @@ -0,0 +1,93 @@ +package cancelreader + +import ( + "fmt" + "io" + "sync" +) + +// ErrCanceled gets returned when trying to read from a canceled reader. +var ErrCanceled = fmt.Errorf("read canceled") + +// CancelReader is a io.Reader whose Read() calls can be canceled without data +// being consumed. The cancelReader has to be closed. +type CancelReader interface { + io.ReadCloser + + // Cancel cancels ongoing and future reads an returns true if it succeeded. + Cancel() bool +} + +// File represents an input/output resource with a file descriptor. +type File interface { + io.ReadWriteCloser + + // Fd returns its file descriptor + Fd() uintptr + + // Name returns its file name. + Name() string +} + +// fallbackCancelReader implements cancelReader but does not actually support +// cancelation during an ongoing Read() call. Thus, Cancel() always returns +// false. However, after calling Cancel(), new Read() calls immediately return +// errCanceled and don't consume any data anymore. +type fallbackCancelReader struct { + r io.Reader + cancelMixin +} + +// newFallbackCancelReader is a fallback for NewReader that cannot actually +// cancel an ongoing read but will immediately return on future reads if it has +// been canceled. +func newFallbackCancelReader(reader io.Reader) (CancelReader, error) { + return &fallbackCancelReader{r: reader}, nil +} + +func (r *fallbackCancelReader) Read(data []byte) (int, error) { + if r.isCanceled() { + return 0, ErrCanceled + } + + n, err := r.r.Read(data) + /* + If the underlying reader is a blocking reader (e.g. an open connection), + it might happen that 1 goroutine cancels the reader while its stuck in + the read call waiting for something. + If that happens, we should still cancel the read. + */ + if r.isCanceled() { + return 0, ErrCanceled + } + return n, err // nolint: wrapcheck +} + +func (r *fallbackCancelReader) Cancel() bool { + r.setCanceled() + return false +} + +func (r *fallbackCancelReader) Close() error { + return nil +} + +// cancelMixin represents a goroutine-safe cancelation status. +type cancelMixin struct { + unsafeCanceled bool + lock sync.Mutex +} + +func (c *cancelMixin) isCanceled() bool { + c.lock.Lock() + defer c.lock.Unlock() + + return c.unsafeCanceled +} + +func (c *cancelMixin) setCanceled() { + c.lock.Lock() + defer c.lock.Unlock() + + c.unsafeCanceled = true +} diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go b/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go new file mode 100644 index 00000000..3ddb6cff --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/cancelreader_bsd.go @@ -0,0 +1,146 @@ +//go:build darwin || freebsd || netbsd || openbsd || dragonfly +// +build darwin freebsd netbsd openbsd dragonfly + +package cancelreader + +import ( + "errors" + "fmt" + "io" + "os" + "strings" + + "golang.org/x/sys/unix" +) + +// NewReader returns a reader and a cancel function. If the input reader is a +// File, the cancel function can be used to interrupt a blocking read call. +// In this case, the cancel function returns true if the call was canceled +// successfully. If the input reader is not a File, the cancel function +// does nothing and always returns false. The BSD and macOS implementation is +// based on the kqueue mechanism. +func NewReader(reader io.Reader) (CancelReader, error) { + file, ok := reader.(File) + if !ok { + return newFallbackCancelReader(reader) + } + + // kqueue returns instantly when polling /dev/tty so fallback to select + if file.Name() == "/dev/tty" { + return newSelectCancelReader(reader) + } + + kQueue, err := unix.Kqueue() + if err != nil { + return nil, fmt.Errorf("create kqueue: %w", err) + } + + r := &kqueueCancelReader{ + file: file, + kQueue: kQueue, + } + + r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe() + if err != nil { + _ = unix.Close(kQueue) + return nil, err + } + + unix.SetKevent(&r.kQueueEvents[0], int(file.Fd()), unix.EVFILT_READ, unix.EV_ADD) + unix.SetKevent(&r.kQueueEvents[1], int(r.cancelSignalReader.Fd()), unix.EVFILT_READ, unix.EV_ADD) + + return r, nil +} + +type kqueueCancelReader struct { + file File + cancelSignalReader File + cancelSignalWriter File + cancelMixin + kQueue int + kQueueEvents [2]unix.Kevent_t +} + +func (r *kqueueCancelReader) Read(data []byte) (int, error) { + if r.isCanceled() { + return 0, ErrCanceled + } + + err := r.wait() + if err != nil { + if errors.Is(err, ErrCanceled) { + // remove signal from pipe + var b [1]byte + _, errRead := r.cancelSignalReader.Read(b[:]) + if errRead != nil { + return 0, fmt.Errorf("reading cancel signal: %w", errRead) + } + } + + return 0, err + } + + return r.file.Read(data) +} + +func (r *kqueueCancelReader) Cancel() bool { + r.setCanceled() + + // send cancel signal + _, err := r.cancelSignalWriter.Write([]byte{'c'}) + return err == nil +} + +func (r *kqueueCancelReader) Close() error { + var errMsgs []string + + // close kqueue + err := unix.Close(r.kQueue) + if err != nil { + errMsgs = append(errMsgs, fmt.Sprintf("closing kqueue: %v", err)) + } + + // close pipe + err = r.cancelSignalWriter.Close() + if err != nil { + errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err)) + } + + err = r.cancelSignalReader.Close() + if err != nil { + errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err)) + } + + if len(errMsgs) > 0 { + return fmt.Errorf(strings.Join(errMsgs, ", ")) + } + + return nil +} + +func (r *kqueueCancelReader) wait() error { + events := make([]unix.Kevent_t, 1) + + for { + _, err := unix.Kevent(r.kQueue, r.kQueueEvents[:], events, nil) + if errors.Is(err, unix.EINTR) { + continue // try again if the syscall was interrupted + } + + if err != nil { + return fmt.Errorf("kevent: %w", err) + } + + break + } + + ident := uint64(events[0].Ident) + switch ident { + case uint64(r.file.Fd()): + return nil + case uint64(r.cancelSignalReader.Fd()): + return ErrCanceled + } + + return fmt.Errorf("unknown error") +} diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_default.go b/vendor/github.com/muesli/cancelreader/cancelreader_default.go new file mode 100644 index 00000000..8e275fa4 --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/cancelreader_default.go @@ -0,0 +1,12 @@ +//go:build !darwin && !windows && !linux && !solaris && !freebsd && !netbsd && !openbsd && !dragonfly +// +build !darwin,!windows,!linux,!solaris,!freebsd,!netbsd,!openbsd,!dragonfly + +package cancelreader + +import "io" + +// NewReader returns a fallbackCancelReader that satisfies the CancelReader but +// does not actually support cancellation. +func NewReader(reader io.Reader) (CancelReader, error) { + return newFallbackCancelReader(reader) +} diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_linux.go b/vendor/github.com/muesli/cancelreader/cancelreader_linux.go new file mode 100644 index 00000000..09f7369f --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/cancelreader_linux.go @@ -0,0 +1,154 @@ +//go:build linux +// +build linux + +package cancelreader + +import ( + "errors" + "fmt" + "io" + "os" + "strings" + + "golang.org/x/sys/unix" +) + +// NewReader returns a reader and a cancel function. If the input reader is a +// File, the cancel function can be used to interrupt a blocking read call. +// In this case, the cancel function returns true if the call was canceled +// successfully. If the input reader is not a File, the cancel function +// does nothing and always returns false. The Linux implementation is based on +// the epoll mechanism. +func NewReader(reader io.Reader) (CancelReader, error) { + file, ok := reader.(File) + if !ok { + return newFallbackCancelReader(reader) + } + + epoll, err := unix.EpollCreate1(0) + if err != nil { + return nil, fmt.Errorf("create epoll: %w", err) + } + + r := &epollCancelReader{ + file: file, + epoll: epoll, + } + + r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe() + if err != nil { + _ = unix.Close(epoll) + return nil, err + } + + err = unix.EpollCtl(epoll, unix.EPOLL_CTL_ADD, int(file.Fd()), &unix.EpollEvent{ + Events: unix.EPOLLIN, + Fd: int32(file.Fd()), + }) + if err != nil { + _ = unix.Close(epoll) + return nil, fmt.Errorf("add reader to epoll interest list") + } + + err = unix.EpollCtl(epoll, unix.EPOLL_CTL_ADD, int(r.cancelSignalReader.Fd()), &unix.EpollEvent{ + Events: unix.EPOLLIN, + Fd: int32(r.cancelSignalReader.Fd()), + }) + if err != nil { + _ = unix.Close(epoll) + return nil, fmt.Errorf("add reader to epoll interest list") + } + + return r, nil +} + +type epollCancelReader struct { + file File + cancelSignalReader File + cancelSignalWriter File + cancelMixin + epoll int +} + +func (r *epollCancelReader) Read(data []byte) (int, error) { + if r.isCanceled() { + return 0, ErrCanceled + } + + err := r.wait() + if err != nil { + if errors.Is(err, ErrCanceled) { + // remove signal from pipe + var b [1]byte + _, readErr := r.cancelSignalReader.Read(b[:]) + if readErr != nil { + return 0, fmt.Errorf("reading cancel signal: %w", readErr) + } + } + + return 0, err + } + + return r.file.Read(data) +} + +func (r *epollCancelReader) Cancel() bool { + r.setCanceled() + + // send cancel signal + _, err := r.cancelSignalWriter.Write([]byte{'c'}) + return err == nil +} + +func (r *epollCancelReader) Close() error { + var errMsgs []string + + // close kqueue + err := unix.Close(r.epoll) + if err != nil { + errMsgs = append(errMsgs, fmt.Sprintf("closing epoll: %v", err)) + } + + // close pipe + err = r.cancelSignalWriter.Close() + if err != nil { + errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err)) + } + + err = r.cancelSignalReader.Close() + if err != nil { + errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err)) + } + + if len(errMsgs) > 0 { + return fmt.Errorf(strings.Join(errMsgs, ", ")) + } + + return nil +} + +func (r *epollCancelReader) wait() error { + events := make([]unix.EpollEvent, 1) + + for { + _, err := unix.EpollWait(r.epoll, events, -1) + if errors.Is(err, unix.EINTR) { + continue // try again if the syscall was interrupted + } + + if err != nil { + return fmt.Errorf("kevent: %w", err) + } + + break + } + + switch events[0].Fd { + case int32(r.file.Fd()): + return nil + case int32(r.cancelSignalReader.Fd()): + return ErrCanceled + } + + return fmt.Errorf("unknown error") +} diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_select.go b/vendor/github.com/muesli/cancelreader/cancelreader_select.go new file mode 100644 index 00000000..03f2a3e1 --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/cancelreader_select.go @@ -0,0 +1,136 @@ +//go:build solaris || darwin || freebsd || netbsd || openbsd || dragonfly +// +build solaris darwin freebsd netbsd openbsd dragonfly + +package cancelreader + +import ( + "errors" + "fmt" + "io" + "os" + "strings" + + "golang.org/x/sys/unix" +) + +// newSelectCancelReader returns a reader and a cancel function. If the input +// reader is a File, the cancel function can be used to interrupt a +// blocking call read call. In this case, the cancel function returns true if +// the call was canceled successfully. If the input reader is not a File or +// the file descriptor is 1024 or larger, the cancel function does nothing and +// always returns false. The generic unix implementation is based on the posix +// select syscall. +func newSelectCancelReader(reader io.Reader) (CancelReader, error) { + file, ok := reader.(File) + if !ok || file.Fd() >= unix.FD_SETSIZE { + return newFallbackCancelReader(reader) + } + r := &selectCancelReader{file: file} + + var err error + + r.cancelSignalReader, r.cancelSignalWriter, err = os.Pipe() + if err != nil { + return nil, err + } + + return r, nil +} + +type selectCancelReader struct { + file File + cancelSignalReader File + cancelSignalWriter File + cancelMixin +} + +func (r *selectCancelReader) Read(data []byte) (int, error) { + if r.isCanceled() { + return 0, ErrCanceled + } + + for { + err := waitForRead(r.file, r.cancelSignalReader) + if err != nil { + if errors.Is(err, unix.EINTR) { + continue // try again if the syscall was interrupted + } + + if errors.Is(err, ErrCanceled) { + // remove signal from pipe + var b [1]byte + _, readErr := r.cancelSignalReader.Read(b[:]) + if readErr != nil { + return 0, fmt.Errorf("reading cancel signal: %w", readErr) + } + } + + return 0, err + } + + return r.file.Read(data) + } +} + +func (r *selectCancelReader) Cancel() bool { + r.setCanceled() + + // send cancel signal + _, err := r.cancelSignalWriter.Write([]byte{'c'}) + return err == nil +} + +func (r *selectCancelReader) Close() error { + var errMsgs []string + + // close pipe + err := r.cancelSignalWriter.Close() + if err != nil { + errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal writer: %v", err)) + } + + err = r.cancelSignalReader.Close() + if err != nil { + errMsgs = append(errMsgs, fmt.Sprintf("closing cancel signal reader: %v", err)) + } + + if len(errMsgs) > 0 { + return fmt.Errorf(strings.Join(errMsgs, ", ")) + } + + return nil +} + +func waitForRead(reader, abort File) error { + readerFd := int(reader.Fd()) + abortFd := int(abort.Fd()) + + maxFd := readerFd + if abortFd > maxFd { + maxFd = abortFd + } + + // this is a limitation of the select syscall + if maxFd >= unix.FD_SETSIZE { + return fmt.Errorf("cannot select on file descriptor %d which is larger than 1024", maxFd) + } + + fdSet := &unix.FdSet{} + fdSet.Set(int(reader.Fd())) + fdSet.Set(int(abort.Fd())) + + _, err := unix.Select(maxFd+1, fdSet, nil, nil, nil) + if err != nil { + return fmt.Errorf("select: %w", err) + } + + if fdSet.IsSet(abortFd) { + return ErrCanceled + } + + if fdSet.IsSet(readerFd) { + return nil + } + + return fmt.Errorf("select returned without setting a file descriptor") +} diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_unix.go b/vendor/github.com/muesli/cancelreader/cancelreader_unix.go new file mode 100644 index 00000000..3c10ee09 --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/cancelreader_unix.go @@ -0,0 +1,18 @@ +//go:build solaris +// +build solaris + +package cancelreader + +import ( + "io" +) + +// NewReader returns a reader and a cancel function. If the input reader is a +// File, the cancel function can be used to interrupt a blocking read call. +// In this case, the cancel function returns true if the call was canceled +// successfully. If the input reader is not a File or the file descriptor +// is 1024 or larger, the cancel function does nothing and always returns false. +// The generic unix implementation is based on the posix select syscall. +func NewReader(reader io.Reader) (CancelReader, error) { + return newSelectCancelReader(reader) +} diff --git a/vendor/github.com/muesli/cancelreader/cancelreader_windows.go b/vendor/github.com/muesli/cancelreader/cancelreader_windows.go new file mode 100644 index 00000000..c1dc8d50 --- /dev/null +++ b/vendor/github.com/muesli/cancelreader/cancelreader_windows.go @@ -0,0 +1,244 @@ +//go:build windows +// +build windows + +package cancelreader + +import ( + "fmt" + "io" + "os" + "syscall" + "time" + "unicode/utf16" + + "golang.org/x/sys/windows" +) + +var fileShareValidFlags uint32 = 0x00000007 + +// NewReader returns a reader and a cancel function. If the input reader is a +// File with the same file descriptor as os.Stdin, the cancel function can +// be used to interrupt a blocking read call. In this case, the cancel function +// returns true if the call was canceled successfully. If the input reader is +// not a File with the same file descriptor as os.Stdin, the cancel +// function does nothing and always returns false. The Windows implementation +// is based on WaitForMultipleObject with overlapping reads from CONIN$. +func NewReader(reader io.Reader) (CancelReader, error) { + if f, ok := reader.(File); !ok || f.Fd() != os.Stdin.Fd() { + return newFallbackCancelReader(reader) + } + + // it is necessary to open CONIN$ (NOT windows.STD_INPUT_HANDLE) in + // overlapped mode to be able to use it with WaitForMultipleObjects. + conin, err := windows.CreateFile( + &(utf16.Encode([]rune("CONIN$\x00"))[0]), windows.GENERIC_READ|windows.GENERIC_WRITE, + fileShareValidFlags, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_OVERLAPPED, 0) + if err != nil { + return nil, fmt.Errorf("open CONIN$ in overlapping mode: %w", err) + } + + resetConsole, err := prepareConsole(conin) + if err != nil { + return nil, fmt.Errorf("prepare console: %w", err) + } + + // flush input, otherwise it can contain events which trigger + // WaitForMultipleObjects but which ReadFile cannot read, resulting in an + // un-cancelable read + err = flushConsoleInputBuffer(conin) + if err != nil { + return nil, fmt.Errorf("flush console input buffer: %w", err) + } + + cancelEvent, err := windows.CreateEvent(nil, 0, 0, nil) + if err != nil { + return nil, fmt.Errorf("create stop event: %w", err) + } + + return &winCancelReader{ + conin: conin, + cancelEvent: cancelEvent, + resetConsole: resetConsole, + blockingReadSignal: make(chan struct{}, 1), + }, nil +} + +type winCancelReader struct { + conin windows.Handle + cancelEvent windows.Handle + cancelMixin + + resetConsole func() error + blockingReadSignal chan struct{} +} + +func (r *winCancelReader) Read(data []byte) (int, error) { + if r.isCanceled() { + return 0, ErrCanceled + } + + err := r.wait() + if err != nil { + return 0, err + } + + if r.isCanceled() { + return 0, ErrCanceled + } + + // windows.Read does not work on overlapping windows.Handles + return r.readAsync(data) +} + +// Cancel cancels ongoing and future Read() calls and returns true if the +// cancelation of the ongoing Read() was successful. On Windows Terminal, +// WaitForMultipleObjects sometimes immediately returns without input being +// available. In this case, graceful cancelation is not possible and Cancel() +// returns false. +func (r *winCancelReader) Cancel() bool { + r.setCanceled() + + select { + case r.blockingReadSignal <- struct{}{}: + err := windows.SetEvent(r.cancelEvent) + if err != nil { + return false + } + <-r.blockingReadSignal + case <-time.After(100 * time.Millisecond): + // Read() hangs in a GetOverlappedResult which is likely due to + // WaitForMultipleObjects returning without input being available + // so we cannot cancel this ongoing read. + return false + } + + return true +} + +func (r *winCancelReader) Close() error { + err := windows.CloseHandle(r.cancelEvent) + if err != nil { + return fmt.Errorf("closing cancel event handle: %w", err) + } + + err = r.resetConsole() + if err != nil { + return err + } + + err = windows.Close(r.conin) + if err != nil { + return fmt.Errorf("closing CONIN$") + } + + return nil +} + +func (r *winCancelReader) wait() error { + event, err := windows.WaitForMultipleObjects([]windows.Handle{r.conin, r.cancelEvent}, false, windows.INFINITE) + switch { + case windows.WAIT_OBJECT_0 <= event && event < windows.WAIT_OBJECT_0+2: + if event == windows.WAIT_OBJECT_0+1 { + return ErrCanceled + } + + if event == windows.WAIT_OBJECT_0 { + return nil + } + + return fmt.Errorf("unexpected wait object is ready: %d", event-windows.WAIT_OBJECT_0) + case windows.WAIT_ABANDONED <= event && event < windows.WAIT_ABANDONED+2: + return fmt.Errorf("abandoned") + case event == uint32(windows.WAIT_TIMEOUT): + return fmt.Errorf("timeout") + case event == windows.WAIT_FAILED: + return fmt.Errorf("failed") + default: + return fmt.Errorf("unexpected error: %w", error(err)) + } +} + +// readAsync is necessary to read from a windows.Handle in overlapping mode. +func (r *winCancelReader) readAsync(data []byte) (int, error) { + hevent, err := windows.CreateEvent(nil, 0, 0, nil) + if err != nil { + return 0, fmt.Errorf("create event: %w", err) + } + + overlapped := windows.Overlapped{ + HEvent: hevent, + } + + var n uint32 + + err = windows.ReadFile(r.conin, data, &n, &overlapped) + if err != nil && err != windows.ERROR_IO_PENDING { + return int(n), err + } + + r.blockingReadSignal <- struct{}{} + err = windows.GetOverlappedResult(r.conin, &overlapped, &n, true) + if err != nil { + return int(n), nil + } + <-r.blockingReadSignal + + return int(n), nil +} + +func prepareConsole(input windows.Handle) (reset func() error, err error) { + var originalMode uint32 + + err = windows.GetConsoleMode(input, &originalMode) + if err != nil { + return nil, fmt.Errorf("get console mode: %w", err) + } + + var newMode uint32 + newMode &^= windows.ENABLE_ECHO_INPUT + newMode &^= windows.ENABLE_LINE_INPUT + newMode &^= windows.ENABLE_MOUSE_INPUT + newMode &^= windows.ENABLE_WINDOW_INPUT + newMode &^= windows.ENABLE_PROCESSED_INPUT + + newMode |= windows.ENABLE_EXTENDED_FLAGS + newMode |= windows.ENABLE_INSERT_MODE + newMode |= windows.ENABLE_QUICK_EDIT_MODE + + // Enabling virtual terminal input is necessary for processing certain + // types of input like X10 mouse events and arrows keys with the current + // bytes-based input reader. It does, however, prevent cancelReader from + // being able to cancel input. The planned solution for this is to read + // Windows events in a more native fashion, rather than the current simple + // bytes-based input reader which works well on unix systems. + newMode |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT + + err = windows.SetConsoleMode(input, newMode) + if err != nil { + return nil, fmt.Errorf("set console mode: %w", err) + } + + return func() error { + err := windows.SetConsoleMode(input, originalMode) + if err != nil { + return fmt.Errorf("reset console mode: %w", err) + } + + return nil + }, nil +} + +var ( + modkernel32 = windows.NewLazySystemDLL("kernel32.dll") + procFlushConsoleInputBuffer = modkernel32.NewProc("FlushConsoleInputBuffer") +) + +func flushConsoleInputBuffer(consoleInput windows.Handle) error { + r, _, e := syscall.Syscall(procFlushConsoleInputBuffer.Addr(), 1, + uintptr(consoleInput), 0, 0) + if r == 0 { + return error(e) + } + + return nil +} diff --git a/vendor/github.com/muesli/termenv/.gitignore b/vendor/github.com/muesli/termenv/.gitignore new file mode 100644 index 00000000..66fd13c9 --- /dev/null +++ b/vendor/github.com/muesli/termenv/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/github.com/muesli/termenv/.golangci-soft.yml b/vendor/github.com/muesli/termenv/.golangci-soft.yml new file mode 100644 index 00000000..84e3d41d --- /dev/null +++ b/vendor/github.com/muesli/termenv/.golangci-soft.yml @@ -0,0 +1,43 @@ +run: + tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + # - dupl + - exhaustive + # - exhaustivestruct + - goconst + - godot + - godox + - mnd + - gomoddirectives + - goprintffuncname + # - lll + - misspell + - nakedret + - nestif + - noctx + - nolintlint + - prealloc + - wrapcheck + + # disable default linters, they are already enabled in .golangci.yml + disable: + - errcheck + - gosimple + - govet + - ineffassign + - staticcheck + - typecheck + - unused diff --git a/vendor/github.com/muesli/termenv/.golangci.yml b/vendor/github.com/muesli/termenv/.golangci.yml new file mode 100644 index 00000000..684d54bf --- /dev/null +++ b/vendor/github.com/muesli/termenv/.golangci.yml @@ -0,0 +1,28 @@ +run: + tests: false + +issues: + include: + - EXC0001 + - EXC0005 + - EXC0011 + - EXC0012 + - EXC0013 + + max-issues-per-linter: 0 + max-same-issues: 0 + +linters: + enable: + - bodyclose + - goimports + - gosec + - nilerr + - predeclared + - revive + - rowserrcheck + - sqlclosecheck + - tparallel + - unconvert + - unparam + - whitespace diff --git a/vendor/github.com/muesli/termenv/LICENSE b/vendor/github.com/muesli/termenv/LICENSE new file mode 100644 index 00000000..8532c45c --- /dev/null +++ b/vendor/github.com/muesli/termenv/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Christian Muehlhaeuser + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/muesli/termenv/README.md b/vendor/github.com/muesli/termenv/README.md new file mode 100644 index 00000000..fa7929d4 --- /dev/null +++ b/vendor/github.com/muesli/termenv/README.md @@ -0,0 +1,431 @@ +

+ termenv Logo +
+ Latest Release + GoDoc + Build Status + Coverage Status + Go ReportCard +
+ Example terminal output +

+ +`termenv` lets you safely use advanced styling options on the terminal. It +gathers information about the terminal environment in terms of its ANSI & color +support and offers you convenient methods to colorize and style your output, +without you having to deal with all kinds of weird ANSI escape sequences and +color conversions. + +## Features + +- RGB/TrueColor support +- Detects the supported color range of your terminal +- Automatically converts colors to the best matching, available colors +- Terminal theme (light/dark) detection +- Chainable syntax +- Nested styles + +## Installation + +```bash +go get github.com/muesli/termenv +``` + +## Usage + +```go +output := termenv.NewOutput(os.Stdout) +``` + +`termenv` queries the terminal's capabilities it is running in, so you can +safely use advanced features, like RGB colors or ANSI styles. `output.Profile` +returns the supported profile: + +- `termenv.Ascii` - no ANSI support detected, ASCII only +- `termenv.ANSI` - 16 color ANSI support +- `termenv.ANSI256` - Extended 256 color ANSI support +- `termenv.TrueColor` - RGB/TrueColor support + +Alternatively, you can use `termenv.EnvColorProfile` which evaluates the +terminal like `ColorProfile`, but also respects the `NO_COLOR` and +`CLICOLOR_FORCE` environment variables. + +You can also query the terminal for its color scheme, so you know whether your +app is running in a light- or dark-themed environment: + +```go +// Returns terminal's foreground color +color := output.ForegroundColor() + +// Returns terminal's background color +color := output.BackgroundColor() + +// Returns whether terminal uses a dark-ish background +darkTheme := output.HasDarkBackground() +``` + +### Manual Profile Selection + +If you don't want to rely on the automatic detection, you can manually select +the profile you want to use: + +```go +output := termenv.NewOutput(os.Stdout, termenv.WithProfile(termenv.TrueColor)) +``` + +## Colors + +`termenv` supports multiple color profiles: Ascii (black & white only), +ANSI (16 colors), ANSI Extended (256 colors), and TrueColor (24-bit RGB). Colors +will automatically be degraded to the best matching available color in the +desired profile: + +`TrueColor` => `ANSI 256 Colors` => `ANSI 16 Colors` => `Ascii` + +```go +s := output.String("Hello World") + +// Supports hex values +// Will automatically degrade colors on terminals not supporting RGB +s.Foreground(output.Color("#abcdef")) +// but also supports ANSI colors (0-255) +s.Background(output.Color("69")) +// ...or the color.Color interface +s.Foreground(output.FromColor(color.RGBA{255, 128, 0, 255})) + +// Combine fore- & background colors +s.Foreground(output.Color("#ffffff")).Background(output.Color("#0000ff")) + +// Supports the fmt.Stringer interface +fmt.Println(s) +``` + +## Styles + +You can use a chainable syntax to compose your own styles: + +```go +s := output.String("foobar") + +// Text styles +s.Bold() +s.Faint() +s.Italic() +s.CrossOut() +s.Underline() +s.Overline() + +// Reverse swaps current fore- & background colors +s.Reverse() + +// Blinking text +s.Blink() + +// Combine multiple options +s.Bold().Underline() +``` + +## Template Helpers + +`termenv` provides a set of helper functions to style your Go templates: + +```go +// load template helpers +f := output.TemplateFuncs() +tpl := template.New("tpl").Funcs(f) + +// apply bold style in a template +bold := `{{ Bold "Hello World" }}` + +// examples for colorized templates +col := `{{ Color "#ff0000" "#0000ff" "Red on Blue" }}` +fg := `{{ Foreground "#ff0000" "Red Foreground" }}` +bg := `{{ Background "#0000ff" "Blue Background" }}` + +// wrap styles +wrap := `{{ Bold (Underline "Hello World") }}` + +// parse and render +tpl, err = tpl.Parse(bold) + +var buf bytes.Buffer +tpl.Execute(&buf, nil) +fmt.Println(&buf) +``` + +Other available helper functions are: `Faint`, `Italic`, `CrossOut`, +`Underline`, `Overline`, `Reverse`, and `Blink`. + +## Positioning + +```go +// Move the cursor to a given position +output.MoveCursor(row, column) + +// Save the cursor position +output.SaveCursorPosition() + +// Restore a saved cursor position +output.RestoreCursorPosition() + +// Move the cursor up a given number of lines +output.CursorUp(n) + +// Move the cursor down a given number of lines +output.CursorDown(n) + +// Move the cursor up a given number of lines +output.CursorForward(n) + +// Move the cursor backwards a given number of cells +output.CursorBack(n) + +// Move the cursor down a given number of lines and place it at the beginning +// of the line +output.CursorNextLine(n) + +// Move the cursor up a given number of lines and place it at the beginning of +// the line +output.CursorPrevLine(n) +``` + +## Screen + +```go +// Reset the terminal to its default style, removing any active styles +output.Reset() + +// RestoreScreen restores a previously saved screen state +output.RestoreScreen() + +// SaveScreen saves the screen state +output.SaveScreen() + +// Switch to the altscreen. The former view can be restored with ExitAltScreen() +output.AltScreen() + +// Exit the altscreen and return to the former terminal view +output.ExitAltScreen() + +// Clear the visible portion of the terminal +output.ClearScreen() + +// Clear the current line +output.ClearLine() + +// Clear a given number of lines +output.ClearLines(n) + +// Set the scrolling region of the terminal +output.ChangeScrollingRegion(top, bottom) + +// Insert the given number of lines at the top of the scrollable region, pushing +// lines below down +output.InsertLines(n) + +// Delete the given number of lines, pulling any lines in the scrollable region +// below up +output.DeleteLines(n) +``` + +## Session + +```go +// SetWindowTitle sets the terminal window title +output.SetWindowTitle(title) + +// SetForegroundColor sets the default foreground color +output.SetForegroundColor(color) + +// SetBackgroundColor sets the default background color +output.SetBackgroundColor(color) + +// SetCursorColor sets the cursor color +output.SetCursorColor(color) + +// Hide the cursor +output.HideCursor() + +// Show the cursor +output.ShowCursor() + +// Copy to clipboard +output.Copy(message) + +// Copy to primary clipboard (X11) +output.CopyPrimary(message) + +// Trigger notification +output.Notify(title, body) +``` + +## Mouse + +```go +// Enable X10 mouse mode, only button press events are sent +output.EnableMousePress() + +// Disable X10 mouse mode +output.DisableMousePress() + +// Enable Mouse Tracking mode +output.EnableMouse() + +// Disable Mouse Tracking mode +output.DisableMouse() + +// Enable Hilite Mouse Tracking mode +output.EnableMouseHilite() + +// Disable Hilite Mouse Tracking mode +output.DisableMouseHilite() + +// Enable Cell Motion Mouse Tracking mode +output.EnableMouseCellMotion() + +// Disable Cell Motion Mouse Tracking mode +output.DisableMouseCellMotion() + +// Enable All Motion Mouse mode +output.EnableMouseAllMotion() + +// Disable All Motion Mouse mode +output.DisableMouseAllMotion() +``` + +## Bracketed Paste + +```go +// Enables bracketed paste mode +termenv.EnableBracketedPaste() + +// Disables bracketed paste mode +termenv.DisableBracketedPaste() +``` + +## Terminal Feature Support + +### Color Support + +- 24-bit (RGB): alacritty, foot, iTerm, kitty, Konsole, st, tmux, vte-based, wezterm, Ghostty, Windows Terminal +- 8-bit (256): rxvt, screen, xterm, Apple Terminal +- 4-bit (16): Linux Console + +### Control Sequences + +
+Click to show feature matrix + +| Terminal | Query Color Scheme | Query Cursor Position | Set Window Title | Change Cursor Color | Change Default Foreground Setting | Change Default Background Setting | Bracketed Paste | Extended Mouse (SGR) | Pixels Mouse (SGR-Pixels) | +| ---------------- | :----------------: | :-------------------: | :--------------: | :-----------------: | :-------------------------------: | :-------------------------------: | :-------------: | :------------------: | :-----------------------: | +| alacritty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| foot | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| kitty | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| Konsole | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | +| rxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | +| urxvt | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| screen | ⛔[^mux] | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | +| st | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| tmux | ⛔[^mux] | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| vte-based[^vte] | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ | +| wezterm | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| xterm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | +| Linux Console | ❌ | ✅ | ⛔ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| Apple Terminal | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | +| iTerm | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | +| Windows cmd | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | +| Windows Terminal | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | + +[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal. +[^mux]: Unavailable as multiplexers (like tmux or screen) can be connected to multiple terminals (with different color settings) at the same time. + +You can help improve this list! Check out [how to](ansi_compat.md) and open an issue or pull request. + +
+ +### System Commands + +
+Click to show feature matrix + +| Terminal | Copy to Clipboard (OSC52) | Hyperlinks (OSC8) | Notifications (OSC777) | +| ---------------- | :-----------------------: | :---------------: | :--------------------: | +| alacritty | ✅ | ✅[^alacritty] | ❌ | +| foot | ✅ | ✅ | ✅ | +| kitty | ✅ | ✅ | ✅ | +| Konsole | ❌[^konsole] | ✅ | ❌ | +| rxvt | ❌ | ❌ | ❌ | +| urxvt | ✅[^urxvt] | ❌ | ✅ | +| screen | ✅ | ❌[^screen] | ❌ | +| st | ✅ | ❌ | ❌ | +| tmux | ✅ | ❌[^tmux] | ❌ | +| vte-based[^vte] | ❌[^vte] | ✅ | ❌ | +| wezterm | ✅ | ✅ | ❌ | +| xterm | ✅ | ❌ | ❌ | +| Linux Console | ⛔ | ⛔ | ❌ | +| Apple Terminal | ✅[^apple] | ❌ | ❌ | +| iTerm | ✅ | ✅ | ❌ | +| Windows cmd | ❌ | ❌ | ❌ | +| Windows Terminal | ✅ | ✅ | ❌ | + +[^vte]: This covers all vte-based terminals, including Gnome Terminal, guake, Pantheon Terminal, Terminator, Tilix, XFCE Terminal. OSC52 is not supported, see [issue#2495](https://gitlab.gnome.org/GNOME/vte/-/issues/2495). +[^urxvt]: Workaround for urxvt not supporting OSC52. See [this](https://unix.stackexchange.com/a/629485) for more information. +[^konsole]: OSC52 is not supported, for more info see [bug#372116](https://bugs.kde.org/show_bug.cgi?id=372116). +[^apple]: OSC52 works with a [workaround](https://github.com/roy2220/osc52pty). +[^tmux]: OSC8 is not supported, for more info see [issue#911](https://github.com/tmux/tmux/issues/911). +[^screen]: OSC8 is not supported, for more info see [bug#50952](https://savannah.gnu.org/bugs/index.php?50952). +[^alacritty]: OSC8 is supported since [v0.11.0](https://github.com/alacritty/alacritty/releases/tag/v0.11.0) + +
+ +## Platform Support + +`termenv` works on Unix systems (like Linux, macOS, or BSD) and Windows. While +terminal applications on Unix support ANSI styling out-of-the-box, on Windows +you need to enable ANSI processing in your application first: + +```go + restoreConsole, err := termenv.EnableVirtualTerminalProcessing(termenv.DefaultOutput()) + if err != nil { + panic(err) + } + defer restoreConsole() +``` + +The above code is safe to include on non-Windows systems or when os.Stdout does +not refer to a terminal (e.g. in tests). + +## Color Chart + +![ANSI color chart](https://github.com/muesli/termenv/raw/master/examples/color-chart/color-chart.png) + +You can find the source code used to create this chart in `termenv`'s examples. + +## Related Projects + +- [reflow](https://github.com/muesli/reflow) - ANSI-aware text operations +- [Lip Gloss](https://github.com/charmbracelet/lipgloss) - style definitions for nice terminal layouts 👄 +- [ansi](https://github.com/muesli/ansi) - ANSI sequence helpers + +## termenv in the Wild + +Need some inspiration or just want to see how others are using `termenv`? Check +out these projects: + +- [Bubble Tea](https://github.com/charmbracelet/bubbletea) - a powerful little TUI framework 🏗 +- [Glamour](https://github.com/charmbracelet/glamour) - stylesheet-based markdown rendering for your CLI apps 💇🏻‍♀️ +- [Glow](https://github.com/charmbracelet/glow) - a markdown renderer for the command-line 💅🏻 +- [duf](https://github.com/muesli/duf) - Disk Usage/Free Utility - a better 'df' alternative +- [gitty](https://github.com/muesli/gitty) - contextual information about your git projects +- [slides](https://github.com/maaslalani/slides) - terminal-based presentation tool + +## Feedback + +Got some feedback or suggestions? Please open an issue or drop me a note! + +- [Twitter](https://twitter.com/mueslix) +- [The Fediverse](https://mastodon.social/@fribbledom) + +## License + +[MIT](https://github.com/muesli/termenv/raw/master/LICENSE) diff --git a/vendor/github.com/muesli/termenv/ansi_compat.md b/vendor/github.com/muesli/termenv/ansi_compat.md new file mode 100644 index 00000000..6b68a3a9 --- /dev/null +++ b/vendor/github.com/muesli/termenv/ansi_compat.md @@ -0,0 +1,65 @@ +## Change Foreground Color + +This command should enable a blue foreground color: + +```bash +echo -ne "\033]10;#0000ff\007" +``` + +## Change Background Color + +This command should enable a green background color: + +```bash +echo -ne "\033]11;#00ff00\007" +``` + +## Change Cursor Color + +This command should enable a red cursor color: + +```bash +echo -ne "\033]12;#ff0000\007" +``` + +## Query Color Scheme + +These two commands should print out the currently active color scheme: + +```bash +echo -ne "\033]10;?\033\\" +echo -ne "\033]11;?\033\\" +``` + +## Query Cursor Position + +This command should print out the current cursor position: + +```bash +echo -ne "\033[6n" +``` + +## Set Window Title + +This command should set the window title to "Test": + +```bash +echo -ne "\033]2;Test\007" && sleep 10 +``` + +## Bracketed paste + +Enter this command, then paste a word from the clipboard. The text +displayed on the terminal should contain the codes `200~` and `201~`: + +```bash +echo -ne "\033[?2004h" && sleep 10 +``` + +## Trigger Notification + +This command should trigger a notification: + +```bash +echo -ne "\033]777;notify;Title;Body\033\\" +``` diff --git a/vendor/github.com/muesli/termenv/ansicolors.go b/vendor/github.com/muesli/termenv/ansicolors.go new file mode 100644 index 00000000..1a301b0f --- /dev/null +++ b/vendor/github.com/muesli/termenv/ansicolors.go @@ -0,0 +1,281 @@ +package termenv + +// ANSI color codes. +const ( + ANSIBlack ANSIColor = iota + ANSIRed + ANSIGreen + ANSIYellow + ANSIBlue + ANSIMagenta + ANSICyan + ANSIWhite + ANSIBrightBlack + ANSIBrightRed + ANSIBrightGreen + ANSIBrightYellow + ANSIBrightBlue + ANSIBrightMagenta + ANSIBrightCyan + ANSIBrightWhite +) + +// RGB values of ANSI colors (0-255). +var ansiHex = []string{ + "#000000", + "#800000", + "#008000", + "#808000", + "#000080", + "#800080", + "#008080", + "#c0c0c0", + "#808080", + "#ff0000", + "#00ff00", + "#ffff00", + "#0000ff", + "#ff00ff", + "#00ffff", + "#ffffff", + "#000000", + "#00005f", + "#000087", + "#0000af", + "#0000d7", + "#0000ff", + "#005f00", + "#005f5f", + "#005f87", + "#005faf", + "#005fd7", + "#005fff", + "#008700", + "#00875f", + "#008787", + "#0087af", + "#0087d7", + "#0087ff", + "#00af00", + "#00af5f", + "#00af87", + "#00afaf", + "#00afd7", + "#00afff", + "#00d700", + "#00d75f", + "#00d787", + "#00d7af", + "#00d7d7", + "#00d7ff", + "#00ff00", + "#00ff5f", + "#00ff87", + "#00ffaf", + "#00ffd7", + "#00ffff", + "#5f0000", + "#5f005f", + "#5f0087", + "#5f00af", + "#5f00d7", + "#5f00ff", + "#5f5f00", + "#5f5f5f", + "#5f5f87", + "#5f5faf", + "#5f5fd7", + "#5f5fff", + "#5f8700", + "#5f875f", + "#5f8787", + "#5f87af", + "#5f87d7", + "#5f87ff", + "#5faf00", + "#5faf5f", + "#5faf87", + "#5fafaf", + "#5fafd7", + "#5fafff", + "#5fd700", + "#5fd75f", + "#5fd787", + "#5fd7af", + "#5fd7d7", + "#5fd7ff", + "#5fff00", + "#5fff5f", + "#5fff87", + "#5fffaf", + "#5fffd7", + "#5fffff", + "#870000", + "#87005f", + "#870087", + "#8700af", + "#8700d7", + "#8700ff", + "#875f00", + "#875f5f", + "#875f87", + "#875faf", + "#875fd7", + "#875fff", + "#878700", + "#87875f", + "#878787", + "#8787af", + "#8787d7", + "#8787ff", + "#87af00", + "#87af5f", + "#87af87", + "#87afaf", + "#87afd7", + "#87afff", + "#87d700", + "#87d75f", + "#87d787", + "#87d7af", + "#87d7d7", + "#87d7ff", + "#87ff00", + "#87ff5f", + "#87ff87", + "#87ffaf", + "#87ffd7", + "#87ffff", + "#af0000", + "#af005f", + "#af0087", + "#af00af", + "#af00d7", + "#af00ff", + "#af5f00", + "#af5f5f", + "#af5f87", + "#af5faf", + "#af5fd7", + "#af5fff", + "#af8700", + "#af875f", + "#af8787", + "#af87af", + "#af87d7", + "#af87ff", + "#afaf00", + "#afaf5f", + "#afaf87", + "#afafaf", + "#afafd7", + "#afafff", + "#afd700", + "#afd75f", + "#afd787", + "#afd7af", + "#afd7d7", + "#afd7ff", + "#afff00", + "#afff5f", + "#afff87", + "#afffaf", + "#afffd7", + "#afffff", + "#d70000", + "#d7005f", + "#d70087", + "#d700af", + "#d700d7", + "#d700ff", + "#d75f00", + "#d75f5f", + "#d75f87", + "#d75faf", + "#d75fd7", + "#d75fff", + "#d78700", + "#d7875f", + "#d78787", + "#d787af", + "#d787d7", + "#d787ff", + "#d7af00", + "#d7af5f", + "#d7af87", + "#d7afaf", + "#d7afd7", + "#d7afff", + "#d7d700", + "#d7d75f", + "#d7d787", + "#d7d7af", + "#d7d7d7", + "#d7d7ff", + "#d7ff00", + "#d7ff5f", + "#d7ff87", + "#d7ffaf", + "#d7ffd7", + "#d7ffff", + "#ff0000", + "#ff005f", + "#ff0087", + "#ff00af", + "#ff00d7", + "#ff00ff", + "#ff5f00", + "#ff5f5f", + "#ff5f87", + "#ff5faf", + "#ff5fd7", + "#ff5fff", + "#ff8700", + "#ff875f", + "#ff8787", + "#ff87af", + "#ff87d7", + "#ff87ff", + "#ffaf00", + "#ffaf5f", + "#ffaf87", + "#ffafaf", + "#ffafd7", + "#ffafff", + "#ffd700", + "#ffd75f", + "#ffd787", + "#ffd7af", + "#ffd7d7", + "#ffd7ff", + "#ffff00", + "#ffff5f", + "#ffff87", + "#ffffaf", + "#ffffd7", + "#ffffff", + "#080808", + "#121212", + "#1c1c1c", + "#262626", + "#303030", + "#3a3a3a", + "#444444", + "#4e4e4e", + "#585858", + "#626262", + "#6c6c6c", + "#767676", + "#808080", + "#8a8a8a", + "#949494", + "#9e9e9e", + "#a8a8a8", + "#b2b2b2", + "#bcbcbc", + "#c6c6c6", + "#d0d0d0", + "#dadada", + "#e4e4e4", + "#eeeeee", +} diff --git a/vendor/github.com/muesli/termenv/color.go b/vendor/github.com/muesli/termenv/color.go new file mode 100644 index 00000000..59e639b1 --- /dev/null +++ b/vendor/github.com/muesli/termenv/color.go @@ -0,0 +1,205 @@ +package termenv + +import ( + "errors" + "fmt" + "math" + "strings" + + "github.com/lucasb-eyer/go-colorful" +) + +// ErrInvalidColor gets returned when a color is invalid. +var ErrInvalidColor = errors.New("invalid color") + +// Foreground and Background sequence codes. +const ( + Foreground = "38" + Background = "48" +) + +// Color is an interface implemented by all colors that can be converted to an +// ANSI sequence. +type Color interface { + // Sequence returns the ANSI Sequence for the color. + Sequence(bg bool) string +} + +// NoColor is a nop for terminals that don't support colors. +type NoColor struct{} + +func (c NoColor) String() string { + return "" +} + +// ANSIColor is a color (0-15) as defined by the ANSI Standard. +type ANSIColor int + +func (c ANSIColor) String() string { + return ansiHex[c] +} + +// ANSI256Color is a color (16-255) as defined by the ANSI Standard. +type ANSI256Color int + +func (c ANSI256Color) String() string { + return ansiHex[c] +} + +// RGBColor is a hex-encoded color, e.g. "#abcdef". +type RGBColor string + +// ConvertToRGB converts a Color to a colorful.Color. +func ConvertToRGB(c Color) colorful.Color { + var hex string + switch v := c.(type) { + case RGBColor: + hex = string(v) + case ANSIColor: + hex = ansiHex[v] + case ANSI256Color: + hex = ansiHex[v] + } + + ch, _ := colorful.Hex(hex) + return ch +} + +// Sequence returns the ANSI Sequence for the color. +func (c NoColor) Sequence(_ bool) string { + return "" +} + +// Sequence returns the ANSI Sequence for the color. +// +//nolint:mnd +func (c ANSIColor) Sequence(bg bool) string { + col := int(c) + bgMod := func(c int) int { + if bg { + return c + 10 + } + return c + } + + if col < 8 { + return fmt.Sprintf("%d", bgMod(col)+30) //nolint:mnd + } + return fmt.Sprintf("%d", bgMod(col-8)+90) //nolint:mnd +} + +// Sequence returns the ANSI Sequence for the color. +func (c ANSI256Color) Sequence(bg bool) string { + prefix := Foreground + if bg { + prefix = Background + } + return fmt.Sprintf("%s;5;%d", prefix, c) +} + +// Sequence returns the ANSI Sequence for the color. +func (c RGBColor) Sequence(bg bool) string { + f, err := colorful.Hex(string(c)) + if err != nil { + return "" + } + + prefix := Foreground + if bg { + prefix = Background + } + return fmt.Sprintf("%s;2;%d;%d;%d", prefix, uint8(f.R*255), uint8(f.G*255), uint8(f.B*255)) //nolint:mnd +} + +func xTermColor(s string) (RGBColor, error) { + if len(s) < 24 || len(s) > 25 { + return RGBColor(""), ErrInvalidColor + } + + switch { + case strings.HasSuffix(s, string(BEL)): + s = strings.TrimSuffix(s, string(BEL)) + case strings.HasSuffix(s, string(ESC)): + s = strings.TrimSuffix(s, string(ESC)) + case strings.HasSuffix(s, ST): + s = strings.TrimSuffix(s, ST) + default: + return RGBColor(""), ErrInvalidColor + } + + s = s[4:] + + prefix := ";rgb:" + if !strings.HasPrefix(s, prefix) { + return RGBColor(""), ErrInvalidColor + } + s = strings.TrimPrefix(s, prefix) + + h := strings.Split(s, "/") + hex := fmt.Sprintf("#%s%s%s", h[0][:2], h[1][:2], h[2][:2]) + return RGBColor(hex), nil +} + +func ansi256ToANSIColor(c ANSI256Color) ANSIColor { + var r int + md := math.MaxFloat64 + + h, _ := colorful.Hex(ansiHex[c]) + for i := 0; i <= 15; i++ { + hb, _ := colorful.Hex(ansiHex[i]) + d := h.DistanceHSLuv(hb) + + if d < md { + md = d + r = i + } + } + + return ANSIColor(r) +} + +//nolint:mnd +func hexToANSI256Color(c colorful.Color) ANSI256Color { + v2ci := func(v float64) int { + if v < 48 { + return 0 + } + if v < 115 { + return 1 + } + return int((v - 35) / 40) + } + + // Calculate the nearest 0-based color index at 16..231 + r := v2ci(c.R * 255.0) // 0..5 each + g := v2ci(c.G * 255.0) + b := v2ci(c.B * 255.0) + ci := 36*r + 6*g + b /* 0..215 */ + + // Calculate the represented colors back from the index + i2cv := [6]int{0, 0x5f, 0x87, 0xaf, 0xd7, 0xff} + cr := i2cv[r] // r/g/b, 0..255 each + cg := i2cv[g] + cb := i2cv[b] + + // Calculate the nearest 0-based gray index at 232..255 + var grayIdx int + average := (r + g + b) / 3 + if average > 238 { + grayIdx = 23 + } else { + grayIdx = (average - 3) / 10 // 0..23 + } + gv := 8 + 10*grayIdx // same value for r/g/b, 0..255 + + // Return the one which is nearer to the original input rgb value + c2 := colorful.Color{R: float64(cr) / 255.0, G: float64(cg) / 255.0, B: float64(cb) / 255.0} + g2 := colorful.Color{R: float64(gv) / 255.0, G: float64(gv) / 255.0, B: float64(gv) / 255.0} + colorDist := c.DistanceHSLuv(c2) + grayDist := c.DistanceHSLuv(g2) + + if colorDist <= grayDist { + return ANSI256Color(16 + ci) + } + return ANSI256Color(232 + grayIdx) +} diff --git a/vendor/github.com/muesli/termenv/constants_linux.go b/vendor/github.com/muesli/termenv/constants_linux.go new file mode 100644 index 00000000..4262f03b --- /dev/null +++ b/vendor/github.com/muesli/termenv/constants_linux.go @@ -0,0 +1,8 @@ +package termenv + +import "golang.org/x/sys/unix" + +const ( + tcgetattr = unix.TCGETS + tcsetattr = unix.TCSETS +) diff --git a/vendor/github.com/muesli/termenv/constants_solaris.go b/vendor/github.com/muesli/termenv/constants_solaris.go new file mode 100644 index 00000000..4262f03b --- /dev/null +++ b/vendor/github.com/muesli/termenv/constants_solaris.go @@ -0,0 +1,8 @@ +package termenv + +import "golang.org/x/sys/unix" + +const ( + tcgetattr = unix.TCGETS + tcsetattr = unix.TCSETS +) diff --git a/vendor/github.com/muesli/termenv/constants_unix.go b/vendor/github.com/muesli/termenv/constants_unix.go new file mode 100644 index 00000000..5d664245 --- /dev/null +++ b/vendor/github.com/muesli/termenv/constants_unix.go @@ -0,0 +1,13 @@ +//go:build (darwin || dragonfly || freebsd || netbsd || openbsd) && !solaris && !illumos +// +build darwin dragonfly freebsd netbsd openbsd +// +build !solaris +// +build !illumos + +package termenv + +import "golang.org/x/sys/unix" + +const ( + tcgetattr = unix.TIOCGETA + tcsetattr = unix.TIOCSETA +) diff --git a/vendor/github.com/muesli/termenv/constants_zos.go b/vendor/github.com/muesli/termenv/constants_zos.go new file mode 100644 index 00000000..4262f03b --- /dev/null +++ b/vendor/github.com/muesli/termenv/constants_zos.go @@ -0,0 +1,8 @@ +package termenv + +import "golang.org/x/sys/unix" + +const ( + tcgetattr = unix.TCGETS + tcsetattr = unix.TCSETS +) diff --git a/vendor/github.com/muesli/termenv/copy.go b/vendor/github.com/muesli/termenv/copy.go new file mode 100644 index 00000000..4bf5c9fe --- /dev/null +++ b/vendor/github.com/muesli/termenv/copy.go @@ -0,0 +1,37 @@ +package termenv + +import ( + "strings" + + "github.com/aymanbagabas/go-osc52/v2" +) + +// Copy copies text to clipboard using OSC 52 escape sequence. +func (o Output) Copy(str string) { + s := osc52.New(str) + if strings.HasPrefix(o.environ.Getenv("TERM"), "screen") { + s = s.Screen() + } + _, _ = s.WriteTo(o) +} + +// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape +// sequence. +func (o Output) CopyPrimary(str string) { + s := osc52.New(str).Primary() + if strings.HasPrefix(o.environ.Getenv("TERM"), "screen") { + s = s.Screen() + } + _, _ = s.WriteTo(o) +} + +// Copy copies text to clipboard using OSC 52 escape sequence. +func Copy(str string) { + output.Copy(str) +} + +// CopyPrimary copies text to primary clipboard (X11) using OSC 52 escape +// sequence. +func CopyPrimary(str string) { + output.CopyPrimary(str) +} diff --git a/vendor/github.com/muesli/termenv/hyperlink.go b/vendor/github.com/muesli/termenv/hyperlink.go new file mode 100644 index 00000000..97e760a3 --- /dev/null +++ b/vendor/github.com/muesli/termenv/hyperlink.go @@ -0,0 +1,11 @@ +package termenv + +// Hyperlink creates a hyperlink using OSC8. +func Hyperlink(link, name string) string { + return output.Hyperlink(link, name) +} + +// Hyperlink creates a hyperlink using OSC8. +func (o *Output) Hyperlink(link, name string) string { + return OSC + "8;;" + link + ST + name + OSC + "8;;" + ST +} diff --git a/vendor/github.com/muesli/termenv/notification.go b/vendor/github.com/muesli/termenv/notification.go new file mode 100644 index 00000000..2a8cf06a --- /dev/null +++ b/vendor/github.com/muesli/termenv/notification.go @@ -0,0 +1,11 @@ +package termenv + +// Notify triggers a notification using OSC777. +func Notify(title, body string) { + output.Notify(title, body) +} + +// Notify triggers a notification using OSC777. +func (o *Output) Notify(title, body string) { + _, _ = o.WriteString(OSC + "777;notify;" + title + ";" + body + ST) +} diff --git a/vendor/github.com/muesli/termenv/output.go b/vendor/github.com/muesli/termenv/output.go new file mode 100644 index 00000000..e4434de0 --- /dev/null +++ b/vendor/github.com/muesli/termenv/output.go @@ -0,0 +1,205 @@ +package termenv + +import ( + "io" + "os" + "sync" +) + +// output is the default global output. +var output = NewOutput(os.Stdout) + +// File represents a file descriptor. +// +// Deprecated: Use *os.File instead. +type File interface { + io.ReadWriter + Fd() uintptr +} + +// OutputOption sets an option on Output. +type OutputOption = func(*Output) + +// Output is a terminal output. +type Output struct { + Profile + w io.Writer + environ Environ + + assumeTTY bool + unsafe bool + cache bool + fgSync *sync.Once + fgColor Color + bgSync *sync.Once + bgColor Color +} + +// Environ is an interface for getting environment variables. +type Environ interface { + Environ() []string + Getenv(string) string +} + +type osEnviron struct{} + +func (oe *osEnviron) Environ() []string { + return os.Environ() +} + +func (oe *osEnviron) Getenv(key string) string { + return os.Getenv(key) +} + +// DefaultOutput returns the default global output. +func DefaultOutput() *Output { + return output +} + +// SetDefaultOutput sets the default global output. +func SetDefaultOutput(o *Output) { + output = o +} + +// NewOutput returns a new Output for the given writer. +func NewOutput(w io.Writer, opts ...OutputOption) *Output { + o := &Output{ + w: w, + environ: &osEnviron{}, + Profile: -1, + fgSync: &sync.Once{}, + fgColor: NoColor{}, + bgSync: &sync.Once{}, + bgColor: NoColor{}, + } + + if o.w == nil { + o.w = os.Stdout + } + for _, opt := range opts { + opt(o) + } + if o.Profile < 0 { + o.Profile = o.EnvColorProfile() + } + + return o +} + +// WithEnvironment returns a new OutputOption for the given environment. +func WithEnvironment(environ Environ) OutputOption { + return func(o *Output) { + o.environ = environ + } +} + +// WithProfile returns a new OutputOption for the given profile. +func WithProfile(profile Profile) OutputOption { + return func(o *Output) { + o.Profile = profile + } +} + +// WithColorCache returns a new OutputOption with fore- and background color values +// pre-fetched and cached. +func WithColorCache(v bool) OutputOption { + return func(o *Output) { + o.cache = v + + // cache the values now + _ = o.ForegroundColor() + _ = o.BackgroundColor() + } +} + +// WithTTY returns a new OutputOption to assume whether or not the output is a TTY. +// This is useful when mocking console output. +func WithTTY(v bool) OutputOption { + return func(o *Output) { + o.assumeTTY = v + } +} + +// WithUnsafe returns a new OutputOption with unsafe mode enabled. Unsafe mode doesn't +// check whether or not the terminal is a TTY. +// +// This option supersedes WithTTY. +// +// This is useful when mocking console output and enforcing ANSI escape output +// e.g. on SSH sessions. +func WithUnsafe() OutputOption { + return func(o *Output) { + o.unsafe = true + } +} + +// ForegroundColor returns the terminal's default foreground color. +func (o *Output) ForegroundColor() Color { + f := func() { + if !o.isTTY() { + return + } + + o.fgColor = o.foregroundColor() + } + + if o.cache { + o.fgSync.Do(f) + } else { + f() + } + + return o.fgColor +} + +// BackgroundColor returns the terminal's default background color. +func (o *Output) BackgroundColor() Color { + f := func() { + if !o.isTTY() { + return + } + + o.bgColor = o.backgroundColor() + } + + if o.cache { + o.bgSync.Do(f) + } else { + f() + } + + return o.bgColor +} + +// HasDarkBackground returns whether terminal uses a dark-ish background. +func (o *Output) HasDarkBackground() bool { + c := ConvertToRGB(o.BackgroundColor()) + _, _, l := c.Hsl() + return l < 0.5 //nolint:mnd +} + +// TTY returns the terminal's file descriptor. This may be nil if the output is +// not a terminal. +// +// Deprecated: Use Writer() instead. +func (o Output) TTY() File { + if f, ok := o.w.(File); ok { + return f + } + return nil +} + +// Writer returns the underlying writer. This may be of type io.Writer, +// io.ReadWriter, or *os.File. +func (o Output) Writer() io.Writer { + return o.w +} + +func (o Output) Write(p []byte) (int, error) { + return o.w.Write(p) //nolint:wrapcheck +} + +// WriteString writes the given string to the output. +func (o Output) WriteString(s string) (int, error) { + return o.Write([]byte(s)) +} diff --git a/vendor/github.com/muesli/termenv/profile.go b/vendor/github.com/muesli/termenv/profile.go new file mode 100644 index 00000000..7d38f5fb --- /dev/null +++ b/vendor/github.com/muesli/termenv/profile.go @@ -0,0 +1,112 @@ +package termenv + +import ( + "image/color" + "strconv" + "strings" + + "github.com/lucasb-eyer/go-colorful" +) + +// Profile is a color profile: Ascii, ANSI, ANSI256, or TrueColor. +type Profile int + +const ( + // TrueColor, 24-bit color profile. + TrueColor = Profile(iota) + // ANSI256, 8-bit color profile. + ANSI256 + // ANSI, 4-bit color profile. + ANSI + // Ascii, uncolored profile. + Ascii //nolint:revive +) + +// Name returns the profile name as a string. +func (p Profile) Name() string { + switch p { + case Ascii: + return "Ascii" + case ANSI: + return "ANSI" + case ANSI256: + return "ANSI256" + case TrueColor: + return "TrueColor" + } + return "Unknown" +} + +// String returns a new Style. +func (p Profile) String(s ...string) Style { + return Style{ + profile: p, + string: strings.Join(s, " "), + } +} + +// Convert transforms a given Color to a Color supported within the Profile. +func (p Profile) Convert(c Color) Color { + if p == Ascii { + return NoColor{} + } + + switch v := c.(type) { + case ANSIColor: + return v + + case ANSI256Color: + if p == ANSI { + return ansi256ToANSIColor(v) + } + return v + + case RGBColor: + h, err := colorful.Hex(string(v)) + if err != nil { + return nil + } + if p != TrueColor { + ac := hexToANSI256Color(h) + if p == ANSI { + return ansi256ToANSIColor(ac) + } + return ac + } + return v + } + + return c +} + +// Color creates a Color from a string. Valid inputs are hex colors, as well as +// ANSI color codes (0-15, 16-255). +func (p Profile) Color(s string) Color { + if len(s) == 0 { + return nil + } + + var c Color + if strings.HasPrefix(s, "#") { + c = RGBColor(s) + } else { + i, err := strconv.Atoi(s) + if err != nil { + return nil + } + + if i < 16 { //nolint:mnd + c = ANSIColor(i) + } else { + c = ANSI256Color(i) + } + } + + return p.Convert(c) +} + +// FromColor creates a Color from a color.Color. +func (p Profile) FromColor(c color.Color) Color { + col, _ := colorful.MakeColor(c) + return p.Color(col.Hex()) +} diff --git a/vendor/github.com/muesli/termenv/screen.go b/vendor/github.com/muesli/termenv/screen.go new file mode 100644 index 00000000..75c11d01 --- /dev/null +++ b/vendor/github.com/muesli/termenv/screen.go @@ -0,0 +1,590 @@ +package termenv + +import ( + "fmt" + "strings" +) + +// Sequence definitions. +const ( + // Cursor positioning. + CursorUpSeq = "%dA" + CursorDownSeq = "%dB" + CursorForwardSeq = "%dC" + CursorBackSeq = "%dD" + CursorNextLineSeq = "%dE" + CursorPreviousLineSeq = "%dF" + CursorHorizontalSeq = "%dG" + CursorPositionSeq = "%d;%dH" + EraseDisplaySeq = "%dJ" + EraseLineSeq = "%dK" + ScrollUpSeq = "%dS" + ScrollDownSeq = "%dT" + SaveCursorPositionSeq = "s" + RestoreCursorPositionSeq = "u" + ChangeScrollingRegionSeq = "%d;%dr" + InsertLineSeq = "%dL" + DeleteLineSeq = "%dM" + + // Explicit values for EraseLineSeq. + EraseLineRightSeq = "0K" + EraseLineLeftSeq = "1K" + EraseEntireLineSeq = "2K" + + // Mouse. + EnableMousePressSeq = "?9h" // press only (X10) + DisableMousePressSeq = "?9l" + EnableMouseSeq = "?1000h" // press, release, wheel + DisableMouseSeq = "?1000l" + EnableMouseHiliteSeq = "?1001h" // highlight + DisableMouseHiliteSeq = "?1001l" + EnableMouseCellMotionSeq = "?1002h" // press, release, move on pressed, wheel + DisableMouseCellMotionSeq = "?1002l" + EnableMouseAllMotionSeq = "?1003h" // press, release, move, wheel + DisableMouseAllMotionSeq = "?1003l" + EnableMouseExtendedModeSeq = "?1006h" // press, release, move, wheel, extended coordinates + DisableMouseExtendedModeSeq = "?1006l" + EnableMousePixelsModeSeq = "?1016h" // press, release, move, wheel, extended pixel coordinates + DisableMousePixelsModeSeq = "?1016l" + + // Screen. + RestoreScreenSeq = "?47l" + SaveScreenSeq = "?47h" + AltScreenSeq = "?1049h" + ExitAltScreenSeq = "?1049l" + + // Bracketed paste. + // https://en.wikipedia.org/wiki/Bracketed-paste + EnableBracketedPasteSeq = "?2004h" + DisableBracketedPasteSeq = "?2004l" + StartBracketedPasteSeq = "200~" + EndBracketedPasteSeq = "201~" + + // Session. + SetWindowTitleSeq = "2;%s" + string(BEL) + SetForegroundColorSeq = "10;%s" + string(BEL) + SetBackgroundColorSeq = "11;%s" + string(BEL) + SetCursorColorSeq = "12;%s" + string(BEL) + ShowCursorSeq = "?25h" + HideCursorSeq = "?25l" +) + +// Reset the terminal to its default style, removing any active styles. +func (o Output) Reset() { + fmt.Fprint(o.w, CSI+ResetSeq+"m") //nolint:errcheck +} + +// SetForegroundColor sets the default foreground color. +func (o Output) SetForegroundColor(color Color) { + fmt.Fprintf(o.w, OSC+SetForegroundColorSeq, color) //nolint:errcheck +} + +// SetBackgroundColor sets the default background color. +func (o Output) SetBackgroundColor(color Color) { + fmt.Fprintf(o.w, OSC+SetBackgroundColorSeq, color) //nolint:errcheck +} + +// SetCursorColor sets the cursor color. +func (o Output) SetCursorColor(color Color) { + fmt.Fprintf(o.w, OSC+SetCursorColorSeq, color) //nolint:errcheck +} + +// RestoreScreen restores a previously saved screen state. +func (o Output) RestoreScreen() { + fmt.Fprint(o.w, CSI+RestoreScreenSeq) //nolint:errcheck +} + +// SaveScreen saves the screen state. +func (o Output) SaveScreen() { + fmt.Fprint(o.w, CSI+SaveScreenSeq) //nolint:errcheck +} + +// AltScreen switches to the alternate screen buffer. The former view can be +// restored with ExitAltScreen(). +func (o Output) AltScreen() { + fmt.Fprint(o.w, CSI+AltScreenSeq) //nolint:errcheck +} + +// ExitAltScreen exits the alternate screen buffer and returns to the former +// terminal view. +func (o Output) ExitAltScreen() { + fmt.Fprint(o.w, CSI+ExitAltScreenSeq) //nolint:errcheck +} + +// ClearScreen clears the visible portion of the terminal. +func (o Output) ClearScreen() { + fmt.Fprintf(o.w, CSI+EraseDisplaySeq, 2) //nolint:errcheck,mnd + o.MoveCursor(1, 1) +} + +// MoveCursor moves the cursor to a given position. +func (o Output) MoveCursor(row int, column int) { + fmt.Fprintf(o.w, CSI+CursorPositionSeq, row, column) //nolint:errcheck +} + +// HideCursor hides the cursor. +func (o Output) HideCursor() { + fmt.Fprint(o.w, CSI+HideCursorSeq) //nolint:errcheck +} + +// ShowCursor shows the cursor. +func (o Output) ShowCursor() { + fmt.Fprint(o.w, CSI+ShowCursorSeq) //nolint:errcheck +} + +// SaveCursorPosition saves the cursor position. +func (o Output) SaveCursorPosition() { + fmt.Fprint(o.w, CSI+SaveCursorPositionSeq) //nolint:errcheck +} + +// RestoreCursorPosition restores a saved cursor position. +func (o Output) RestoreCursorPosition() { + fmt.Fprint(o.w, CSI+RestoreCursorPositionSeq) //nolint:errcheck +} + +// CursorUp moves the cursor up a given number of lines. +func (o Output) CursorUp(n int) { + fmt.Fprintf(o.w, CSI+CursorUpSeq, n) //nolint:errcheck +} + +// CursorDown moves the cursor down a given number of lines. +func (o Output) CursorDown(n int) { + fmt.Fprintf(o.w, CSI+CursorDownSeq, n) //nolint:errcheck +} + +// CursorForward moves the cursor up a given number of lines. +func (o Output) CursorForward(n int) { + fmt.Fprintf(o.w, CSI+CursorForwardSeq, n) //nolint:errcheck +} + +// CursorBack moves the cursor backwards a given number of cells. +func (o Output) CursorBack(n int) { + fmt.Fprintf(o.w, CSI+CursorBackSeq, n) //nolint:errcheck +} + +// CursorNextLine moves the cursor down a given number of lines and places it at +// the beginning of the line. +func (o Output) CursorNextLine(n int) { + fmt.Fprintf(o.w, CSI+CursorNextLineSeq, n) //nolint:errcheck +} + +// CursorPrevLine moves the cursor up a given number of lines and places it at +// the beginning of the line. +func (o Output) CursorPrevLine(n int) { + fmt.Fprintf(o.w, CSI+CursorPreviousLineSeq, n) //nolint:errcheck +} + +// ClearLine clears the current line. +func (o Output) ClearLine() { + fmt.Fprint(o.w, CSI+EraseEntireLineSeq) //nolint:errcheck +} + +// ClearLineLeft clears the line to the left of the cursor. +func (o Output) ClearLineLeft() { + fmt.Fprint(o.w, CSI+EraseLineLeftSeq) //nolint:errcheck +} + +// ClearLineRight clears the line to the right of the cursor. +func (o Output) ClearLineRight() { + fmt.Fprint(o.w, CSI+EraseLineRightSeq) //nolint:errcheck +} + +// ClearLines clears a given number of lines. +func (o Output) ClearLines(n int) { + clearLine := fmt.Sprintf(CSI+EraseLineSeq, 2) //nolint:mnd + cursorUp := fmt.Sprintf(CSI+CursorUpSeq, 1) + fmt.Fprint(o.w, clearLine+strings.Repeat(cursorUp+clearLine, n)) //nolint:errcheck +} + +// ChangeScrollingRegion sets the scrolling region of the terminal. +func (o Output) ChangeScrollingRegion(top, bottom int) { + fmt.Fprintf(o.w, CSI+ChangeScrollingRegionSeq, top, bottom) //nolint:errcheck +} + +// InsertLines inserts the given number of lines at the top of the scrollable +// region, pushing lines below down. +func (o Output) InsertLines(n int) { + fmt.Fprintf(o.w, CSI+InsertLineSeq, n) //nolint:errcheck +} + +// DeleteLines deletes the given number of lines, pulling any lines in +// the scrollable region below up. +func (o Output) DeleteLines(n int) { + fmt.Fprintf(o.w, CSI+DeleteLineSeq, n) //nolint:errcheck +} + +// EnableMousePress enables X10 mouse mode. Button press events are sent only. +func (o Output) EnableMousePress() { + fmt.Fprint(o.w, CSI+EnableMousePressSeq) //nolint:errcheck +} + +// DisableMousePress disables X10 mouse mode. +func (o Output) DisableMousePress() { + fmt.Fprint(o.w, CSI+DisableMousePressSeq) //nolint:errcheck +} + +// EnableMouse enables Mouse Tracking mode. +func (o Output) EnableMouse() { + fmt.Fprint(o.w, CSI+EnableMouseSeq) //nolint:errcheck +} + +// DisableMouse disables Mouse Tracking mode. +func (o Output) DisableMouse() { + fmt.Fprint(o.w, CSI+DisableMouseSeq) //nolint:errcheck +} + +// EnableMouseHilite enables Hilite Mouse Tracking mode. +func (o Output) EnableMouseHilite() { + fmt.Fprint(o.w, CSI+EnableMouseHiliteSeq) //nolint:errcheck +} + +// DisableMouseHilite disables Hilite Mouse Tracking mode. +func (o Output) DisableMouseHilite() { + fmt.Fprint(o.w, CSI+DisableMouseHiliteSeq) //nolint:errcheck +} + +// EnableMouseCellMotion enables Cell Motion Mouse Tracking mode. +func (o Output) EnableMouseCellMotion() { + fmt.Fprint(o.w, CSI+EnableMouseCellMotionSeq) //nolint:errcheck +} + +// DisableMouseCellMotion disables Cell Motion Mouse Tracking mode. +func (o Output) DisableMouseCellMotion() { + fmt.Fprint(o.w, CSI+DisableMouseCellMotionSeq) //nolint:errcheck +} + +// EnableMouseAllMotion enables All Motion Mouse mode. +func (o Output) EnableMouseAllMotion() { + fmt.Fprint(o.w, CSI+EnableMouseAllMotionSeq) //nolint:errcheck +} + +// DisableMouseAllMotion disables All Motion Mouse mode. +func (o Output) DisableMouseAllMotion() { + fmt.Fprint(o.w, CSI+DisableMouseAllMotionSeq) //nolint:errcheck +} + +// EnableMouseExtendedMotion enables Extended Mouse mode (SGR). This should be +// enabled in conjunction with EnableMouseCellMotion, and EnableMouseAllMotion. +func (o Output) EnableMouseExtendedMode() { + fmt.Fprint(o.w, CSI+EnableMouseExtendedModeSeq) //nolint:errcheck +} + +// DisableMouseExtendedMotion disables Extended Mouse mode (SGR). +func (o Output) DisableMouseExtendedMode() { + fmt.Fprint(o.w, CSI+DisableMouseExtendedModeSeq) //nolint:errcheck +} + +// EnableMousePixelsMotion enables Pixel Motion Mouse mode (SGR-Pixels). This +// should be enabled in conjunction with EnableMouseCellMotion, and +// EnableMouseAllMotion. +func (o Output) EnableMousePixelsMode() { + fmt.Fprint(o.w, CSI+EnableMousePixelsModeSeq) //nolint:errcheck +} + +// DisableMousePixelsMotion disables Pixel Motion Mouse mode (SGR-Pixels). +func (o Output) DisableMousePixelsMode() { + fmt.Fprint(o.w, CSI+DisableMousePixelsModeSeq) //nolint:errcheck +} + +// SetWindowTitle sets the terminal window title. +func (o Output) SetWindowTitle(title string) { + fmt.Fprintf(o.w, OSC+SetWindowTitleSeq, title) //nolint:errcheck +} + +// EnableBracketedPaste enables bracketed paste. +func (o Output) EnableBracketedPaste() { + fmt.Fprintf(o.w, CSI+EnableBracketedPasteSeq) //nolint:errcheck +} + +// DisableBracketedPaste disables bracketed paste. +func (o Output) DisableBracketedPaste() { + fmt.Fprintf(o.w, CSI+DisableBracketedPasteSeq) //nolint:errcheck +} + +// Legacy functions. + +// Reset the terminal to its default style, removing any active styles. +// +// Deprecated: please use termenv.Output instead. +func Reset() { + output.Reset() +} + +// SetForegroundColor sets the default foreground color. +// +// Deprecated: please use termenv.Output instead. +func SetForegroundColor(color Color) { + output.SetForegroundColor(color) +} + +// SetBackgroundColor sets the default background color. +// +// Deprecated: please use termenv.Output instead. +func SetBackgroundColor(color Color) { + output.SetBackgroundColor(color) +} + +// SetCursorColor sets the cursor color. +// +// Deprecated: please use termenv.Output instead. +func SetCursorColor(color Color) { + output.SetCursorColor(color) +} + +// RestoreScreen restores a previously saved screen state. +// +// Deprecated: please use termenv.Output instead. +func RestoreScreen() { + output.RestoreScreen() +} + +// SaveScreen saves the screen state. +// +// Deprecated: please use termenv.Output instead. +func SaveScreen() { + output.SaveScreen() +} + +// AltScreen switches to the alternate screen buffer. The former view can be +// restored with ExitAltScreen(). +// +// Deprecated: please use termenv.Output instead. +func AltScreen() { + output.AltScreen() +} + +// ExitAltScreen exits the alternate screen buffer and returns to the former +// terminal view. +// +// Deprecated: please use termenv.Output instead. +func ExitAltScreen() { + output.ExitAltScreen() +} + +// ClearScreen clears the visible portion of the terminal. +// +// Deprecated: please use termenv.Output instead. +func ClearScreen() { + output.ClearScreen() +} + +// MoveCursor moves the cursor to a given position. +// +// Deprecated: please use termenv.Output instead. +func MoveCursor(row int, column int) { + output.MoveCursor(row, column) +} + +// HideCursor hides the cursor. +// +// Deprecated: please use termenv.Output instead. +func HideCursor() { + output.HideCursor() +} + +// ShowCursor shows the cursor. +// +// Deprecated: please use termenv.Output instead. +func ShowCursor() { + output.ShowCursor() +} + +// SaveCursorPosition saves the cursor position. +// +// Deprecated: please use termenv.Output instead. +func SaveCursorPosition() { + output.SaveCursorPosition() +} + +// RestoreCursorPosition restores a saved cursor position. +// +// Deprecated: please use termenv.Output instead. +func RestoreCursorPosition() { + output.RestoreCursorPosition() +} + +// CursorUp moves the cursor up a given number of lines. +// +// Deprecated: please use termenv.Output instead. +func CursorUp(n int) { + output.CursorUp(n) +} + +// CursorDown moves the cursor down a given number of lines. +// +// Deprecated: please use termenv.Output instead. +func CursorDown(n int) { + output.CursorDown(n) +} + +// CursorForward moves the cursor up a given number of lines. +// +// Deprecated: please use termenv.Output instead. +func CursorForward(n int) { + output.CursorForward(n) +} + +// CursorBack moves the cursor backwards a given number of cells. +// +// Deprecated: please use termenv.Output instead. +func CursorBack(n int) { + output.CursorBack(n) +} + +// CursorNextLine moves the cursor down a given number of lines and places it at +// the beginning of the line. +// +// Deprecated: please use termenv.Output instead. +func CursorNextLine(n int) { + output.CursorNextLine(n) +} + +// CursorPrevLine moves the cursor up a given number of lines and places it at +// the beginning of the line. +// +// Deprecated: please use termenv.Output instead. +func CursorPrevLine(n int) { + output.CursorPrevLine(n) +} + +// ClearLine clears the current line. +// +// Deprecated: please use termenv.Output instead. +func ClearLine() { + output.ClearLine() +} + +// ClearLineLeft clears the line to the left of the cursor. +// +// Deprecated: please use termenv.Output instead. +func ClearLineLeft() { + output.ClearLineLeft() +} + +// ClearLineRight clears the line to the right of the cursor. +// +// Deprecated: please use termenv.Output instead. +func ClearLineRight() { + output.ClearLineRight() +} + +// ClearLines clears a given number of lines. +// +// Deprecated: please use termenv.Output instead. +func ClearLines(n int) { + output.ClearLines(n) +} + +// ChangeScrollingRegion sets the scrolling region of the terminal. +// +// Deprecated: please use termenv.Output instead. +func ChangeScrollingRegion(top, bottom int) { + output.ChangeScrollingRegion(top, bottom) +} + +// InsertLines inserts the given number of lines at the top of the scrollable +// region, pushing lines below down. +// +// Deprecated: please use termenv.Output instead. +func InsertLines(n int) { + output.InsertLines(n) +} + +// DeleteLines deletes the given number of lines, pulling any lines in +// the scrollable region below up. +// +// Deprecated: please use termenv.Output instead. +func DeleteLines(n int) { + output.DeleteLines(n) +} + +// EnableMousePress enables X10 mouse mode. Button press events are sent only. +// +// Deprecated: please use termenv.Output instead. +func EnableMousePress() { + output.EnableMousePress() +} + +// DisableMousePress disables X10 mouse mode. +// +// Deprecated: please use termenv.Output instead. +func DisableMousePress() { + output.DisableMousePress() +} + +// EnableMouse enables Mouse Tracking mode. +// +// Deprecated: please use termenv.Output instead. +func EnableMouse() { + output.EnableMouse() +} + +// DisableMouse disables Mouse Tracking mode. +// +// Deprecated: please use termenv.Output instead. +func DisableMouse() { + output.DisableMouse() +} + +// EnableMouseHilite enables Hilite Mouse Tracking mode. +// +// Deprecated: please use termenv.Output instead. +func EnableMouseHilite() { + output.EnableMouseHilite() +} + +// DisableMouseHilite disables Hilite Mouse Tracking mode. +// +// Deprecated: please use termenv.Output instead. +func DisableMouseHilite() { + output.DisableMouseHilite() +} + +// EnableMouseCellMotion enables Cell Motion Mouse Tracking mode. +// +// Deprecated: please use termenv.Output instead. +func EnableMouseCellMotion() { + output.EnableMouseCellMotion() +} + +// DisableMouseCellMotion disables Cell Motion Mouse Tracking mode. +// +// Deprecated: please use termenv.Output instead. +func DisableMouseCellMotion() { + output.DisableMouseCellMotion() +} + +// EnableMouseAllMotion enables All Motion Mouse mode. +// +// Deprecated: please use termenv.Output instead. +func EnableMouseAllMotion() { + output.EnableMouseAllMotion() +} + +// DisableMouseAllMotion disables All Motion Mouse mode. +// +// Deprecated: please use termenv.Output instead. +func DisableMouseAllMotion() { + output.DisableMouseAllMotion() +} + +// SetWindowTitle sets the terminal window title. +// +// Deprecated: please use termenv.Output instead. +func SetWindowTitle(title string) { + output.SetWindowTitle(title) +} + +// EnableBracketedPaste enables bracketed paste. +// +// Deprecated: please use termenv.Output instead. +func EnableBracketedPaste() { + output.EnableBracketedPaste() +} + +// DisableBracketedPaste disables bracketed paste. +// +// Deprecated: please use termenv.Output instead. +func DisableBracketedPaste() { + output.DisableBracketedPaste() +} diff --git a/vendor/github.com/muesli/termenv/style.go b/vendor/github.com/muesli/termenv/style.go new file mode 100644 index 00000000..dedc1f9f --- /dev/null +++ b/vendor/github.com/muesli/termenv/style.go @@ -0,0 +1,126 @@ +package termenv + +import ( + "fmt" + "strings" + + "github.com/rivo/uniseg" +) + +// Sequence definitions. +const ( + ResetSeq = "0" + BoldSeq = "1" + FaintSeq = "2" + ItalicSeq = "3" + UnderlineSeq = "4" + BlinkSeq = "5" + ReverseSeq = "7" + CrossOutSeq = "9" + OverlineSeq = "53" +) + +// Style is a string that various rendering styles can be applied to. +type Style struct { + profile Profile + string + styles []string +} + +// String returns a new Style. +func String(s ...string) Style { + return Style{ + profile: ANSI, + string: strings.Join(s, " "), + } +} + +func (t Style) String() string { + return t.Styled(t.string) +} + +// Styled renders s with all applied styles. +func (t Style) Styled(s string) string { + if t.profile == Ascii { + return s + } + if len(t.styles) == 0 { + return s + } + + seq := strings.Join(t.styles, ";") + if seq == "" { + return s + } + + return fmt.Sprintf("%s%sm%s%sm", CSI, seq, s, CSI+ResetSeq) +} + +// Foreground sets a foreground color. +func (t Style) Foreground(c Color) Style { + if c != nil { + t.styles = append(t.styles, c.Sequence(false)) + } + return t +} + +// Background sets a background color. +func (t Style) Background(c Color) Style { + if c != nil { + t.styles = append(t.styles, c.Sequence(true)) + } + return t +} + +// Bold enables bold rendering. +func (t Style) Bold() Style { + t.styles = append(t.styles, BoldSeq) + return t +} + +// Faint enables faint rendering. +func (t Style) Faint() Style { + t.styles = append(t.styles, FaintSeq) + return t +} + +// Italic enables italic rendering. +func (t Style) Italic() Style { + t.styles = append(t.styles, ItalicSeq) + return t +} + +// Underline enables underline rendering. +func (t Style) Underline() Style { + t.styles = append(t.styles, UnderlineSeq) + return t +} + +// Overline enables overline rendering. +func (t Style) Overline() Style { + t.styles = append(t.styles, OverlineSeq) + return t +} + +// Blink enables blink mode. +func (t Style) Blink() Style { + t.styles = append(t.styles, BlinkSeq) + return t +} + +// Reverse enables reverse color mode. +func (t Style) Reverse() Style { + t.styles = append(t.styles, ReverseSeq) + return t +} + +// CrossOut enables crossed-out rendering. +func (t Style) CrossOut() Style { + t.styles = append(t.styles, CrossOutSeq) + return t +} + +// Width returns the width required to print all runes in Style. +func (t Style) Width() int { + return uniseg.StringWidth(t.string) +} diff --git a/vendor/github.com/muesli/termenv/templatehelper.go b/vendor/github.com/muesli/termenv/templatehelper.go new file mode 100644 index 00000000..4c7c80f5 --- /dev/null +++ b/vendor/github.com/muesli/termenv/templatehelper.go @@ -0,0 +1,88 @@ +package termenv + +import ( + "text/template" +) + +// TemplateFuncs returns template helpers for the given output. +func (o Output) TemplateFuncs() template.FuncMap { + return TemplateFuncs(o.Profile) +} + +// TemplateFuncs contains a few useful template helpers. +// +//nolint:mnd +func TemplateFuncs(p Profile) template.FuncMap { + if p == Ascii { + return noopTemplateFuncs + } + + return template.FuncMap{ + "Color": func(values ...interface{}) string { + s := p.String(values[len(values)-1].(string)) + switch len(values) { + case 2: + s = s.Foreground(p.Color(values[0].(string))) + case 3: + s = s. + Foreground(p.Color(values[0].(string))). + Background(p.Color(values[1].(string))) + } + + return s.String() + }, + "Foreground": func(values ...interface{}) string { + s := p.String(values[len(values)-1].(string)) + if len(values) == 2 { + s = s.Foreground(p.Color(values[0].(string))) + } + + return s.String() + }, + "Background": func(values ...interface{}) string { + s := p.String(values[len(values)-1].(string)) + if len(values) == 2 { + s = s.Background(p.Color(values[0].(string))) + } + + return s.String() + }, + "Bold": styleFunc(p, Style.Bold), + "Faint": styleFunc(p, Style.Faint), + "Italic": styleFunc(p, Style.Italic), + "Underline": styleFunc(p, Style.Underline), + "Overline": styleFunc(p, Style.Overline), + "Blink": styleFunc(p, Style.Blink), + "Reverse": styleFunc(p, Style.Reverse), + "CrossOut": styleFunc(p, Style.CrossOut), + } +} + +func styleFunc(p Profile, f func(Style) Style) func(...interface{}) string { + return func(values ...interface{}) string { + s := p.String(values[0].(string)) + return f(s).String() + } +} + +var noopTemplateFuncs = template.FuncMap{ + "Color": noColorFunc, + "Foreground": noColorFunc, + "Background": noColorFunc, + "Bold": noStyleFunc, + "Faint": noStyleFunc, + "Italic": noStyleFunc, + "Underline": noStyleFunc, + "Overline": noStyleFunc, + "Blink": noStyleFunc, + "Reverse": noStyleFunc, + "CrossOut": noStyleFunc, +} + +func noColorFunc(values ...interface{}) string { + return values[len(values)-1].(string) +} + +func noStyleFunc(values ...interface{}) string { + return values[0].(string) +} diff --git a/vendor/github.com/muesli/termenv/termenv.go b/vendor/github.com/muesli/termenv/termenv.go new file mode 100644 index 00000000..d702cd55 --- /dev/null +++ b/vendor/github.com/muesli/termenv/termenv.go @@ -0,0 +1,115 @@ +package termenv + +import ( + "errors" + "os" + + "github.com/mattn/go-isatty" +) + +var ( + // ErrStatusReport gets returned when the terminal can't be queried. + ErrStatusReport = errors.New("unable to retrieve status report") +) + +const ( + // Escape character. + ESC = '\x1b' + // Bell. + BEL = '\a' + // Control Sequence Introducer. + CSI = string(ESC) + "[" + // Operating System Command. + OSC = string(ESC) + "]" + // String Terminator. + ST = string(ESC) + `\` +) + +func (o *Output) isTTY() bool { + if o.assumeTTY || o.unsafe { + return true + } + if len(o.environ.Getenv("CI")) > 0 { + return false + } + if f, ok := o.Writer().(*os.File); ok { + return isatty.IsTerminal(f.Fd()) + } + + return false +} + +// ColorProfile returns the supported color profile: +// Ascii, ANSI, ANSI256, or TrueColor. +func ColorProfile() Profile { + return output.ColorProfile() +} + +// ForegroundColor returns the terminal's default foreground color. +func ForegroundColor() Color { + return output.ForegroundColor() +} + +// BackgroundColor returns the terminal's default background color. +func BackgroundColor() Color { + return output.BackgroundColor() +} + +// HasDarkBackground returns whether terminal uses a dark-ish background. +func HasDarkBackground() bool { + return output.HasDarkBackground() +} + +// EnvNoColor returns true if the environment variables explicitly disable color output +// by setting NO_COLOR (https://no-color.org/) +// or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/) +// If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE +// If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset. +func (o *Output) EnvNoColor() bool { + return o.environ.Getenv("NO_COLOR") != "" || (o.environ.Getenv("CLICOLOR") == "0" && !o.cliColorForced()) +} + +// EnvNoColor returns true if the environment variables explicitly disable color output +// by setting NO_COLOR (https://no-color.org/) +// or CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/) +// If NO_COLOR is set, this will return true, ignoring CLICOLOR/CLICOLOR_FORCE +// If CLICOLOR=="0", it will be true only if CLICOLOR_FORCE is also "0" or is unset. +func EnvNoColor() bool { + return output.EnvNoColor() +} + +// EnvColorProfile returns the color profile based on environment variables set +// Supports NO_COLOR (https://no-color.org/) +// and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/) +// If none of these environment variables are set, this behaves the same as ColorProfile() +// It will return the Ascii color profile if EnvNoColor() returns true +// If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0" +// then the ANSI color profile will be returned. +func EnvColorProfile() Profile { + return output.EnvColorProfile() +} + +// EnvColorProfile returns the color profile based on environment variables set +// Supports NO_COLOR (https://no-color.org/) +// and CLICOLOR/CLICOLOR_FORCE (https://bixense.com/clicolors/) +// If none of these environment variables are set, this behaves the same as ColorProfile() +// It will return the Ascii color profile if EnvNoColor() returns true +// If the terminal does not support any colors, but CLICOLOR_FORCE is set and not "0" +// then the ANSI color profile will be returned. +func (o *Output) EnvColorProfile() Profile { + if o.EnvNoColor() { + return Ascii + } + p := o.ColorProfile() + if o.cliColorForced() && p == Ascii { + return ANSI + } + return p +} + +func (o *Output) cliColorForced() bool { + if forced := o.environ.Getenv("CLICOLOR_FORCE"); forced != "" { + return forced != "0" + } + return false +} diff --git a/vendor/github.com/muesli/termenv/termenv_other.go b/vendor/github.com/muesli/termenv/termenv_other.go new file mode 100644 index 00000000..93a43b6a --- /dev/null +++ b/vendor/github.com/muesli/termenv/termenv_other.go @@ -0,0 +1,30 @@ +//go:build js || plan9 || aix +// +build js plan9 aix + +package termenv + +import "io" + +// ColorProfile returns the supported color profile: +// ANSI256 +func (o Output) ColorProfile() Profile { + return ANSI256 +} + +func (o Output) foregroundColor() Color { + // default gray + return ANSIColor(7) +} + +func (o Output) backgroundColor() Color { + // default black + return ANSIColor(0) +} + +// EnableVirtualTerminalProcessing enables virtual terminal processing on +// Windows for w and returns a function that restores w to its previous state. +// On non-Windows platforms, or if w does not refer to a terminal, then it +// returns a non-nil no-op function and no error. +func EnableVirtualTerminalProcessing(w io.Writer) (func() error, error) { + return func() error { return nil }, nil +} diff --git a/vendor/github.com/muesli/termenv/termenv_posix.go b/vendor/github.com/muesli/termenv/termenv_posix.go new file mode 100644 index 00000000..c971dd99 --- /dev/null +++ b/vendor/github.com/muesli/termenv/termenv_posix.go @@ -0,0 +1,17 @@ +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || zos +// +build darwin dragonfly freebsd linux netbsd openbsd zos + +package termenv + +import ( + "golang.org/x/sys/unix" +) + +func isForeground(fd int) bool { + pgrp, err := unix.IoctlGetInt(fd, unix.TIOCGPGRP) + if err != nil { + return false + } + + return pgrp == unix.Getpgrp() +} diff --git a/vendor/github.com/muesli/termenv/termenv_solaris.go b/vendor/github.com/muesli/termenv/termenv_solaris.go new file mode 100644 index 00000000..27a95a93 --- /dev/null +++ b/vendor/github.com/muesli/termenv/termenv_solaris.go @@ -0,0 +1,22 @@ +//go:build solaris || illumos +// +build solaris illumos + +package termenv + +import ( + "golang.org/x/sys/unix" +) + +func isForeground(fd int) bool { + pgrp, err := unix.IoctlGetInt(fd, unix.TIOCGPGRP) + if err != nil { + return false + } + + g, err := unix.Getpgrp() + if err != nil { + return false + } + + return pgrp == g +} diff --git a/vendor/github.com/muesli/termenv/termenv_unix.go b/vendor/github.com/muesli/termenv/termenv_unix.go new file mode 100644 index 00000000..bef49ca3 --- /dev/null +++ b/vendor/github.com/muesli/termenv/termenv_unix.go @@ -0,0 +1,301 @@ +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos +// +build darwin dragonfly freebsd linux netbsd openbsd solaris zos + +package termenv + +import ( + "fmt" + "io" + "strconv" + "strings" + "time" + + "golang.org/x/sys/unix" +) + +const ( + // timeout for OSC queries. + OSCTimeout = 5 * time.Second +) + +// ColorProfile returns the supported color profile: +// Ascii, ANSI, ANSI256, or TrueColor. +func (o *Output) ColorProfile() Profile { + if !o.isTTY() { + return Ascii + } + + if o.environ.Getenv("GOOGLE_CLOUD_SHELL") == "true" { + return TrueColor + } + + term := o.environ.Getenv("TERM") + colorTerm := o.environ.Getenv("COLORTERM") + + switch strings.ToLower(colorTerm) { + case "24bit": + fallthrough + case "truecolor": + if strings.HasPrefix(term, "screen") { + // tmux supports TrueColor, screen only ANSI256 + if o.environ.Getenv("TERM_PROGRAM") != "tmux" { + return ANSI256 + } + } + return TrueColor + case "yes": + fallthrough + case "true": + return ANSI256 + } + + switch term { + case + "alacritty", + "contour", + "rio", + "wezterm", + "xterm-ghostty", + "xterm-kitty": + return TrueColor + case "linux", "xterm": + return ANSI + } + + if strings.Contains(term, "256color") { + return ANSI256 + } + if strings.Contains(term, "color") { + return ANSI + } + if strings.Contains(term, "ansi") { + return ANSI + } + + return Ascii +} + +//nolint:mnd +func (o Output) foregroundColor() Color { + s, err := o.termStatusReport(10) + if err == nil { + c, err := xTermColor(s) + if err == nil { + return c + } + } + + colorFGBG := o.environ.Getenv("COLORFGBG") + if strings.Contains(colorFGBG, ";") { + c := strings.Split(colorFGBG, ";") + i, err := strconv.Atoi(c[0]) + if err == nil { + return ANSIColor(i) + } + } + + // default gray + return ANSIColor(7) +} + +//nolint:mnd +func (o Output) backgroundColor() Color { + s, err := o.termStatusReport(11) + if err == nil { + c, err := xTermColor(s) + if err == nil { + return c + } + } + + colorFGBG := o.environ.Getenv("COLORFGBG") + if strings.Contains(colorFGBG, ";") { + c := strings.Split(colorFGBG, ";") + i, err := strconv.Atoi(c[len(c)-1]) + if err == nil { + return ANSIColor(i) + } + } + + // default black + return ANSIColor(0) +} + +func (o *Output) waitForData(timeout time.Duration) error { + fd := o.TTY().Fd() + tv := unix.NsecToTimeval(int64(timeout)) + var readfds unix.FdSet + readfds.Set(int(fd)) //nolint:gosec + + for { + n, err := unix.Select(int(fd)+1, &readfds, nil, nil, &tv) //nolint:gosec + if err == unix.EINTR { + continue + } + if err != nil { + return err //nolint:wrapcheck + } + if n == 0 { + return fmt.Errorf("timeout") + } + + break + } + + return nil +} + +func (o *Output) readNextByte() (byte, error) { + if !o.unsafe { + if err := o.waitForData(OSCTimeout); err != nil { + return 0, err + } + } + + var b [1]byte + n, err := o.TTY().Read(b[:]) + if err != nil { + return 0, err //nolint:wrapcheck + } + + if n == 0 { + panic("read returned no data") + } + + return b[0], nil +} + +// readNextResponse reads either an OSC response or a cursor position response: +// - OSC response: "\x1b]11;rgb:1111/1111/1111\x1b\\" +// - cursor position response: "\x1b[42;1R" +func (o *Output) readNextResponse() (response string, isOSC bool, err error) { + start, err := o.readNextByte() + if err != nil { + return "", false, err + } + + // first byte must be ESC + for start != ESC { + start, err = o.readNextByte() + if err != nil { + return "", false, err + } + } + + response += string(start) + + // next byte is either '[' (cursor position response) or ']' (OSC response) + tpe, err := o.readNextByte() + if err != nil { + return "", false, err + } + + response += string(tpe) + + var oscResponse bool + switch tpe { + case '[': + oscResponse = false + case ']': + oscResponse = true + default: + return "", false, ErrStatusReport + } + + for { + b, err := o.readNextByte() + if err != nil { + return "", false, err + } + + response += string(b) + + if oscResponse { + // OSC can be terminated by BEL (\a) or ST (ESC) + if b == BEL || strings.HasSuffix(response, string(ESC)) { + return response, true, nil + } + } else { + // cursor position response is terminated by 'R' + if b == 'R' { + return response, false, nil + } + } + + // both responses have less than 25 bytes, so if we read more, that's an error + if len(response) > 25 { //nolint:mnd + break + } + } + + return "", false, ErrStatusReport +} + +func (o Output) termStatusReport(sequence int) (string, error) { + // screen/tmux can't support OSC, because they can be connected to multiple + // terminals concurrently. + term := o.environ.Getenv("TERM") + if strings.HasPrefix(term, "screen") || strings.HasPrefix(term, "tmux") || strings.HasPrefix(term, "dumb") { + return "", ErrStatusReport + } + + tty := o.TTY() + if tty == nil { + return "", ErrStatusReport + } + + if !o.unsafe { + fd := int(tty.Fd()) //nolint:gosec + // if in background, we can't control the terminal + if !isForeground(fd) { + return "", ErrStatusReport + } + + t, err := unix.IoctlGetTermios(fd, tcgetattr) + if err != nil { + return "", fmt.Errorf("%s: %s", ErrStatusReport, err) + } + defer unix.IoctlSetTermios(fd, tcsetattr, t) //nolint:errcheck + + noecho := *t + noecho.Lflag = noecho.Lflag &^ unix.ECHO + noecho.Lflag = noecho.Lflag &^ unix.ICANON + if err := unix.IoctlSetTermios(fd, tcsetattr, &noecho); err != nil { + return "", fmt.Errorf("%s: %s", ErrStatusReport, err) + } + } + + // first, send OSC query, which is ignored by terminal which do not support it + fmt.Fprintf(tty, OSC+"%d;?"+ST, sequence) //nolint:errcheck + + // then, query cursor position, should be supported by all terminals + fmt.Fprintf(tty, CSI+"6n") //nolint:errcheck + + // read the next response + res, isOSC, err := o.readNextResponse() + if err != nil { + return "", fmt.Errorf("%s: %s", ErrStatusReport, err) + } + + // if this is not OSC response, then the terminal does not support it + if !isOSC { + return "", ErrStatusReport + } + + // read the cursor query response next and discard the result + _, _, err = o.readNextResponse() + if err != nil { + return "", err + } + + // fmt.Println("Rcvd", res[1:]) + return res, nil +} + +// EnableVirtualTerminalProcessing enables virtual terminal processing on +// Windows for w and returns a function that restores w to its previous state. +// On non-Windows platforms, or if w does not refer to a terminal, then it +// returns a non-nil no-op function and no error. +func EnableVirtualTerminalProcessing(_ io.Writer) (func() error, error) { + return func() error { return nil }, nil +} diff --git a/vendor/github.com/muesli/termenv/termenv_windows.go b/vendor/github.com/muesli/termenv/termenv_windows.go new file mode 100644 index 00000000..f9b1def0 --- /dev/null +++ b/vendor/github.com/muesli/termenv/termenv_windows.go @@ -0,0 +1,140 @@ +//go:build windows +// +build windows + +package termenv + +import ( + "fmt" + "os" + "strconv" + + "golang.org/x/sys/windows" +) + +func (o *Output) ColorProfile() Profile { + if !o.isTTY() { + return Ascii + } + + if o.environ.Getenv("ConEmuANSI") == "ON" { + return TrueColor + } + + winVersion, _, buildNumber := windows.RtlGetNtVersionNumbers() + if buildNumber < 10586 || winVersion < 10 { + // No ANSI support before Windows 10 build 10586. + if o.environ.Getenv("ANSICON") != "" { + conVersion := o.environ.Getenv("ANSICON_VER") + cv, err := strconv.ParseInt(conVersion, 10, 64) + if err != nil || cv < 181 { + // No 8 bit color support before v1.81 release. + return ANSI + } + + return ANSI256 + } + + return Ascii + } + if buildNumber < 14931 { + // No true color support before build 14931. + return ANSI256 + } + + return TrueColor +} + +func (o Output) foregroundColor() Color { + // default gray + return ANSIColor(7) +} + +func (o Output) backgroundColor() Color { + // default black + return ANSIColor(0) +} + +// EnableWindowsANSIConsole enables virtual terminal processing on Windows +// platforms. This allows the use of ANSI escape sequences in Windows console +// applications. Ensure this gets called before anything gets rendered with +// termenv. +// +// Returns the original console mode and an error if one occurred. +func EnableWindowsANSIConsole() (uint32, error) { + handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE) + if err != nil { + return 0, err + } + + var mode uint32 + err = windows.GetConsoleMode(handle, &mode) + if err != nil { + return 0, err + } + + // See https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences + if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING != windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING { + vtpmode := mode | windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING + if err := windows.SetConsoleMode(handle, vtpmode); err != nil { + return 0, err + } + } + + return mode, nil +} + +// RestoreWindowsConsole restores the console mode to a previous state. +func RestoreWindowsConsole(mode uint32) error { + handle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE) + if err != nil { + return err + } + + return windows.SetConsoleMode(handle, mode) +} + +// EnableVirtualTerminalProcessing enables virtual terminal processing on +// Windows for o and returns a function that restores o to its previous state. +// On non-Windows platforms, or if o does not refer to a terminal, then it +// returns a non-nil no-op function and no error. +func EnableVirtualTerminalProcessing(o *Output) (restoreFunc func() error, err error) { + // There is nothing to restore until we set the console mode. + restoreFunc = func() error { + return nil + } + + // If o is not a tty, then there is nothing to do. + tty, ok := o.Writer().(*os.File) + if tty == nil || !ok { + return + } + + // Get the current console mode. If there is an error, assume that o is not + // a terminal, discard the error, and return. + var mode uint32 + if err2 := windows.GetConsoleMode(windows.Handle(tty.Fd()), &mode); err2 != nil { + return + } + + // If virtual terminal processing is already set, then there is nothing to + // do and nothing to restore. + if mode&windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING == windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING { + return + } + + // Enable virtual terminal processing. See + // https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences + if err2 := windows.SetConsoleMode(windows.Handle(tty.Fd()), mode|windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err2 != nil { + err = fmt.Errorf("windows.SetConsoleMode: %w", err2) + return + } + + // Set the restore function. We maintain a reference to the tty in the + // closure (rather than just its handle) to ensure that the tty is not + // closed by a finalizer. + restoreFunc = func() error { + return windows.SetConsoleMode(windows.Handle(tty.Fd()), mode) + } + + return +} diff --git a/vendor/github.com/xo/terminfo/.gitignore b/vendor/github.com/xo/terminfo/.gitignore new file mode 100644 index 00000000..368e0c06 --- /dev/null +++ b/vendor/github.com/xo/terminfo/.gitignore @@ -0,0 +1,9 @@ +/.cache/ + +/cmd/infocmp/infocmp +/cmd/infocmp/.out/ + +/infocmp +/.out/ + +*.txt diff --git a/vendor/github.com/xo/terminfo/LICENSE b/vendor/github.com/xo/terminfo/LICENSE new file mode 100644 index 00000000..197dadb1 --- /dev/null +++ b/vendor/github.com/xo/terminfo/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Anmol Sethi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/xo/terminfo/README.md b/vendor/github.com/xo/terminfo/README.md new file mode 100644 index 00000000..e5002d23 --- /dev/null +++ b/vendor/github.com/xo/terminfo/README.md @@ -0,0 +1,139 @@ +# About terminfo [![GoDoc][1]][2] + +Package `terminfo` provides a pure-Go implementation of reading information +from the terminfo database. + +`terminfo` is meant as a replacement for `ncurses` in simple Go programs. + +## Installing + +Install in the usual Go way: + +```sh +$ go get -u github.com/xo/terminfo +``` + +## Using + +Please see the [GoDoc API listing][2] for more information on using `terminfo`. + +```go +// _examples/simple/main.go +package main + +import ( + "bytes" + "fmt" + "log" + "os" + "os/signal" + "strings" + "sync" + "syscall" + + "github.com/xo/terminfo" +) + +func main() { + //r := rand.New(nil) + + // load terminfo + ti, err := terminfo.LoadFromEnv() + if err != nil { + log.Fatal(err) + } + + // cleanup + defer func() { + err := recover() + termreset(ti) + if err != nil { + log.Fatal(err) + } + }() + + terminit(ti) + termtitle(ti, "simple example!") + termputs(ti, 3, 3, "Ctrl-C to exit") + maxColors := termcolors(ti) + if maxColors > 256 { + maxColors = 256 + } + for i := 0; i < maxColors; i++ { + termputs(ti, 5+i/16, 5+i%16, ti.Colorf(i, 0, "█")) + } + + // wait for signal + sigs := make(chan os.Signal, 1) + signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) + <-sigs +} + +// terminit initializes the special CA mode on the terminal, and makes the +// cursor invisible. +func terminit(ti *terminfo.Terminfo) { + buf := new(bytes.Buffer) + // set the cursor invisible + ti.Fprintf(buf, terminfo.CursorInvisible) + // enter special mode + ti.Fprintf(buf, terminfo.EnterCaMode) + // clear the screen + ti.Fprintf(buf, terminfo.ClearScreen) + os.Stdout.Write(buf.Bytes()) +} + +// termreset is the inverse of terminit. +func termreset(ti *terminfo.Terminfo) { + buf := new(bytes.Buffer) + ti.Fprintf(buf, terminfo.ExitCaMode) + ti.Fprintf(buf, terminfo.CursorNormal) + os.Stdout.Write(buf.Bytes()) +} + +// termputs puts a string at row, col, interpolating v. +func termputs(ti *terminfo.Terminfo, row, col int, s string, v ...interface{}) { + buf := new(bytes.Buffer) + ti.Fprintf(buf, terminfo.CursorAddress, row, col) + fmt.Fprintf(buf, s, v...) + os.Stdout.Write(buf.Bytes()) +} + +// sl is the status line terminfo. +var sl *terminfo.Terminfo + +// termtitle sets the window title. +func termtitle(ti *terminfo.Terminfo, s string) { + var once sync.Once + once.Do(func() { + if ti.Has(terminfo.HasStatusLine) { + return + } + // load the sl xterm if terminal is an xterm or has COLORTERM + if strings.Contains(strings.ToLower(os.Getenv("TERM")), "xterm") || os.Getenv("COLORTERM") == "truecolor" { + sl, _ = terminfo.Load("xterm+sl") + } + }) + if sl != nil { + ti = sl + } + if !ti.Has(terminfo.HasStatusLine) { + return + } + buf := new(bytes.Buffer) + ti.Fprintf(buf, terminfo.ToStatusLine) + fmt.Fprint(buf, s) + ti.Fprintf(buf, terminfo.FromStatusLine) + os.Stdout.Write(buf.Bytes()) +} + +// termcolors returns the maximum colors available for the terminal. +func termcolors(ti *terminfo.Terminfo) int { + if colors := ti.Num(terminfo.MaxColors); colors > 0 { + return colors + } + return int(terminfo.ColorLevelBasic) +} +``` + +[1]: https://godoc.org/github.com/xo/terminfo?status.svg +[2]: https://godoc.org/github.com/xo/terminfo diff --git a/vendor/github.com/xo/terminfo/caps.go b/vendor/github.com/xo/terminfo/caps.go new file mode 100644 index 00000000..e5e1d41f --- /dev/null +++ b/vendor/github.com/xo/terminfo/caps.go @@ -0,0 +1,31 @@ +package terminfo + +// BoolCapName returns the bool capability name. +func BoolCapName(i int) string { + return boolCapNames[2*i] +} + +// BoolCapNameShort returns the short bool capability name. +func BoolCapNameShort(i int) string { + return boolCapNames[2*i+1] +} + +// NumCapName returns the num capability name. +func NumCapName(i int) string { + return numCapNames[2*i] +} + +// NumCapNameShort returns the short num capability name. +func NumCapNameShort(i int) string { + return numCapNames[2*i+1] +} + +// StringCapName returns the string capability name. +func StringCapName(i int) string { + return stringCapNames[2*i] +} + +// StringCapNameShort returns the short string capability name. +func StringCapNameShort(i int) string { + return stringCapNames[2*i+1] +} diff --git a/vendor/github.com/xo/terminfo/capvals.go b/vendor/github.com/xo/terminfo/capvals.go new file mode 100644 index 00000000..0c2274e3 --- /dev/null +++ b/vendor/github.com/xo/terminfo/capvals.go @@ -0,0 +1,1525 @@ +package terminfo + +// Code generated by gen.go. DO NOT EDIT. +// Bool capabilities. +const ( + // The AutoLeftMargin [auto_left_margin, bw] bool capability indicates cub1 wraps from column 0 to last column. + AutoLeftMargin = iota + // The AutoRightMargin [auto_right_margin, am] bool capability indicates terminal has automatic margins. + AutoRightMargin + // The NoEscCtlc [no_esc_ctlc, xsb] bool capability indicates beehive (f1=escape, f2=ctrl C). + NoEscCtlc + // The CeolStandoutGlitch [ceol_standout_glitch, xhp] bool capability indicates standout not erased by overwriting (hp). + CeolStandoutGlitch + // The EatNewlineGlitch [eat_newline_glitch, xenl] bool capability indicates newline ignored after 80 cols (concept). + EatNewlineGlitch + // The EraseOverstrike [erase_overstrike, eo] bool capability indicates can erase overstrikes with a blank. + EraseOverstrike + // The GenericType [generic_type, gn] bool capability indicates generic line type. + GenericType + // The HardCopy [hard_copy, hc] bool capability indicates hardcopy terminal. + HardCopy + // The HasMetaKey [has_meta_key, km] bool capability indicates Has a meta key (i.e., sets 8th-bit). + HasMetaKey + // The HasStatusLine [has_status_line, hs] bool capability indicates has extra status line. + HasStatusLine + // The InsertNullGlitch [insert_null_glitch, in] bool capability indicates insert mode distinguishes nulls. + InsertNullGlitch + // The MemoryAbove [memory_above, da] bool capability indicates display may be retained above the screen. + MemoryAbove + // The MemoryBelow [memory_below, db] bool capability indicates display may be retained below the screen. + MemoryBelow + // The MoveInsertMode [move_insert_mode, mir] bool capability indicates safe to move while in insert mode. + MoveInsertMode + // The MoveStandoutMode [move_standout_mode, msgr] bool capability indicates safe to move while in standout mode. + MoveStandoutMode + // The OverStrike [over_strike, os] bool capability indicates terminal can overstrike. + OverStrike + // The StatusLineEscOk [status_line_esc_ok, eslok] bool capability indicates escape can be used on the status line. + StatusLineEscOk + // The DestTabsMagicSmso [dest_tabs_magic_smso, xt] bool capability indicates tabs destructive, magic so char (t1061). + DestTabsMagicSmso + // The TildeGlitch [tilde_glitch, hz] bool capability indicates cannot print ~'s (Hazeltine). + TildeGlitch + // The TransparentUnderline [transparent_underline, ul] bool capability indicates underline character overstrikes. + TransparentUnderline + // The XonXoff [xon_xoff, xon] bool capability indicates terminal uses xon/xoff handshaking. + XonXoff + // The NeedsXonXoff [needs_xon_xoff, nxon] bool capability indicates padding will not work, xon/xoff required. + NeedsXonXoff + // The PrtrSilent [prtr_silent, mc5i] bool capability indicates printer will not echo on screen. + PrtrSilent + // The HardCursor [hard_cursor, chts] bool capability indicates cursor is hard to see. + HardCursor + // The NonRevRmcup [non_rev_rmcup, nrrmc] bool capability indicates smcup does not reverse rmcup. + NonRevRmcup + // The NoPadChar [no_pad_char, npc] bool capability indicates pad character does not exist. + NoPadChar + // The NonDestScrollRegion [non_dest_scroll_region, ndscr] bool capability indicates scrolling region is non-destructive. + NonDestScrollRegion + // The CanChange [can_change, ccc] bool capability indicates terminal can re-define existing colors. + CanChange + // The BackColorErase [back_color_erase, bce] bool capability indicates screen erased with background color. + BackColorErase + // The HueLightnessSaturation [hue_lightness_saturation, hls] bool capability indicates terminal uses only HLS color notation (Tektronix). + HueLightnessSaturation + // The ColAddrGlitch [col_addr_glitch, xhpa] bool capability indicates only positive motion for hpa/mhpa caps. + ColAddrGlitch + // The CrCancelsMicroMode [cr_cancels_micro_mode, crxm] bool capability indicates using cr turns off micro mode. + CrCancelsMicroMode + // The HasPrintWheel [has_print_wheel, daisy] bool capability indicates printer needs operator to change character set. + HasPrintWheel + // The RowAddrGlitch [row_addr_glitch, xvpa] bool capability indicates only positive motion for vpa/mvpa caps. + RowAddrGlitch + // The SemiAutoRightMargin [semi_auto_right_margin, sam] bool capability indicates printing in last column causes cr. + SemiAutoRightMargin + // The CpiChangesRes [cpi_changes_res, cpix] bool capability indicates changing character pitch changes resolution. + CpiChangesRes + // The LpiChangesRes [lpi_changes_res, lpix] bool capability indicates changing line pitch changes resolution. + LpiChangesRes + // The BackspacesWithBs [backspaces_with_bs, OTbs] bool capability indicates uses ^H to move left. + BackspacesWithBs + // The CrtNoScrolling [crt_no_scrolling, OTns] bool capability indicates crt cannot scroll. + CrtNoScrolling + // The NoCorrectlyWorkingCr [no_correctly_working_cr, OTnc] bool capability indicates no way to go to start of line. + NoCorrectlyWorkingCr + // The GnuHasMetaKey [gnu_has_meta_key, OTMT] bool capability indicates has meta key. + GnuHasMetaKey + // The LinefeedIsNewline [linefeed_is_newline, OTNL] bool capability indicates move down with \n. + LinefeedIsNewline + // The HasHardwareTabs [has_hardware_tabs, OTpt] bool capability indicates has 8-char tabs invoked with ^I. + HasHardwareTabs + // The ReturnDoesClrEol [return_does_clr_eol, OTxr] bool capability indicates return clears the line. + ReturnDoesClrEol +) + +// Num capabilities. +const ( + // The Columns [columns, cols] num capability is number of columns in a line. + Columns = iota + // The InitTabs [init_tabs, it] num capability is tabs initially every # spaces. + InitTabs + // The Lines [lines, lines] num capability is number of lines on screen or page. + Lines + // The LinesOfMemory [lines_of_memory, lm] num capability is lines of memory if > line. 0 means varies. + LinesOfMemory + // The MagicCookieGlitch [magic_cookie_glitch, xmc] num capability is number of blank characters left by smso or rmso. + MagicCookieGlitch + // The PaddingBaudRate [padding_baud_rate, pb] num capability is lowest baud rate where padding needed. + PaddingBaudRate + // The VirtualTerminal [virtual_terminal, vt] num capability is virtual terminal number (CB/unix). + VirtualTerminal + // The WidthStatusLine [width_status_line, wsl] num capability is number of columns in status line. + WidthStatusLine + // The NumLabels [num_labels, nlab] num capability is number of labels on screen. + NumLabels + // The LabelHeight [label_height, lh] num capability is rows in each label. + LabelHeight + // The LabelWidth [label_width, lw] num capability is columns in each label. + LabelWidth + // The MaxAttributes [max_attributes, ma] num capability is maximum combined attributes terminal can handle. + MaxAttributes + // The MaximumWindows [maximum_windows, wnum] num capability is maximum number of definable windows. + MaximumWindows + // The MaxColors [max_colors, colors] num capability is maximum number of colors on screen. + MaxColors + // The MaxPairs [max_pairs, pairs] num capability is maximum number of color-pairs on the screen. + MaxPairs + // The NoColorVideo [no_color_video, ncv] num capability is video attributes that cannot be used with colors. + NoColorVideo + // The BufferCapacity [buffer_capacity, bufsz] num capability is numbers of bytes buffered before printing. + BufferCapacity + // The DotVertSpacing [dot_vert_spacing, spinv] num capability is spacing of pins vertically in pins per inch. + DotVertSpacing + // The DotHorzSpacing [dot_horz_spacing, spinh] num capability is spacing of dots horizontally in dots per inch. + DotHorzSpacing + // The MaxMicroAddress [max_micro_address, maddr] num capability is maximum value in micro_..._address. + MaxMicroAddress + // The MaxMicroJump [max_micro_jump, mjump] num capability is maximum value in parm_..._micro. + MaxMicroJump + // The MicroColSize [micro_col_size, mcs] num capability is character step size when in micro mode. + MicroColSize + // The MicroLineSize [micro_line_size, mls] num capability is line step size when in micro mode. + MicroLineSize + // The NumberOfPins [number_of_pins, npins] num capability is numbers of pins in print-head. + NumberOfPins + // The OutputResChar [output_res_char, orc] num capability is horizontal resolution in units per line. + OutputResChar + // The OutputResLine [output_res_line, orl] num capability is vertical resolution in units per line. + OutputResLine + // The OutputResHorzInch [output_res_horz_inch, orhi] num capability is horizontal resolution in units per inch. + OutputResHorzInch + // The OutputResVertInch [output_res_vert_inch, orvi] num capability is vertical resolution in units per inch. + OutputResVertInch + // The PrintRate [print_rate, cps] num capability is print rate in characters per second. + PrintRate + // The WideCharSize [wide_char_size, widcs] num capability is character step size when in double wide mode. + WideCharSize + // The Buttons [buttons, btns] num capability is number of buttons on mouse. + Buttons + // The BitImageEntwining [bit_image_entwining, bitwin] num capability is number of passes for each bit-image row. + BitImageEntwining + // The BitImageType [bit_image_type, bitype] num capability is type of bit-image device. + BitImageType + // The MagicCookieGlitchUl [magic_cookie_glitch_ul, OTug] num capability is number of blanks left by ul. + MagicCookieGlitchUl + // The CarriageReturnDelay [carriage_return_delay, OTdC] num capability is pad needed for CR. + CarriageReturnDelay + // The NewLineDelay [new_line_delay, OTdN] num capability is pad needed for LF. + NewLineDelay + // The BackspaceDelay [backspace_delay, OTdB] num capability is padding required for ^H. + BackspaceDelay + // The HorizontalTabDelay [horizontal_tab_delay, OTdT] num capability is padding required for ^I. + HorizontalTabDelay + // The NumberOfFunctionKeys [number_of_function_keys, OTkn] num capability is count of function keys. + NumberOfFunctionKeys +) + +// String capabilities. +const ( + // The BackTab [back_tab, cbt] string capability is the back tab (P). + BackTab = iota + // The Bell [bell, bel] string capability is the audible signal (bell) (P). + Bell + // The CarriageReturn [carriage_return, cr] string capability is the carriage return (P*) (P*). + CarriageReturn + // The ChangeScrollRegion [change_scroll_region, csr] string capability is the change region to line #1 to line #2 (P). + ChangeScrollRegion + // The ClearAllTabs [clear_all_tabs, tbc] string capability is the clear all tab stops (P). + ClearAllTabs + // The ClearScreen [clear_screen, clear] string capability is the clear screen and home cursor (P*). + ClearScreen + // The ClrEol [clr_eol, el] string capability is the clear to end of line (P). + ClrEol + // The ClrEos [clr_eos, ed] string capability is the clear to end of screen (P*). + ClrEos + // The ColumnAddress [column_address, hpa] string capability is the horizontal position #1, absolute (P). + ColumnAddress + // The CommandCharacter [command_character, cmdch] string capability is the terminal settable cmd character in prototype !?. + CommandCharacter + // The CursorAddress [cursor_address, cup] string capability is the move to row #1 columns #2. + CursorAddress + // The CursorDown [cursor_down, cud1] string capability is the down one line. + CursorDown + // The CursorHome [cursor_home, home] string capability is the home cursor (if no cup). + CursorHome + // The CursorInvisible [cursor_invisible, civis] string capability is the make cursor invisible. + CursorInvisible + // The CursorLeft [cursor_left, cub1] string capability is the move left one space. + CursorLeft + // The CursorMemAddress [cursor_mem_address, mrcup] string capability is the memory relative cursor addressing, move to row #1 columns #2. + CursorMemAddress + // The CursorNormal [cursor_normal, cnorm] string capability is the make cursor appear normal (undo civis/cvvis). + CursorNormal + // The CursorRight [cursor_right, cuf1] string capability is the non-destructive space (move right one space). + CursorRight + // The CursorToLl [cursor_to_ll, ll] string capability is the last line, first column (if no cup). + CursorToLl + // The CursorUp [cursor_up, cuu1] string capability is the up one line. + CursorUp + // The CursorVisible [cursor_visible, cvvis] string capability is the make cursor very visible. + CursorVisible + // The DeleteCharacter [delete_character, dch1] string capability is the delete character (P*). + DeleteCharacter + // The DeleteLine [delete_line, dl1] string capability is the delete line (P*). + DeleteLine + // The DisStatusLine [dis_status_line, dsl] string capability is the disable status line. + DisStatusLine + // The DownHalfLine [down_half_line, hd] string capability is the half a line down. + DownHalfLine + // The EnterAltCharsetMode [enter_alt_charset_mode, smacs] string capability is the start alternate character set (P). + EnterAltCharsetMode + // The EnterBlinkMode [enter_blink_mode, blink] string capability is the turn on blinking. + EnterBlinkMode + // The EnterBoldMode [enter_bold_mode, bold] string capability is the turn on bold (extra bright) mode. + EnterBoldMode + // The EnterCaMode [enter_ca_mode, smcup] string capability is the string to start programs using cup. + EnterCaMode + // The EnterDeleteMode [enter_delete_mode, smdc] string capability is the enter delete mode. + EnterDeleteMode + // The EnterDimMode [enter_dim_mode, dim] string capability is the turn on half-bright mode. + EnterDimMode + // The EnterInsertMode [enter_insert_mode, smir] string capability is the enter insert mode. + EnterInsertMode + // The EnterSecureMode [enter_secure_mode, invis] string capability is the turn on blank mode (characters invisible). + EnterSecureMode + // The EnterProtectedMode [enter_protected_mode, prot] string capability is the turn on protected mode. + EnterProtectedMode + // The EnterReverseMode [enter_reverse_mode, rev] string capability is the turn on reverse video mode. + EnterReverseMode + // The EnterStandoutMode [enter_standout_mode, smso] string capability is the begin standout mode. + EnterStandoutMode + // The EnterUnderlineMode [enter_underline_mode, smul] string capability is the begin underline mode. + EnterUnderlineMode + // The EraseChars [erase_chars, ech] string capability is the erase #1 characters (P). + EraseChars + // The ExitAltCharsetMode [exit_alt_charset_mode, rmacs] string capability is the end alternate character set (P). + ExitAltCharsetMode + // The ExitAttributeMode [exit_attribute_mode, sgr0] string capability is the turn off all attributes. + ExitAttributeMode + // The ExitCaMode [exit_ca_mode, rmcup] string capability is the strings to end programs using cup. + ExitCaMode + // The ExitDeleteMode [exit_delete_mode, rmdc] string capability is the end delete mode. + ExitDeleteMode + // The ExitInsertMode [exit_insert_mode, rmir] string capability is the exit insert mode. + ExitInsertMode + // The ExitStandoutMode [exit_standout_mode, rmso] string capability is the exit standout mode. + ExitStandoutMode + // The ExitUnderlineMode [exit_underline_mode, rmul] string capability is the exit underline mode. + ExitUnderlineMode + // The FlashScreen [flash_screen, flash] string capability is the visible bell (may not move cursor). + FlashScreen + // The FormFeed [form_feed, ff] string capability is the hardcopy terminal page eject (P*). + FormFeed + // The FromStatusLine [from_status_line, fsl] string capability is the return from status line. + FromStatusLine + // The Init1string [init_1string, is1] string capability is the initialization string. + Init1string + // The Init2string [init_2string, is2] string capability is the initialization string. + Init2string + // The Init3string [init_3string, is3] string capability is the initialization string. + Init3string + // The InitFile [init_file, if] string capability is the name of initialization file. + InitFile + // The InsertCharacter [insert_character, ich1] string capability is the insert character (P). + InsertCharacter + // The InsertLine [insert_line, il1] string capability is the insert line (P*). + InsertLine + // The InsertPadding [insert_padding, ip] string capability is the insert padding after inserted character. + InsertPadding + // The KeyBackspace [key_backspace, kbs] string capability is the backspace key. + KeyBackspace + // The KeyCatab [key_catab, ktbc] string capability is the clear-all-tabs key. + KeyCatab + // The KeyClear [key_clear, kclr] string capability is the clear-screen or erase key. + KeyClear + // The KeyCtab [key_ctab, kctab] string capability is the clear-tab key. + KeyCtab + // The KeyDc [key_dc, kdch1] string capability is the delete-character key. + KeyDc + // The KeyDl [key_dl, kdl1] string capability is the delete-line key. + KeyDl + // The KeyDown [key_down, kcud1] string capability is the down-arrow key. + KeyDown + // The KeyEic [key_eic, krmir] string capability is the sent by rmir or smir in insert mode. + KeyEic + // The KeyEol [key_eol, kel] string capability is the clear-to-end-of-line key. + KeyEol + // The KeyEos [key_eos, ked] string capability is the clear-to-end-of-screen key. + KeyEos + // The KeyF0 [key_f0, kf0] string capability is the F0 function key. + KeyF0 + // The KeyF1 [key_f1, kf1] string capability is the F1 function key. + KeyF1 + // The KeyF10 [key_f10, kf10] string capability is the F10 function key. + KeyF10 + // The KeyF2 [key_f2, kf2] string capability is the F2 function key. + KeyF2 + // The KeyF3 [key_f3, kf3] string capability is the F3 function key. + KeyF3 + // The KeyF4 [key_f4, kf4] string capability is the F4 function key. + KeyF4 + // The KeyF5 [key_f5, kf5] string capability is the F5 function key. + KeyF5 + // The KeyF6 [key_f6, kf6] string capability is the F6 function key. + KeyF6 + // The KeyF7 [key_f7, kf7] string capability is the F7 function key. + KeyF7 + // The KeyF8 [key_f8, kf8] string capability is the F8 function key. + KeyF8 + // The KeyF9 [key_f9, kf9] string capability is the F9 function key. + KeyF9 + // The KeyHome [key_home, khome] string capability is the home key. + KeyHome + // The KeyIc [key_ic, kich1] string capability is the insert-character key. + KeyIc + // The KeyIl [key_il, kil1] string capability is the insert-line key. + KeyIl + // The KeyLeft [key_left, kcub1] string capability is the left-arrow key. + KeyLeft + // The KeyLl [key_ll, kll] string capability is the lower-left key (home down). + KeyLl + // The KeyNpage [key_npage, knp] string capability is the next-page key. + KeyNpage + // The KeyPpage [key_ppage, kpp] string capability is the previous-page key. + KeyPpage + // The KeyRight [key_right, kcuf1] string capability is the right-arrow key. + KeyRight + // The KeySf [key_sf, kind] string capability is the scroll-forward key. + KeySf + // The KeySr [key_sr, kri] string capability is the scroll-backward key. + KeySr + // The KeyStab [key_stab, khts] string capability is the set-tab key. + KeyStab + // The KeyUp [key_up, kcuu1] string capability is the up-arrow key. + KeyUp + // The KeypadLocal [keypad_local, rmkx] string capability is the leave 'keyboard_transmit' mode. + KeypadLocal + // The KeypadXmit [keypad_xmit, smkx] string capability is the enter 'keyboard_transmit' mode. + KeypadXmit + // The LabF0 [lab_f0, lf0] string capability is the label on function key f0 if not f0. + LabF0 + // The LabF1 [lab_f1, lf1] string capability is the label on function key f1 if not f1. + LabF1 + // The LabF10 [lab_f10, lf10] string capability is the label on function key f10 if not f10. + LabF10 + // The LabF2 [lab_f2, lf2] string capability is the label on function key f2 if not f2. + LabF2 + // The LabF3 [lab_f3, lf3] string capability is the label on function key f3 if not f3. + LabF3 + // The LabF4 [lab_f4, lf4] string capability is the label on function key f4 if not f4. + LabF4 + // The LabF5 [lab_f5, lf5] string capability is the label on function key f5 if not f5. + LabF5 + // The LabF6 [lab_f6, lf6] string capability is the label on function key f6 if not f6. + LabF6 + // The LabF7 [lab_f7, lf7] string capability is the label on function key f7 if not f7. + LabF7 + // The LabF8 [lab_f8, lf8] string capability is the label on function key f8 if not f8. + LabF8 + // The LabF9 [lab_f9, lf9] string capability is the label on function key f9 if not f9. + LabF9 + // The MetaOff [meta_off, rmm] string capability is the turn off meta mode. + MetaOff + // The MetaOn [meta_on, smm] string capability is the turn on meta mode (8th-bit on). + MetaOn + // The Newline [newline, nel] string capability is the newline (behave like cr followed by lf). + Newline + // The PadChar [pad_char, pad] string capability is the padding char (instead of null). + PadChar + // The ParmDch [parm_dch, dch] string capability is the delete #1 characters (P*). + ParmDch + // The ParmDeleteLine [parm_delete_line, dl] string capability is the delete #1 lines (P*). + ParmDeleteLine + // The ParmDownCursor [parm_down_cursor, cud] string capability is the down #1 lines (P*). + ParmDownCursor + // The ParmIch [parm_ich, ich] string capability is the insert #1 characters (P*). + ParmIch + // The ParmIndex [parm_index, indn] string capability is the scroll forward #1 lines (P). + ParmIndex + // The ParmInsertLine [parm_insert_line, il] string capability is the insert #1 lines (P*). + ParmInsertLine + // The ParmLeftCursor [parm_left_cursor, cub] string capability is the move #1 characters to the left (P). + ParmLeftCursor + // The ParmRightCursor [parm_right_cursor, cuf] string capability is the move #1 characters to the right (P*). + ParmRightCursor + // The ParmRindex [parm_rindex, rin] string capability is the scroll back #1 lines (P). + ParmRindex + // The ParmUpCursor [parm_up_cursor, cuu] string capability is the up #1 lines (P*). + ParmUpCursor + // The PkeyKey [pkey_key, pfkey] string capability is the program function key #1 to type string #2. + PkeyKey + // The PkeyLocal [pkey_local, pfloc] string capability is the program function key #1 to execute string #2. + PkeyLocal + // The PkeyXmit [pkey_xmit, pfx] string capability is the program function key #1 to transmit string #2. + PkeyXmit + // The PrintScreen [print_screen, mc0] string capability is the print contents of screen. + PrintScreen + // The PrtrOff [prtr_off, mc4] string capability is the turn off printer. + PrtrOff + // The PrtrOn [prtr_on, mc5] string capability is the turn on printer. + PrtrOn + // The RepeatChar [repeat_char, rep] string capability is the repeat char #1 #2 times (P*). + RepeatChar + // The Reset1string [reset_1string, rs1] string capability is the reset string. + Reset1string + // The Reset2string [reset_2string, rs2] string capability is the reset string. + Reset2string + // The Reset3string [reset_3string, rs3] string capability is the reset string. + Reset3string + // The ResetFile [reset_file, rf] string capability is the name of reset file. + ResetFile + // The RestoreCursor [restore_cursor, rc] string capability is the restore cursor to position of last save_cursor. + RestoreCursor + // The RowAddress [row_address, vpa] string capability is the vertical position #1 absolute (P). + RowAddress + // The SaveCursor [save_cursor, sc] string capability is the save current cursor position (P). + SaveCursor + // The ScrollForward [scroll_forward, ind] string capability is the scroll text up (P). + ScrollForward + // The ScrollReverse [scroll_reverse, ri] string capability is the scroll text down (P). + ScrollReverse + // The SetAttributes [set_attributes, sgr] string capability is the define video attributes #1-#9 (PG9). + SetAttributes + // The SetTab [set_tab, hts] string capability is the set a tab in every row, current columns. + SetTab + // The SetWindow [set_window, wind] string capability is the current window is lines #1-#2 cols #3-#4. + SetWindow + // The Tab [tab, ht] string capability is the tab to next 8-space hardware tab stop. + Tab + // The ToStatusLine [to_status_line, tsl] string capability is the move to status line, column #1. + ToStatusLine + // The UnderlineChar [underline_char, uc] string capability is the underline char and move past it. + UnderlineChar + // The UpHalfLine [up_half_line, hu] string capability is the half a line up. + UpHalfLine + // The InitProg [init_prog, iprog] string capability is the path name of program for initialization. + InitProg + // The KeyA1 [key_a1, ka1] string capability is the upper left of keypad. + KeyA1 + // The KeyA3 [key_a3, ka3] string capability is the upper right of keypad. + KeyA3 + // The KeyB2 [key_b2, kb2] string capability is the center of keypad. + KeyB2 + // The KeyC1 [key_c1, kc1] string capability is the lower left of keypad. + KeyC1 + // The KeyC3 [key_c3, kc3] string capability is the lower right of keypad. + KeyC3 + // The PrtrNon [prtr_non, mc5p] string capability is the turn on printer for #1 bytes. + PrtrNon + // The CharPadding [char_padding, rmp] string capability is the like ip but when in insert mode. + CharPadding + // The AcsChars [acs_chars, acsc] string capability is the graphics charset pairs, based on vt100. + AcsChars + // The PlabNorm [plab_norm, pln] string capability is the program label #1 to show string #2. + PlabNorm + // The KeyBtab [key_btab, kcbt] string capability is the back-tab key. + KeyBtab + // The EnterXonMode [enter_xon_mode, smxon] string capability is the turn on xon/xoff handshaking. + EnterXonMode + // The ExitXonMode [exit_xon_mode, rmxon] string capability is the turn off xon/xoff handshaking. + ExitXonMode + // The EnterAmMode [enter_am_mode, smam] string capability is the turn on automatic margins. + EnterAmMode + // The ExitAmMode [exit_am_mode, rmam] string capability is the turn off automatic margins. + ExitAmMode + // The XonCharacter [xon_character, xonc] string capability is the XON character. + XonCharacter + // The XoffCharacter [xoff_character, xoffc] string capability is the XOFF character. + XoffCharacter + // The EnaAcs [ena_acs, enacs] string capability is the enable alternate char set. + EnaAcs + // The LabelOn [label_on, smln] string capability is the turn on soft labels. + LabelOn + // The LabelOff [label_off, rmln] string capability is the turn off soft labels. + LabelOff + // The KeyBeg [key_beg, kbeg] string capability is the begin key. + KeyBeg + // The KeyCancel [key_cancel, kcan] string capability is the cancel key. + KeyCancel + // The KeyClose [key_close, kclo] string capability is the close key. + KeyClose + // The KeyCommand [key_command, kcmd] string capability is the command key. + KeyCommand + // The KeyCopy [key_copy, kcpy] string capability is the copy key. + KeyCopy + // The KeyCreate [key_create, kcrt] string capability is the create key. + KeyCreate + // The KeyEnd [key_end, kend] string capability is the end key. + KeyEnd + // The KeyEnter [key_enter, kent] string capability is the enter/send key. + KeyEnter + // The KeyExit [key_exit, kext] string capability is the exit key. + KeyExit + // The KeyFind [key_find, kfnd] string capability is the find key. + KeyFind + // The KeyHelp [key_help, khlp] string capability is the help key. + KeyHelp + // The KeyMark [key_mark, kmrk] string capability is the mark key. + KeyMark + // The KeyMessage [key_message, kmsg] string capability is the message key. + KeyMessage + // The KeyMove [key_move, kmov] string capability is the move key. + KeyMove + // The KeyNext [key_next, knxt] string capability is the next key. + KeyNext + // The KeyOpen [key_open, kopn] string capability is the open key. + KeyOpen + // The KeyOptions [key_options, kopt] string capability is the options key. + KeyOptions + // The KeyPrevious [key_previous, kprv] string capability is the previous key. + KeyPrevious + // The KeyPrint [key_print, kprt] string capability is the print key. + KeyPrint + // The KeyRedo [key_redo, krdo] string capability is the redo key. + KeyRedo + // The KeyReference [key_reference, kref] string capability is the reference key. + KeyReference + // The KeyRefresh [key_refresh, krfr] string capability is the refresh key. + KeyRefresh + // The KeyReplace [key_replace, krpl] string capability is the replace key. + KeyReplace + // The KeyRestart [key_restart, krst] string capability is the restart key. + KeyRestart + // The KeyResume [key_resume, kres] string capability is the resume key. + KeyResume + // The KeySave [key_save, ksav] string capability is the save key. + KeySave + // The KeySuspend [key_suspend, kspd] string capability is the suspend key. + KeySuspend + // The KeyUndo [key_undo, kund] string capability is the undo key. + KeyUndo + // The KeySbeg [key_sbeg, kBEG] string capability is the shifted begin key. + KeySbeg + // The KeyScancel [key_scancel, kCAN] string capability is the shifted cancel key. + KeyScancel + // The KeyScommand [key_scommand, kCMD] string capability is the shifted command key. + KeyScommand + // The KeyScopy [key_scopy, kCPY] string capability is the shifted copy key. + KeyScopy + // The KeyScreate [key_screate, kCRT] string capability is the shifted create key. + KeyScreate + // The KeySdc [key_sdc, kDC] string capability is the shifted delete-character key. + KeySdc + // The KeySdl [key_sdl, kDL] string capability is the shifted delete-line key. + KeySdl + // The KeySelect [key_select, kslt] string capability is the select key. + KeySelect + // The KeySend [key_send, kEND] string capability is the shifted end key. + KeySend + // The KeySeol [key_seol, kEOL] string capability is the shifted clear-to-end-of-line key. + KeySeol + // The KeySexit [key_sexit, kEXT] string capability is the shifted exit key. + KeySexit + // The KeySfind [key_sfind, kFND] string capability is the shifted find key. + KeySfind + // The KeyShelp [key_shelp, kHLP] string capability is the shifted help key. + KeyShelp + // The KeyShome [key_shome, kHOM] string capability is the shifted home key. + KeyShome + // The KeySic [key_sic, kIC] string capability is the shifted insert-character key. + KeySic + // The KeySleft [key_sleft, kLFT] string capability is the shifted left-arrow key. + KeySleft + // The KeySmessage [key_smessage, kMSG] string capability is the shifted message key. + KeySmessage + // The KeySmove [key_smove, kMOV] string capability is the shifted move key. + KeySmove + // The KeySnext [key_snext, kNXT] string capability is the shifted next key. + KeySnext + // The KeySoptions [key_soptions, kOPT] string capability is the shifted options key. + KeySoptions + // The KeySprevious [key_sprevious, kPRV] string capability is the shifted previous key. + KeySprevious + // The KeySprint [key_sprint, kPRT] string capability is the shifted print key. + KeySprint + // The KeySredo [key_sredo, kRDO] string capability is the shifted redo key. + KeySredo + // The KeySreplace [key_sreplace, kRPL] string capability is the shifted replace key. + KeySreplace + // The KeySright [key_sright, kRIT] string capability is the shifted right-arrow key. + KeySright + // The KeySrsume [key_srsume, kRES] string capability is the shifted resume key. + KeySrsume + // The KeySsave [key_ssave, kSAV] string capability is the shifted save key. + KeySsave + // The KeySsuspend [key_ssuspend, kSPD] string capability is the shifted suspend key. + KeySsuspend + // The KeySundo [key_sundo, kUND] string capability is the shifted undo key. + KeySundo + // The ReqForInput [req_for_input, rfi] string capability is the send next input char (for ptys). + ReqForInput + // The KeyF11 [key_f11, kf11] string capability is the F11 function key. + KeyF11 + // The KeyF12 [key_f12, kf12] string capability is the F12 function key. + KeyF12 + // The KeyF13 [key_f13, kf13] string capability is the F13 function key. + KeyF13 + // The KeyF14 [key_f14, kf14] string capability is the F14 function key. + KeyF14 + // The KeyF15 [key_f15, kf15] string capability is the F15 function key. + KeyF15 + // The KeyF16 [key_f16, kf16] string capability is the F16 function key. + KeyF16 + // The KeyF17 [key_f17, kf17] string capability is the F17 function key. + KeyF17 + // The KeyF18 [key_f18, kf18] string capability is the F18 function key. + KeyF18 + // The KeyF19 [key_f19, kf19] string capability is the F19 function key. + KeyF19 + // The KeyF20 [key_f20, kf20] string capability is the F20 function key. + KeyF20 + // The KeyF21 [key_f21, kf21] string capability is the F21 function key. + KeyF21 + // The KeyF22 [key_f22, kf22] string capability is the F22 function key. + KeyF22 + // The KeyF23 [key_f23, kf23] string capability is the F23 function key. + KeyF23 + // The KeyF24 [key_f24, kf24] string capability is the F24 function key. + KeyF24 + // The KeyF25 [key_f25, kf25] string capability is the F25 function key. + KeyF25 + // The KeyF26 [key_f26, kf26] string capability is the F26 function key. + KeyF26 + // The KeyF27 [key_f27, kf27] string capability is the F27 function key. + KeyF27 + // The KeyF28 [key_f28, kf28] string capability is the F28 function key. + KeyF28 + // The KeyF29 [key_f29, kf29] string capability is the F29 function key. + KeyF29 + // The KeyF30 [key_f30, kf30] string capability is the F30 function key. + KeyF30 + // The KeyF31 [key_f31, kf31] string capability is the F31 function key. + KeyF31 + // The KeyF32 [key_f32, kf32] string capability is the F32 function key. + KeyF32 + // The KeyF33 [key_f33, kf33] string capability is the F33 function key. + KeyF33 + // The KeyF34 [key_f34, kf34] string capability is the F34 function key. + KeyF34 + // The KeyF35 [key_f35, kf35] string capability is the F35 function key. + KeyF35 + // The KeyF36 [key_f36, kf36] string capability is the F36 function key. + KeyF36 + // The KeyF37 [key_f37, kf37] string capability is the F37 function key. + KeyF37 + // The KeyF38 [key_f38, kf38] string capability is the F38 function key. + KeyF38 + // The KeyF39 [key_f39, kf39] string capability is the F39 function key. + KeyF39 + // The KeyF40 [key_f40, kf40] string capability is the F40 function key. + KeyF40 + // The KeyF41 [key_f41, kf41] string capability is the F41 function key. + KeyF41 + // The KeyF42 [key_f42, kf42] string capability is the F42 function key. + KeyF42 + // The KeyF43 [key_f43, kf43] string capability is the F43 function key. + KeyF43 + // The KeyF44 [key_f44, kf44] string capability is the F44 function key. + KeyF44 + // The KeyF45 [key_f45, kf45] string capability is the F45 function key. + KeyF45 + // The KeyF46 [key_f46, kf46] string capability is the F46 function key. + KeyF46 + // The KeyF47 [key_f47, kf47] string capability is the F47 function key. + KeyF47 + // The KeyF48 [key_f48, kf48] string capability is the F48 function key. + KeyF48 + // The KeyF49 [key_f49, kf49] string capability is the F49 function key. + KeyF49 + // The KeyF50 [key_f50, kf50] string capability is the F50 function key. + KeyF50 + // The KeyF51 [key_f51, kf51] string capability is the F51 function key. + KeyF51 + // The KeyF52 [key_f52, kf52] string capability is the F52 function key. + KeyF52 + // The KeyF53 [key_f53, kf53] string capability is the F53 function key. + KeyF53 + // The KeyF54 [key_f54, kf54] string capability is the F54 function key. + KeyF54 + // The KeyF55 [key_f55, kf55] string capability is the F55 function key. + KeyF55 + // The KeyF56 [key_f56, kf56] string capability is the F56 function key. + KeyF56 + // The KeyF57 [key_f57, kf57] string capability is the F57 function key. + KeyF57 + // The KeyF58 [key_f58, kf58] string capability is the F58 function key. + KeyF58 + // The KeyF59 [key_f59, kf59] string capability is the F59 function key. + KeyF59 + // The KeyF60 [key_f60, kf60] string capability is the F60 function key. + KeyF60 + // The KeyF61 [key_f61, kf61] string capability is the F61 function key. + KeyF61 + // The KeyF62 [key_f62, kf62] string capability is the F62 function key. + KeyF62 + // The KeyF63 [key_f63, kf63] string capability is the F63 function key. + KeyF63 + // The ClrBol [clr_bol, el1] string capability is the Clear to beginning of line. + ClrBol + // The ClearMargins [clear_margins, mgc] string capability is the clear right and left soft margins. + ClearMargins + // The SetLeftMargin [set_left_margin, smgl] string capability is the set left soft margin at current column. (ML is not in BSD termcap). + SetLeftMargin + // The SetRightMargin [set_right_margin, smgr] string capability is the set right soft margin at current column. + SetRightMargin + // The LabelFormat [label_format, fln] string capability is the label format. + LabelFormat + // The SetClock [set_clock, sclk] string capability is the set clock, #1 hrs #2 mins #3 secs. + SetClock + // The DisplayClock [display_clock, dclk] string capability is the display clock. + DisplayClock + // The RemoveClock [remove_clock, rmclk] string capability is the remove clock. + RemoveClock + // The CreateWindow [create_window, cwin] string capability is the define a window #1 from #2,#3 to #4,#5. + CreateWindow + // The GotoWindow [goto_window, wingo] string capability is the go to window #1. + GotoWindow + // The Hangup [hangup, hup] string capability is the hang-up phone. + Hangup + // The DialPhone [dial_phone, dial] string capability is the dial number #1. + DialPhone + // The QuickDial [quick_dial, qdial] string capability is the dial number #1 without checking. + QuickDial + // The Tone [tone, tone] string capability is the select touch tone dialing. + Tone + // The Pulse [pulse, pulse] string capability is the select pulse dialing. + Pulse + // The FlashHook [flash_hook, hook] string capability is the flash switch hook. + FlashHook + // The FixedPause [fixed_pause, pause] string capability is the pause for 2-3 seconds. + FixedPause + // The WaitTone [wait_tone, wait] string capability is the wait for dial-tone. + WaitTone + // The User0 [user0, u0] string capability is the User string #0. + User0 + // The User1 [user1, u1] string capability is the User string #1. + User1 + // The User2 [user2, u2] string capability is the User string #2. + User2 + // The User3 [user3, u3] string capability is the User string #3. + User3 + // The User4 [user4, u4] string capability is the User string #4. + User4 + // The User5 [user5, u5] string capability is the User string #5. + User5 + // The User6 [user6, u6] string capability is the User string #6. + User6 + // The User7 [user7, u7] string capability is the User string #7. + User7 + // The User8 [user8, u8] string capability is the User string #8. + User8 + // The User9 [user9, u9] string capability is the User string #9. + User9 + // The OrigPair [orig_pair, op] string capability is the Set default pair to its original value. + OrigPair + // The OrigColors [orig_colors, oc] string capability is the Set all color pairs to the original ones. + OrigColors + // The InitializeColor [initialize_color, initc] string capability is the initialize color #1 to (#2,#3,#4). + InitializeColor + // The InitializePair [initialize_pair, initp] string capability is the Initialize color pair #1 to fg=(#2,#3,#4), bg=(#5,#6,#7). + InitializePair + // The SetColorPair [set_color_pair, scp] string capability is the Set current color pair to #1. + SetColorPair + // The SetForeground [set_foreground, setf] string capability is the Set foreground color #1. + SetForeground + // The SetBackground [set_background, setb] string capability is the Set background color #1. + SetBackground + // The ChangeCharPitch [change_char_pitch, cpi] string capability is the Change number of characters per inch to #1. + ChangeCharPitch + // The ChangeLinePitch [change_line_pitch, lpi] string capability is the Change number of lines per inch to #1. + ChangeLinePitch + // The ChangeResHorz [change_res_horz, chr] string capability is the Change horizontal resolution to #1. + ChangeResHorz + // The ChangeResVert [change_res_vert, cvr] string capability is the Change vertical resolution to #1. + ChangeResVert + // The DefineChar [define_char, defc] string capability is the Define a character #1, #2 dots wide, descender #3. + DefineChar + // The EnterDoublewideMode [enter_doublewide_mode, swidm] string capability is the Enter double-wide mode. + EnterDoublewideMode + // The EnterDraftQuality [enter_draft_quality, sdrfq] string capability is the Enter draft-quality mode. + EnterDraftQuality + // The EnterItalicsMode [enter_italics_mode, sitm] string capability is the Enter italic mode. + EnterItalicsMode + // The EnterLeftwardMode [enter_leftward_mode, slm] string capability is the Start leftward carriage motion. + EnterLeftwardMode + // The EnterMicroMode [enter_micro_mode, smicm] string capability is the Start micro-motion mode. + EnterMicroMode + // The EnterNearLetterQuality [enter_near_letter_quality, snlq] string capability is the Enter NLQ mode. + EnterNearLetterQuality + // The EnterNormalQuality [enter_normal_quality, snrmq] string capability is the Enter normal-quality mode. + EnterNormalQuality + // The EnterShadowMode [enter_shadow_mode, sshm] string capability is the Enter shadow-print mode. + EnterShadowMode + // The EnterSubscriptMode [enter_subscript_mode, ssubm] string capability is the Enter subscript mode. + EnterSubscriptMode + // The EnterSuperscriptMode [enter_superscript_mode, ssupm] string capability is the Enter superscript mode. + EnterSuperscriptMode + // The EnterUpwardMode [enter_upward_mode, sum] string capability is the Start upward carriage motion. + EnterUpwardMode + // The ExitDoublewideMode [exit_doublewide_mode, rwidm] string capability is the End double-wide mode. + ExitDoublewideMode + // The ExitItalicsMode [exit_italics_mode, ritm] string capability is the End italic mode. + ExitItalicsMode + // The ExitLeftwardMode [exit_leftward_mode, rlm] string capability is the End left-motion mode. + ExitLeftwardMode + // The ExitMicroMode [exit_micro_mode, rmicm] string capability is the End micro-motion mode. + ExitMicroMode + // The ExitShadowMode [exit_shadow_mode, rshm] string capability is the End shadow-print mode. + ExitShadowMode + // The ExitSubscriptMode [exit_subscript_mode, rsubm] string capability is the End subscript mode. + ExitSubscriptMode + // The ExitSuperscriptMode [exit_superscript_mode, rsupm] string capability is the End superscript mode. + ExitSuperscriptMode + // The ExitUpwardMode [exit_upward_mode, rum] string capability is the End reverse character motion. + ExitUpwardMode + // The MicroColumnAddress [micro_column_address, mhpa] string capability is the Like column_address in micro mode. + MicroColumnAddress + // The MicroDown [micro_down, mcud1] string capability is the Like cursor_down in micro mode. + MicroDown + // The MicroLeft [micro_left, mcub1] string capability is the Like cursor_left in micro mode. + MicroLeft + // The MicroRight [micro_right, mcuf1] string capability is the Like cursor_right in micro mode. + MicroRight + // The MicroRowAddress [micro_row_address, mvpa] string capability is the Like row_address #1 in micro mode. + MicroRowAddress + // The MicroUp [micro_up, mcuu1] string capability is the Like cursor_up in micro mode. + MicroUp + // The OrderOfPins [order_of_pins, porder] string capability is the Match software bits to print-head pins. + OrderOfPins + // The ParmDownMicro [parm_down_micro, mcud] string capability is the Like parm_down_cursor in micro mode. + ParmDownMicro + // The ParmLeftMicro [parm_left_micro, mcub] string capability is the Like parm_left_cursor in micro mode. + ParmLeftMicro + // The ParmRightMicro [parm_right_micro, mcuf] string capability is the Like parm_right_cursor in micro mode. + ParmRightMicro + // The ParmUpMicro [parm_up_micro, mcuu] string capability is the Like parm_up_cursor in micro mode. + ParmUpMicro + // The SelectCharSet [select_char_set, scs] string capability is the Select character set, #1. + SelectCharSet + // The SetBottomMargin [set_bottom_margin, smgb] string capability is the Set bottom margin at current line. + SetBottomMargin + // The SetBottomMarginParm [set_bottom_margin_parm, smgbp] string capability is the Set bottom margin at line #1 or (if smgtp is not given) #2 lines from bottom. + SetBottomMarginParm + // The SetLeftMarginParm [set_left_margin_parm, smglp] string capability is the Set left (right) margin at column #1. + SetLeftMarginParm + // The SetRightMarginParm [set_right_margin_parm, smgrp] string capability is the Set right margin at column #1. + SetRightMarginParm + // The SetTopMargin [set_top_margin, smgt] string capability is the Set top margin at current line. + SetTopMargin + // The SetTopMarginParm [set_top_margin_parm, smgtp] string capability is the Set top (bottom) margin at row #1. + SetTopMarginParm + // The StartBitImage [start_bit_image, sbim] string capability is the Start printing bit image graphics. + StartBitImage + // The StartCharSetDef [start_char_set_def, scsd] string capability is the Start character set definition #1, with #2 characters in the set. + StartCharSetDef + // The StopBitImage [stop_bit_image, rbim] string capability is the Stop printing bit image graphics. + StopBitImage + // The StopCharSetDef [stop_char_set_def, rcsd] string capability is the End definition of character set #1. + StopCharSetDef + // The SubscriptCharacters [subscript_characters, subcs] string capability is the List of subscriptable characters. + SubscriptCharacters + // The SuperscriptCharacters [superscript_characters, supcs] string capability is the List of superscriptable characters. + SuperscriptCharacters + // The TheseCauseCr [these_cause_cr, docr] string capability is the Printing any of these characters causes CR. + TheseCauseCr + // The ZeroMotion [zero_motion, zerom] string capability is the No motion for subsequent character. + ZeroMotion + // The CharSetNames [char_set_names, csnm] string capability is the Produce #1'th item from list of character set names. + CharSetNames + // The KeyMouse [key_mouse, kmous] string capability is the Mouse event has occurred. + KeyMouse + // The MouseInfo [mouse_info, minfo] string capability is the Mouse status information. + MouseInfo + // The ReqMousePos [req_mouse_pos, reqmp] string capability is the Request mouse position. + ReqMousePos + // The GetMouse [get_mouse, getm] string capability is the Curses should get button events, parameter #1 not documented. + GetMouse + // The SetAForeground [set_a_foreground, setaf] string capability is the Set foreground color to #1, using ANSI escape. + SetAForeground + // The SetABackground [set_a_background, setab] string capability is the Set background color to #1, using ANSI escape. + SetABackground + // The PkeyPlab [pkey_plab, pfxl] string capability is the Program function key #1 to type string #2 and show string #3. + PkeyPlab + // The DeviceType [device_type, devt] string capability is the Indicate language/codeset support. + DeviceType + // The CodeSetInit [code_set_init, csin] string capability is the Init sequence for multiple codesets. + CodeSetInit + // The Set0DesSeq [set0_des_seq, s0ds] string capability is the Shift to codeset 0 (EUC set 0, ASCII). + Set0DesSeq + // The Set1DesSeq [set1_des_seq, s1ds] string capability is the Shift to codeset 1. + Set1DesSeq + // The Set2DesSeq [set2_des_seq, s2ds] string capability is the Shift to codeset 2. + Set2DesSeq + // The Set3DesSeq [set3_des_seq, s3ds] string capability is the Shift to codeset 3. + Set3DesSeq + // The SetLrMargin [set_lr_margin, smglr] string capability is the Set both left and right margins to #1, #2. (ML is not in BSD termcap). + SetLrMargin + // The SetTbMargin [set_tb_margin, smgtb] string capability is the Sets both top and bottom margins to #1, #2. + SetTbMargin + // The BitImageRepeat [bit_image_repeat, birep] string capability is the Repeat bit image cell #1 #2 times. + BitImageRepeat + // The BitImageNewline [bit_image_newline, binel] string capability is the Move to next row of the bit image. + BitImageNewline + // The BitImageCarriageReturn [bit_image_carriage_return, bicr] string capability is the Move to beginning of same row. + BitImageCarriageReturn + // The ColorNames [color_names, colornm] string capability is the Give name for color #1. + ColorNames + // The DefineBitImageRegion [define_bit_image_region, defbi] string capability is the Define rectangular bit image region. + DefineBitImageRegion + // The EndBitImageRegion [end_bit_image_region, endbi] string capability is the End a bit-image region. + EndBitImageRegion + // The SetColorBand [set_color_band, setcolor] string capability is the Change to ribbon color #1. + SetColorBand + // The SetPageLength [set_page_length, slines] string capability is the Set page length to #1 lines. + SetPageLength + // The DisplayPcChar [display_pc_char, dispc] string capability is the Display PC character #1. + DisplayPcChar + // The EnterPcCharsetMode [enter_pc_charset_mode, smpch] string capability is the Enter PC character display mode. + EnterPcCharsetMode + // The ExitPcCharsetMode [exit_pc_charset_mode, rmpch] string capability is the Exit PC character display mode. + ExitPcCharsetMode + // The EnterScancodeMode [enter_scancode_mode, smsc] string capability is the Enter PC scancode mode. + EnterScancodeMode + // The ExitScancodeMode [exit_scancode_mode, rmsc] string capability is the Exit PC scancode mode. + ExitScancodeMode + // The PcTermOptions [pc_term_options, pctrm] string capability is the PC terminal options. + PcTermOptions + // The ScancodeEscape [scancode_escape, scesc] string capability is the Escape for scancode emulation. + ScancodeEscape + // The AltScancodeEsc [alt_scancode_esc, scesa] string capability is the Alternate escape for scancode emulation. + AltScancodeEsc + // The EnterHorizontalHlMode [enter_horizontal_hl_mode, ehhlm] string capability is the Enter horizontal highlight mode. + EnterHorizontalHlMode + // The EnterLeftHlMode [enter_left_hl_mode, elhlm] string capability is the Enter left highlight mode. + EnterLeftHlMode + // The EnterLowHlMode [enter_low_hl_mode, elohlm] string capability is the Enter low highlight mode. + EnterLowHlMode + // The EnterRightHlMode [enter_right_hl_mode, erhlm] string capability is the Enter right highlight mode. + EnterRightHlMode + // The EnterTopHlMode [enter_top_hl_mode, ethlm] string capability is the Enter top highlight mode. + EnterTopHlMode + // The EnterVerticalHlMode [enter_vertical_hl_mode, evhlm] string capability is the Enter vertical highlight mode. + EnterVerticalHlMode + // The SetAAttributes [set_a_attributes, sgr1] string capability is the Define second set of video attributes #1-#6. + SetAAttributes + // The SetPglenInch [set_pglen_inch, slength] string capability is the Set page length to #1 hundredth of an inch (some implementations use sL for termcap). + SetPglenInch + // The TermcapInit2 [termcap_init2, OTi2] string capability is the secondary initialization string. + TermcapInit2 + // The TermcapReset [termcap_reset, OTrs] string capability is the terminal reset string. + TermcapReset + // The LinefeedIfNotLf [linefeed_if_not_lf, OTnl] string capability is the use to move down. + LinefeedIfNotLf + // The BackspaceIfNotBs [backspace_if_not_bs, OTbc] string capability is the move left, if not ^H. + BackspaceIfNotBs + // The OtherNonFunctionKeys [other_non_function_keys, OTko] string capability is the list of self-mapped keycaps. + OtherNonFunctionKeys + // The ArrowKeyMap [arrow_key_map, OTma] string capability is the map motion-keys for vi version 2. + ArrowKeyMap + // The AcsUlcorner [acs_ulcorner, OTG2] string capability is the single upper left. + AcsUlcorner + // The AcsLlcorner [acs_llcorner, OTG3] string capability is the single lower left. + AcsLlcorner + // The AcsUrcorner [acs_urcorner, OTG1] string capability is the single upper right. + AcsUrcorner + // The AcsLrcorner [acs_lrcorner, OTG4] string capability is the single lower right. + AcsLrcorner + // The AcsLtee [acs_ltee, OTGR] string capability is the tee pointing right. + AcsLtee + // The AcsRtee [acs_rtee, OTGL] string capability is the tee pointing left. + AcsRtee + // The AcsBtee [acs_btee, OTGU] string capability is the tee pointing up. + AcsBtee + // The AcsTtee [acs_ttee, OTGD] string capability is the tee pointing down. + AcsTtee + // The AcsHline [acs_hline, OTGH] string capability is the single horizontal line. + AcsHline + // The AcsVline [acs_vline, OTGV] string capability is the single vertical line. + AcsVline + // The AcsPlus [acs_plus, OTGC] string capability is the single intersection. + AcsPlus + // The MemoryLock [memory_lock, meml] string capability is the lock memory above cursor. + MemoryLock + // The MemoryUnlock [memory_unlock, memu] string capability is the unlock memory. + MemoryUnlock + // The BoxChars1 [box_chars_1, box1] string capability is the box characters primary set. + BoxChars1 +) +const ( + // CapCountBool is the count of bool capabilities. + CapCountBool = ReturnDoesClrEol + 1 + // CapCountNum is the count of num capabilities. + CapCountNum = NumberOfFunctionKeys + 1 + // CapCountString is the count of string capabilities. + CapCountString = BoxChars1 + 1 +) + +// boolCapNames are the bool term cap names. +var boolCapNames = [...]string{ + "auto_left_margin", "bw", + "auto_right_margin", "am", + "no_esc_ctlc", "xsb", + "ceol_standout_glitch", "xhp", + "eat_newline_glitch", "xenl", + "erase_overstrike", "eo", + "generic_type", "gn", + "hard_copy", "hc", + "has_meta_key", "km", + "has_status_line", "hs", + "insert_null_glitch", "in", + "memory_above", "da", + "memory_below", "db", + "move_insert_mode", "mir", + "move_standout_mode", "msgr", + "over_strike", "os", + "status_line_esc_ok", "eslok", + "dest_tabs_magic_smso", "xt", + "tilde_glitch", "hz", + "transparent_underline", "ul", + "xon_xoff", "xon", + "needs_xon_xoff", "nxon", + "prtr_silent", "mc5i", + "hard_cursor", "chts", + "non_rev_rmcup", "nrrmc", + "no_pad_char", "npc", + "non_dest_scroll_region", "ndscr", + "can_change", "ccc", + "back_color_erase", "bce", + "hue_lightness_saturation", "hls", + "col_addr_glitch", "xhpa", + "cr_cancels_micro_mode", "crxm", + "has_print_wheel", "daisy", + "row_addr_glitch", "xvpa", + "semi_auto_right_margin", "sam", + "cpi_changes_res", "cpix", + "lpi_changes_res", "lpix", + "backspaces_with_bs", "OTbs", + "crt_no_scrolling", "OTns", + "no_correctly_working_cr", "OTnc", + "gnu_has_meta_key", "OTMT", + "linefeed_is_newline", "OTNL", + "has_hardware_tabs", "OTpt", + "return_does_clr_eol", "OTxr", +} + +// numCapNames are the num term cap names. +var numCapNames = [...]string{ + "columns", "cols", + "init_tabs", "it", + "lines", "lines", + "lines_of_memory", "lm", + "magic_cookie_glitch", "xmc", + "padding_baud_rate", "pb", + "virtual_terminal", "vt", + "width_status_line", "wsl", + "num_labels", "nlab", + "label_height", "lh", + "label_width", "lw", + "max_attributes", "ma", + "maximum_windows", "wnum", + "max_colors", "colors", + "max_pairs", "pairs", + "no_color_video", "ncv", + "buffer_capacity", "bufsz", + "dot_vert_spacing", "spinv", + "dot_horz_spacing", "spinh", + "max_micro_address", "maddr", + "max_micro_jump", "mjump", + "micro_col_size", "mcs", + "micro_line_size", "mls", + "number_of_pins", "npins", + "output_res_char", "orc", + "output_res_line", "orl", + "output_res_horz_inch", "orhi", + "output_res_vert_inch", "orvi", + "print_rate", "cps", + "wide_char_size", "widcs", + "buttons", "btns", + "bit_image_entwining", "bitwin", + "bit_image_type", "bitype", + "magic_cookie_glitch_ul", "OTug", + "carriage_return_delay", "OTdC", + "new_line_delay", "OTdN", + "backspace_delay", "OTdB", + "horizontal_tab_delay", "OTdT", + "number_of_function_keys", "OTkn", +} + +// stringCapNames are the string term cap names. +var stringCapNames = [...]string{ + "back_tab", "cbt", + "bell", "bel", + "carriage_return", "cr", + "change_scroll_region", "csr", + "clear_all_tabs", "tbc", + "clear_screen", "clear", + "clr_eol", "el", + "clr_eos", "ed", + "column_address", "hpa", + "command_character", "cmdch", + "cursor_address", "cup", + "cursor_down", "cud1", + "cursor_home", "home", + "cursor_invisible", "civis", + "cursor_left", "cub1", + "cursor_mem_address", "mrcup", + "cursor_normal", "cnorm", + "cursor_right", "cuf1", + "cursor_to_ll", "ll", + "cursor_up", "cuu1", + "cursor_visible", "cvvis", + "delete_character", "dch1", + "delete_line", "dl1", + "dis_status_line", "dsl", + "down_half_line", "hd", + "enter_alt_charset_mode", "smacs", + "enter_blink_mode", "blink", + "enter_bold_mode", "bold", + "enter_ca_mode", "smcup", + "enter_delete_mode", "smdc", + "enter_dim_mode", "dim", + "enter_insert_mode", "smir", + "enter_secure_mode", "invis", + "enter_protected_mode", "prot", + "enter_reverse_mode", "rev", + "enter_standout_mode", "smso", + "enter_underline_mode", "smul", + "erase_chars", "ech", + "exit_alt_charset_mode", "rmacs", + "exit_attribute_mode", "sgr0", + "exit_ca_mode", "rmcup", + "exit_delete_mode", "rmdc", + "exit_insert_mode", "rmir", + "exit_standout_mode", "rmso", + "exit_underline_mode", "rmul", + "flash_screen", "flash", + "form_feed", "ff", + "from_status_line", "fsl", + "init_1string", "is1", + "init_2string", "is2", + "init_3string", "is3", + "init_file", "if", + "insert_character", "ich1", + "insert_line", "il1", + "insert_padding", "ip", + "key_backspace", "kbs", + "key_catab", "ktbc", + "key_clear", "kclr", + "key_ctab", "kctab", + "key_dc", "kdch1", + "key_dl", "kdl1", + "key_down", "kcud1", + "key_eic", "krmir", + "key_eol", "kel", + "key_eos", "ked", + "key_f0", "kf0", + "key_f1", "kf1", + "key_f10", "kf10", + "key_f2", "kf2", + "key_f3", "kf3", + "key_f4", "kf4", + "key_f5", "kf5", + "key_f6", "kf6", + "key_f7", "kf7", + "key_f8", "kf8", + "key_f9", "kf9", + "key_home", "khome", + "key_ic", "kich1", + "key_il", "kil1", + "key_left", "kcub1", + "key_ll", "kll", + "key_npage", "knp", + "key_ppage", "kpp", + "key_right", "kcuf1", + "key_sf", "kind", + "key_sr", "kri", + "key_stab", "khts", + "key_up", "kcuu1", + "keypad_local", "rmkx", + "keypad_xmit", "smkx", + "lab_f0", "lf0", + "lab_f1", "lf1", + "lab_f10", "lf10", + "lab_f2", "lf2", + "lab_f3", "lf3", + "lab_f4", "lf4", + "lab_f5", "lf5", + "lab_f6", "lf6", + "lab_f7", "lf7", + "lab_f8", "lf8", + "lab_f9", "lf9", + "meta_off", "rmm", + "meta_on", "smm", + "newline", "nel", + "pad_char", "pad", + "parm_dch", "dch", + "parm_delete_line", "dl", + "parm_down_cursor", "cud", + "parm_ich", "ich", + "parm_index", "indn", + "parm_insert_line", "il", + "parm_left_cursor", "cub", + "parm_right_cursor", "cuf", + "parm_rindex", "rin", + "parm_up_cursor", "cuu", + "pkey_key", "pfkey", + "pkey_local", "pfloc", + "pkey_xmit", "pfx", + "print_screen", "mc0", + "prtr_off", "mc4", + "prtr_on", "mc5", + "repeat_char", "rep", + "reset_1string", "rs1", + "reset_2string", "rs2", + "reset_3string", "rs3", + "reset_file", "rf", + "restore_cursor", "rc", + "row_address", "vpa", + "save_cursor", "sc", + "scroll_forward", "ind", + "scroll_reverse", "ri", + "set_attributes", "sgr", + "set_tab", "hts", + "set_window", "wind", + "tab", "ht", + "to_status_line", "tsl", + "underline_char", "uc", + "up_half_line", "hu", + "init_prog", "iprog", + "key_a1", "ka1", + "key_a3", "ka3", + "key_b2", "kb2", + "key_c1", "kc1", + "key_c3", "kc3", + "prtr_non", "mc5p", + "char_padding", "rmp", + "acs_chars", "acsc", + "plab_norm", "pln", + "key_btab", "kcbt", + "enter_xon_mode", "smxon", + "exit_xon_mode", "rmxon", + "enter_am_mode", "smam", + "exit_am_mode", "rmam", + "xon_character", "xonc", + "xoff_character", "xoffc", + "ena_acs", "enacs", + "label_on", "smln", + "label_off", "rmln", + "key_beg", "kbeg", + "key_cancel", "kcan", + "key_close", "kclo", + "key_command", "kcmd", + "key_copy", "kcpy", + "key_create", "kcrt", + "key_end", "kend", + "key_enter", "kent", + "key_exit", "kext", + "key_find", "kfnd", + "key_help", "khlp", + "key_mark", "kmrk", + "key_message", "kmsg", + "key_move", "kmov", + "key_next", "knxt", + "key_open", "kopn", + "key_options", "kopt", + "key_previous", "kprv", + "key_print", "kprt", + "key_redo", "krdo", + "key_reference", "kref", + "key_refresh", "krfr", + "key_replace", "krpl", + "key_restart", "krst", + "key_resume", "kres", + "key_save", "ksav", + "key_suspend", "kspd", + "key_undo", "kund", + "key_sbeg", "kBEG", + "key_scancel", "kCAN", + "key_scommand", "kCMD", + "key_scopy", "kCPY", + "key_screate", "kCRT", + "key_sdc", "kDC", + "key_sdl", "kDL", + "key_select", "kslt", + "key_send", "kEND", + "key_seol", "kEOL", + "key_sexit", "kEXT", + "key_sfind", "kFND", + "key_shelp", "kHLP", + "key_shome", "kHOM", + "key_sic", "kIC", + "key_sleft", "kLFT", + "key_smessage", "kMSG", + "key_smove", "kMOV", + "key_snext", "kNXT", + "key_soptions", "kOPT", + "key_sprevious", "kPRV", + "key_sprint", "kPRT", + "key_sredo", "kRDO", + "key_sreplace", "kRPL", + "key_sright", "kRIT", + "key_srsume", "kRES", + "key_ssave", "kSAV", + "key_ssuspend", "kSPD", + "key_sundo", "kUND", + "req_for_input", "rfi", + "key_f11", "kf11", + "key_f12", "kf12", + "key_f13", "kf13", + "key_f14", "kf14", + "key_f15", "kf15", + "key_f16", "kf16", + "key_f17", "kf17", + "key_f18", "kf18", + "key_f19", "kf19", + "key_f20", "kf20", + "key_f21", "kf21", + "key_f22", "kf22", + "key_f23", "kf23", + "key_f24", "kf24", + "key_f25", "kf25", + "key_f26", "kf26", + "key_f27", "kf27", + "key_f28", "kf28", + "key_f29", "kf29", + "key_f30", "kf30", + "key_f31", "kf31", + "key_f32", "kf32", + "key_f33", "kf33", + "key_f34", "kf34", + "key_f35", "kf35", + "key_f36", "kf36", + "key_f37", "kf37", + "key_f38", "kf38", + "key_f39", "kf39", + "key_f40", "kf40", + "key_f41", "kf41", + "key_f42", "kf42", + "key_f43", "kf43", + "key_f44", "kf44", + "key_f45", "kf45", + "key_f46", "kf46", + "key_f47", "kf47", + "key_f48", "kf48", + "key_f49", "kf49", + "key_f50", "kf50", + "key_f51", "kf51", + "key_f52", "kf52", + "key_f53", "kf53", + "key_f54", "kf54", + "key_f55", "kf55", + "key_f56", "kf56", + "key_f57", "kf57", + "key_f58", "kf58", + "key_f59", "kf59", + "key_f60", "kf60", + "key_f61", "kf61", + "key_f62", "kf62", + "key_f63", "kf63", + "clr_bol", "el1", + "clear_margins", "mgc", + "set_left_margin", "smgl", + "set_right_margin", "smgr", + "label_format", "fln", + "set_clock", "sclk", + "display_clock", "dclk", + "remove_clock", "rmclk", + "create_window", "cwin", + "goto_window", "wingo", + "hangup", "hup", + "dial_phone", "dial", + "quick_dial", "qdial", + "tone", "tone", + "pulse", "pulse", + "flash_hook", "hook", + "fixed_pause", "pause", + "wait_tone", "wait", + "user0", "u0", + "user1", "u1", + "user2", "u2", + "user3", "u3", + "user4", "u4", + "user5", "u5", + "user6", "u6", + "user7", "u7", + "user8", "u8", + "user9", "u9", + "orig_pair", "op", + "orig_colors", "oc", + "initialize_color", "initc", + "initialize_pair", "initp", + "set_color_pair", "scp", + "set_foreground", "setf", + "set_background", "setb", + "change_char_pitch", "cpi", + "change_line_pitch", "lpi", + "change_res_horz", "chr", + "change_res_vert", "cvr", + "define_char", "defc", + "enter_doublewide_mode", "swidm", + "enter_draft_quality", "sdrfq", + "enter_italics_mode", "sitm", + "enter_leftward_mode", "slm", + "enter_micro_mode", "smicm", + "enter_near_letter_quality", "snlq", + "enter_normal_quality", "snrmq", + "enter_shadow_mode", "sshm", + "enter_subscript_mode", "ssubm", + "enter_superscript_mode", "ssupm", + "enter_upward_mode", "sum", + "exit_doublewide_mode", "rwidm", + "exit_italics_mode", "ritm", + "exit_leftward_mode", "rlm", + "exit_micro_mode", "rmicm", + "exit_shadow_mode", "rshm", + "exit_subscript_mode", "rsubm", + "exit_superscript_mode", "rsupm", + "exit_upward_mode", "rum", + "micro_column_address", "mhpa", + "micro_down", "mcud1", + "micro_left", "mcub1", + "micro_right", "mcuf1", + "micro_row_address", "mvpa", + "micro_up", "mcuu1", + "order_of_pins", "porder", + "parm_down_micro", "mcud", + "parm_left_micro", "mcub", + "parm_right_micro", "mcuf", + "parm_up_micro", "mcuu", + "select_char_set", "scs", + "set_bottom_margin", "smgb", + "set_bottom_margin_parm", "smgbp", + "set_left_margin_parm", "smglp", + "set_right_margin_parm", "smgrp", + "set_top_margin", "smgt", + "set_top_margin_parm", "smgtp", + "start_bit_image", "sbim", + "start_char_set_def", "scsd", + "stop_bit_image", "rbim", + "stop_char_set_def", "rcsd", + "subscript_characters", "subcs", + "superscript_characters", "supcs", + "these_cause_cr", "docr", + "zero_motion", "zerom", + "char_set_names", "csnm", + "key_mouse", "kmous", + "mouse_info", "minfo", + "req_mouse_pos", "reqmp", + "get_mouse", "getm", + "set_a_foreground", "setaf", + "set_a_background", "setab", + "pkey_plab", "pfxl", + "device_type", "devt", + "code_set_init", "csin", + "set0_des_seq", "s0ds", + "set1_des_seq", "s1ds", + "set2_des_seq", "s2ds", + "set3_des_seq", "s3ds", + "set_lr_margin", "smglr", + "set_tb_margin", "smgtb", + "bit_image_repeat", "birep", + "bit_image_newline", "binel", + "bit_image_carriage_return", "bicr", + "color_names", "colornm", + "define_bit_image_region", "defbi", + "end_bit_image_region", "endbi", + "set_color_band", "setcolor", + "set_page_length", "slines", + "display_pc_char", "dispc", + "enter_pc_charset_mode", "smpch", + "exit_pc_charset_mode", "rmpch", + "enter_scancode_mode", "smsc", + "exit_scancode_mode", "rmsc", + "pc_term_options", "pctrm", + "scancode_escape", "scesc", + "alt_scancode_esc", "scesa", + "enter_horizontal_hl_mode", "ehhlm", + "enter_left_hl_mode", "elhlm", + "enter_low_hl_mode", "elohlm", + "enter_right_hl_mode", "erhlm", + "enter_top_hl_mode", "ethlm", + "enter_vertical_hl_mode", "evhlm", + "set_a_attributes", "sgr1", + "set_pglen_inch", "slength", + "termcap_init2", "OTi2", + "termcap_reset", "OTrs", + "linefeed_if_not_lf", "OTnl", + "backspace_if_not_bs", "OTbc", + "other_non_function_keys", "OTko", + "arrow_key_map", "OTma", + "acs_ulcorner", "OTG2", + "acs_llcorner", "OTG3", + "acs_urcorner", "OTG1", + "acs_lrcorner", "OTG4", + "acs_ltee", "OTGR", + "acs_rtee", "OTGL", + "acs_btee", "OTGU", + "acs_ttee", "OTGD", + "acs_hline", "OTGH", + "acs_vline", "OTGV", + "acs_plus", "OTGC", + "memory_lock", "meml", + "memory_unlock", "memu", + "box_chars_1", "box1", +} diff --git a/vendor/github.com/xo/terminfo/color.go b/vendor/github.com/xo/terminfo/color.go new file mode 100644 index 00000000..76c439fc --- /dev/null +++ b/vendor/github.com/xo/terminfo/color.go @@ -0,0 +1,88 @@ +package terminfo + +import ( + "os" + "strconv" + "strings" +) + +// ColorLevel is the color level supported by a terminal. +type ColorLevel uint + +// ColorLevel values. +const ( + ColorLevelNone ColorLevel = iota + ColorLevelBasic + ColorLevelHundreds + ColorLevelMillions +) + +// String satisfies the Stringer interface. +func (c ColorLevel) String() string { + switch c { + case ColorLevelBasic: + return "basic" + case ColorLevelHundreds: + return "hundreds" + case ColorLevelMillions: + return "millions" + } + return "none" +} + +// ChromaFormatterName returns the github.com/alecthomas/chroma compatible +// formatter name for the color level. +func (c ColorLevel) ChromaFormatterName() string { + switch c { + case ColorLevelBasic: + return "terminal" + case ColorLevelHundreds: + return "terminal256" + case ColorLevelMillions: + return "terminal16m" + } + return "noop" +} + +// ColorLevelFromEnv returns the color level COLORTERM, FORCE_COLOR, +// TERM_PROGRAM, or determined from the TERM environment variable. +func ColorLevelFromEnv() (ColorLevel, error) { + // check for overriding environment variables + colorTerm, termProg, forceColor := os.Getenv("COLORTERM"), os.Getenv("TERM_PROGRAM"), os.Getenv("FORCE_COLOR") + switch { + case strings.Contains(colorTerm, "truecolor") || strings.Contains(colorTerm, "24bit") || termProg == "Hyper": + return ColorLevelMillions, nil + case colorTerm != "" || forceColor != "": + return ColorLevelBasic, nil + case termProg == "Apple_Terminal": + return ColorLevelHundreds, nil + case termProg == "iTerm.app": + ver := os.Getenv("TERM_PROGRAM_VERSION") + if ver == "" { + return ColorLevelHundreds, nil + } + i, err := strconv.Atoi(strings.Split(ver, ".")[0]) + if err != nil { + return ColorLevelNone, ErrInvalidTermProgramVersion + } + if i == 3 { + return ColorLevelMillions, nil + } + return ColorLevelHundreds, nil + } + // otherwise determine from TERM's max_colors capability + if term := os.Getenv("TERM"); term != "" { + ti, err := Load(term) + if err != nil { + return ColorLevelNone, err + } + v, ok := ti.Nums[MaxColors] + switch { + case !ok || v <= 16: + return ColorLevelNone, nil + case ok && v >= 256: + return ColorLevelHundreds, nil + } + } + return ColorLevelBasic, nil +} diff --git a/vendor/github.com/xo/terminfo/dec.go b/vendor/github.com/xo/terminfo/dec.go new file mode 100644 index 00000000..dacc88e3 --- /dev/null +++ b/vendor/github.com/xo/terminfo/dec.go @@ -0,0 +1,245 @@ +package terminfo + +import ( + "sort" +) + +const ( + // maxFileLength is the max file length. + maxFileLength = 4096 + // magic is the file magic for terminfo files. + magic = 0o432 + // magicExtended is the file magic for terminfo files with the extended + // number format. + magicExtended = 0o1036 +) + +// header fields. +const ( + fieldMagic = iota + fieldNameSize + fieldBoolCount + fieldNumCount + fieldStringCount + fieldTableSize +) + +// header extended fields. +const ( + fieldExtBoolCount = iota + fieldExtNumCount + fieldExtStringCount + fieldExtOffsetCount + fieldExtTableSize +) + +// hasInvalidCaps determines if the capabilities in h are invalid. +func hasInvalidCaps(h []int) bool { + return h[fieldBoolCount] > CapCountBool || + h[fieldNumCount] > CapCountNum || + h[fieldStringCount] > CapCountString +} + +// capLength returns the total length of the capabilities in bytes. +func capLength(h []int) int { + return h[fieldNameSize] + + h[fieldBoolCount] + + (h[fieldNameSize]+h[fieldBoolCount])%2 + // account for word align + h[fieldNumCount]*2 + + h[fieldStringCount]*2 + + h[fieldTableSize] +} + +// hasInvalidExtOffset determines if the extended offset field is valid. +func hasInvalidExtOffset(h []int) bool { + return h[fieldExtBoolCount]+ + h[fieldExtNumCount]+ + h[fieldExtStringCount]*2 != h[fieldExtOffsetCount] +} + +// extCapLength returns the total length of extended capabilities in bytes. +func extCapLength(h []int, numWidth int) int { + return h[fieldExtBoolCount] + + h[fieldExtBoolCount]%2 + // account for word align + h[fieldExtNumCount]*(numWidth/8) + + h[fieldExtOffsetCount]*2 + + h[fieldExtTableSize] +} + +// findNull finds the position of null in buf. +func findNull(buf []byte, i int) int { + for ; i < len(buf); i++ { + if buf[i] == 0 { + return i + } + } + return -1 +} + +// readStrings decodes n strings from string data table buf using the indexes in idx. +func readStrings(idx []int, buf []byte, n int) (map[int][]byte, int, error) { + var last int + m := make(map[int][]byte) + for i := 0; i < n; i++ { + start := idx[i] + if start < 0 { + continue + } + if end := findNull(buf, start); end != -1 { + m[i], last = buf[start:end], end+1 + } else { + return nil, 0, ErrInvalidStringTable + } + } + return m, last, nil +} + +// decoder holds state info while decoding a terminfo file. +type decoder struct { + buf []byte + pos int + n int +} + +// readBytes reads the next n bytes of buf, incrementing pos by n. +func (d *decoder) readBytes(n int) ([]byte, error) { + if d.n < d.pos+n { + return nil, ErrUnexpectedFileEnd + } + n, d.pos = d.pos, d.pos+n + return d.buf[n:d.pos], nil +} + +// readInts reads n number of ints with width w. +func (d *decoder) readInts(n, w int) ([]int, error) { + w /= 8 + l := n * w + buf, err := d.readBytes(l) + if err != nil { + return nil, err + } + // align + d.pos += d.pos % 2 + z := make([]int, n) + for i, j := 0, 0; i < l; i, j = i+w, j+1 { + switch w { + case 1: + z[i] = int(buf[i]) + case 2: + z[j] = int(int16(buf[i+1])<<8 | int16(buf[i])) + case 4: + z[j] = int(buf[i+3])<<24 | int(buf[i+2])<<16 | int(buf[i+1])<<8 | int(buf[i]) + } + } + return z, nil +} + +// readBools reads the next n bools. +func (d *decoder) readBools(n int) (map[int]bool, map[int]bool, error) { + buf, err := d.readInts(n, 8) + if err != nil { + return nil, nil, err + } + // process + bools, boolsM := make(map[int]bool), make(map[int]bool) + for i, b := range buf { + bools[i] = b == 1 + if int8(b) == -2 { + boolsM[i] = true + } + } + return bools, boolsM, nil +} + +// readNums reads the next n nums. +func (d *decoder) readNums(n, w int) (map[int]int, map[int]bool, error) { + buf, err := d.readInts(n, w) + if err != nil { + return nil, nil, err + } + // process + nums, numsM := make(map[int]int), make(map[int]bool) + for i := 0; i < n; i++ { + nums[i] = buf[i] + if buf[i] == -2 { + numsM[i] = true + } + } + return nums, numsM, nil +} + +// readStringTable reads the string data for n strings and the accompanying data +// table of length sz. +func (d *decoder) readStringTable(n, sz int) ([][]byte, []int, error) { + buf, err := d.readInts(n, 16) + if err != nil { + return nil, nil, err + } + // read string data table + data, err := d.readBytes(sz) + if err != nil { + return nil, nil, err + } + // align + d.pos += d.pos % 2 + // process + s := make([][]byte, n) + var m []int + for i := 0; i < n; i++ { + start := buf[i] + if start == -2 { + m = append(m, i) + } else if start >= 0 { + if end := findNull(data, start); end != -1 { + s[i] = data[start:end] + } else { + return nil, nil, ErrInvalidStringTable + } + } + } + return s, m, nil +} + +// readStrings reads the next n strings and processes the string data table of +// length sz. +func (d *decoder) readStrings(n, sz int) (map[int][]byte, map[int]bool, error) { + s, m, err := d.readStringTable(n, sz) + if err != nil { + return nil, nil, err + } + strs := make(map[int][]byte) + for k, v := range s { + if k == AcsChars { + v = canonicalizeAscChars(v) + } + strs[k] = v + } + strsM := make(map[int]bool, len(m)) + for _, k := range m { + strsM[k] = true + } + return strs, strsM, nil +} + +// canonicalizeAscChars reorders chars to be unique, in order. +// +// see repair_ascc in ncurses-6.3/progs/dump_entry.c +func canonicalizeAscChars(z []byte) []byte { + var c []byte + enc := make(map[byte]byte, len(z)/2) + for i := 0; i < len(z); i += 2 { + if _, ok := enc[z[i]]; !ok { + a, b := z[i], z[i+1] + // log.Printf(">>> a: %d %c, b: %d %c", a, a, b, b) + c, enc[a] = append(c, b), b + } + } + sort.Slice(c, func(i, j int) bool { + return c[i] < c[j] + }) + r := make([]byte, 2*len(c)) + for i := 0; i < len(c); i++ { + r[i*2], r[i*2+1] = c[i], enc[c[i]] + } + return r +} diff --git a/vendor/github.com/xo/terminfo/load.go b/vendor/github.com/xo/terminfo/load.go new file mode 100644 index 00000000..d7cd266c --- /dev/null +++ b/vendor/github.com/xo/terminfo/load.go @@ -0,0 +1,64 @@ +package terminfo + +import ( + "os" + "os/user" + "path" + "strings" + "sync" +) + +// termCache is the terminfo cache. +var termCache = struct { + db map[string]*Terminfo + sync.RWMutex +}{ + db: make(map[string]*Terminfo), +} + +// Load follows the behavior described in terminfo(5) to find correct the +// terminfo file using the name, reads the file and then returns a Terminfo +// struct that describes the file. +func Load(name string) (*Terminfo, error) { + if name == "" { + return nil, ErrEmptyTermName + } + termCache.RLock() + ti, ok := termCache.db[name] + termCache.RUnlock() + if ok { + return ti, nil + } + var checkDirs []string + // check $TERMINFO + if dir := os.Getenv("TERMINFO"); dir != "" { + checkDirs = append(checkDirs, dir) + } + // check $HOME/.terminfo + u, err := user.Current() + if err != nil { + return nil, err + } + checkDirs = append(checkDirs, path.Join(u.HomeDir, ".terminfo")) + // check $TERMINFO_DIRS + if dirs := os.Getenv("TERMINFO_DIRS"); dirs != "" { + checkDirs = append(checkDirs, strings.Split(dirs, ":")...) + } + // check fallback directories + checkDirs = append(checkDirs, "/etc/terminfo", "/lib/terminfo", "/usr/share/terminfo") + for _, dir := range checkDirs { + ti, err = Open(dir, name) + if err != nil && err != ErrFileNotFound && !os.IsNotExist(err) { + return nil, err + } else if err == nil { + return ti, nil + } + } + return nil, ErrDatabaseDirectoryNotFound +} + +// LoadFromEnv loads the terminal info based on the name contained in +// environment variable TERM. +func LoadFromEnv() (*Terminfo, error) { + return Load(os.Getenv("TERM")) +} diff --git a/vendor/github.com/xo/terminfo/param.go b/vendor/github.com/xo/terminfo/param.go new file mode 100644 index 00000000..ed4cb86b --- /dev/null +++ b/vendor/github.com/xo/terminfo/param.go @@ -0,0 +1,405 @@ +package terminfo + +import ( + "bytes" + "fmt" + "io" + "strconv" + "strings" + "sync" +) + +// parametizer represents the a scan state for a parameterized string. +type parametizer struct { + // z is the string to parameterize + z []byte + // pos is the current position in s. + pos int + // nest is the current nest level. + nest int + // s is the variable stack. + s stack + // skipElse keeps the state of skipping else. + skipElse bool + // buf is the result buffer. + buf *bytes.Buffer + // params are the parameters to interpolate. + params [9]interface{} + // vars are dynamic variables. + vars [26]interface{} +} + +// staticVars are the static, global variables. +var staticVars = struct { + vars [26]interface{} + sync.Mutex +}{} + +var parametizerPool = sync.Pool{ + New: func() interface{} { + p := new(parametizer) + p.buf = bytes.NewBuffer(make([]byte, 0, 45)) + return p + }, +} + +// newParametizer returns a new initialized parametizer from the pool. +func newParametizer(z []byte) *parametizer { + p := parametizerPool.Get().(*parametizer) + p.z = z + return p +} + +// reset resets the parametizer. +func (p *parametizer) reset() { + p.pos, p.nest = 0, 0 + p.s.reset() + p.buf.Reset() + p.params, p.vars = [9]interface{}{}, [26]interface{}{} + parametizerPool.Put(p) +} + +// stateFn represents the state of the scanner as a function that returns the +// next state. +type stateFn func() stateFn + +// exec executes the parameterizer, interpolating the supplied parameters. +func (p *parametizer) exec() string { + for state := p.scanTextFn; state != nil; { + state = state() + } + return p.buf.String() +} + +// peek returns the next byte. +func (p *parametizer) peek() (byte, error) { + if p.pos >= len(p.z) { + return 0, io.EOF + } + return p.z[p.pos], nil +} + +// writeFrom writes the characters from ppos to pos to the buffer. +func (p *parametizer) writeFrom(ppos int) { + if p.pos > ppos { + // append remaining characters. + p.buf.Write(p.z[ppos:p.pos]) + } +} + +func (p *parametizer) scanTextFn() stateFn { + ppos := p.pos + for { + ch, err := p.peek() + if err != nil { + p.writeFrom(ppos) + return nil + } + if ch == '%' { + p.writeFrom(ppos) + p.pos++ + return p.scanCodeFn + } + p.pos++ + } +} + +func (p *parametizer) scanCodeFn() stateFn { + ch, err := p.peek() + if err != nil { + return nil + } + switch ch { + case '%': + p.buf.WriteByte('%') + case ':': + // this character is used to avoid interpreting "%-" and "%+" as operators. + // the next character is where the format really begins. + p.pos++ + _, err = p.peek() + if err != nil { + return nil + } + return p.scanFormatFn + case '#', ' ', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.': + return p.scanFormatFn + case 'o': + p.buf.WriteString(strconv.FormatInt(int64(p.s.popInt()), 8)) + case 'd': + p.buf.WriteString(strconv.Itoa(p.s.popInt())) + case 'x': + p.buf.WriteString(strconv.FormatInt(int64(p.s.popInt()), 16)) + case 'X': + p.buf.WriteString(strings.ToUpper(strconv.FormatInt(int64(p.s.popInt()), 16))) + case 's': + p.buf.WriteString(p.s.popString()) + case 'c': + p.buf.WriteByte(p.s.popByte()) + case 'p': + p.pos++ + return p.pushParamFn + case 'P': + p.pos++ + return p.setDsVarFn + case 'g': + p.pos++ + return p.getDsVarFn + case '\'': + p.pos++ + ch, err = p.peek() + if err != nil { + return nil + } + p.s.push(ch) + // skip the '\'' + p.pos++ + case '{': + p.pos++ + return p.pushIntfn + case 'l': + p.s.push(len(p.s.popString())) + case '+': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai + bi) + case '-': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai - bi) + case '*': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai * bi) + case '/': + bi, ai := p.s.popInt(), p.s.popInt() + if bi != 0 { + p.s.push(ai / bi) + } else { + p.s.push(0) + } + case 'm': + bi, ai := p.s.popInt(), p.s.popInt() + if bi != 0 { + p.s.push(ai % bi) + } else { + p.s.push(0) + } + case '&': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai & bi) + case '|': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai | bi) + case '^': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai ^ bi) + case '=': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai == bi) + case '>': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai > bi) + case '<': + bi, ai := p.s.popInt(), p.s.popInt() + p.s.push(ai < bi) + case 'A': + bi, ai := p.s.popBool(), p.s.popBool() + p.s.push(ai && bi) + case 'O': + bi, ai := p.s.popBool(), p.s.popBool() + p.s.push(ai || bi) + case '!': + p.s.push(!p.s.popBool()) + case '~': + p.s.push(^p.s.popInt()) + case 'i': + for i := range p.params[:2] { + if n, ok := p.params[i].(int); ok { + p.params[i] = n + 1 + } + } + case '?', ';': + case 't': + return p.scanThenFn + case 'e': + p.skipElse = true + return p.skipTextFn + } + p.pos++ + return p.scanTextFn +} + +func (p *parametizer) scanFormatFn() stateFn { + // the character was already read, so no need to check the error. + ch, _ := p.peek() + // 6 should be the maximum length of a format string, for example "%:-9.9d". + f := []byte{'%', ch, 0, 0, 0, 0} + var err error + for { + p.pos++ + ch, err = p.peek() + if err != nil { + return nil + } + f = append(f, ch) + switch ch { + case 'o', 'd', 'x', 'X': + fmt.Fprintf(p.buf, string(f), p.s.popInt()) + break + case 's': + fmt.Fprintf(p.buf, string(f), p.s.popString()) + break + case 'c': + fmt.Fprintf(p.buf, string(f), p.s.popByte()) + break + } + } + p.pos++ + return p.scanTextFn +} + +func (p *parametizer) pushParamFn() stateFn { + ch, err := p.peek() + if err != nil { + return nil + } + if ai := int(ch - '1'); ai >= 0 && ai < len(p.params) { + p.s.push(p.params[ai]) + } else { + p.s.push(0) + } + // skip the '}' + p.pos++ + return p.scanTextFn +} + +func (p *parametizer) setDsVarFn() stateFn { + ch, err := p.peek() + if err != nil { + return nil + } + if ch >= 'A' && ch <= 'Z' { + staticVars.Lock() + staticVars.vars[int(ch-'A')] = p.s.pop() + staticVars.Unlock() + } else if ch >= 'a' && ch <= 'z' { + p.vars[int(ch-'a')] = p.s.pop() + } + p.pos++ + return p.scanTextFn +} + +func (p *parametizer) getDsVarFn() stateFn { + ch, err := p.peek() + if err != nil { + return nil + } + var a byte + if ch >= 'A' && ch <= 'Z' { + a = 'A' + } else if ch >= 'a' && ch <= 'z' { + a = 'a' + } + staticVars.Lock() + p.s.push(staticVars.vars[int(ch-a)]) + staticVars.Unlock() + p.pos++ + return p.scanTextFn +} + +func (p *parametizer) pushIntfn() stateFn { + var ai int + for { + ch, err := p.peek() + if err != nil { + return nil + } + p.pos++ + if ch < '0' || ch > '9' { + p.s.push(ai) + return p.scanTextFn + } + ai = (ai * 10) + int(ch-'0') + } +} + +func (p *parametizer) scanThenFn() stateFn { + p.pos++ + if p.s.popBool() { + return p.scanTextFn + } + p.skipElse = false + return p.skipTextFn +} + +func (p *parametizer) skipTextFn() stateFn { + for { + ch, err := p.peek() + if err != nil { + return nil + } + p.pos++ + if ch == '%' { + break + } + } + if p.skipElse { + return p.skipElseFn + } + return p.skipThenFn +} + +func (p *parametizer) skipThenFn() stateFn { + ch, err := p.peek() + if err != nil { + return nil + } + p.pos++ + switch ch { + case ';': + if p.nest == 0 { + return p.scanTextFn + } + p.nest-- + case '?': + p.nest++ + case 'e': + if p.nest == 0 { + return p.scanTextFn + } + } + return p.skipTextFn +} + +func (p *parametizer) skipElseFn() stateFn { + ch, err := p.peek() + if err != nil { + return nil + } + p.pos++ + switch ch { + case ';': + if p.nest == 0 { + return p.scanTextFn + } + p.nest-- + case '?': + p.nest++ + } + return p.skipTextFn +} + +// Printf evaluates a parameterized terminfo value z, interpolating params. +func Printf(z []byte, params ...interface{}) string { + p := newParametizer(z) + defer p.reset() + // make sure we always have 9 parameters -- makes it easier + // later to skip checks and its faster + for i := 0; i < len(p.params) && i < len(params); i++ { + p.params[i] = params[i] + } + return p.exec() +} + +// Fprintf evaluates a parameterized terminfo value z, interpolating params and +// writing to w. +func Fprintf(w io.Writer, z []byte, params ...interface{}) { + w.Write([]byte(Printf(z, params...))) +} diff --git a/vendor/github.com/xo/terminfo/stack.go b/vendor/github.com/xo/terminfo/stack.go new file mode 100644 index 00000000..a6de3950 --- /dev/null +++ b/vendor/github.com/xo/terminfo/stack.go @@ -0,0 +1,48 @@ +package terminfo + +type stack []interface{} + +func (s *stack) push(v interface{}) { + *s = append(*s, v) +} + +func (s *stack) pop() interface{} { + if len(*s) == 0 { + return nil + } + v := (*s)[len(*s)-1] + *s = (*s)[:len(*s)-1] + return v +} + +func (s *stack) popInt() int { + if i, ok := s.pop().(int); ok { + return i + } + return 0 +} + +func (s *stack) popBool() bool { + if b, ok := s.pop().(bool); ok { + return b + } + return false +} + +func (s *stack) popByte() byte { + if b, ok := s.pop().(byte); ok { + return b + } + return 0 +} + +func (s *stack) popString() string { + if a, ok := s.pop().(string); ok { + return a + } + return "" +} + +func (s *stack) reset() { + *s = (*s)[:0] +} diff --git a/vendor/github.com/xo/terminfo/terminfo.go b/vendor/github.com/xo/terminfo/terminfo.go new file mode 100644 index 00000000..69e3b606 --- /dev/null +++ b/vendor/github.com/xo/terminfo/terminfo.go @@ -0,0 +1,479 @@ +// Package terminfo implements reading terminfo files in pure go. +package terminfo + +//go:generate go run gen.go + +import ( + "io" + "io/ioutil" + "path" + "strconv" + "strings" +) + +// Error is a terminfo error. +type Error string + +// Error satisfies the error interface. +func (err Error) Error() string { + return string(err) +} + +const ( + // ErrInvalidFileSize is the invalid file size error. + ErrInvalidFileSize Error = "invalid file size" + // ErrUnexpectedFileEnd is the unexpected file end error. + ErrUnexpectedFileEnd Error = "unexpected file end" + // ErrInvalidStringTable is the invalid string table error. + ErrInvalidStringTable Error = "invalid string table" + // ErrInvalidMagic is the invalid magic error. + ErrInvalidMagic Error = "invalid magic" + // ErrInvalidHeader is the invalid header error. + ErrInvalidHeader Error = "invalid header" + // ErrInvalidNames is the invalid names error. + ErrInvalidNames Error = "invalid names" + // ErrInvalidExtendedHeader is the invalid extended header error. + ErrInvalidExtendedHeader Error = "invalid extended header" + // ErrEmptyTermName is the empty term name error. + ErrEmptyTermName Error = "empty term name" + // ErrDatabaseDirectoryNotFound is the database directory not found error. + ErrDatabaseDirectoryNotFound Error = "database directory not found" + // ErrFileNotFound is the file not found error. + ErrFileNotFound Error = "file not found" + // ErrInvalidTermProgramVersion is the invalid TERM_PROGRAM_VERSION error. + ErrInvalidTermProgramVersion Error = "invalid TERM_PROGRAM_VERSION" +) + +// Terminfo describes a terminal's capabilities. +type Terminfo struct { + // File is the original source file. + File string + // Names are the provided cap names. + Names []string + // Bools are the bool capabilities. + Bools map[int]bool + // BoolsM are the missing bool capabilities. + BoolsM map[int]bool + // Nums are the num capabilities. + Nums map[int]int + // NumsM are the missing num capabilities. + NumsM map[int]bool + // Strings are the string capabilities. + Strings map[int][]byte + // StringsM are the missing string capabilities. + StringsM map[int]bool + // ExtBools are the extended bool capabilities. + ExtBools map[int]bool + // ExtBoolsNames is the map of extended bool capabilities to their index. + ExtBoolNames map[int][]byte + // ExtNums are the extended num capabilities. + ExtNums map[int]int + // ExtNumsNames is the map of extended num capabilities to their index. + ExtNumNames map[int][]byte + // ExtStrings are the extended string capabilities. + ExtStrings map[int][]byte + // ExtStringsNames is the map of extended string capabilities to their index. + ExtStringNames map[int][]byte +} + +// Decode decodes the terminfo data contained in buf. +func Decode(buf []byte) (*Terminfo, error) { + var err error + // check max file length + if len(buf) >= maxFileLength { + return nil, ErrInvalidFileSize + } + d := &decoder{ + buf: buf, + n: len(buf), + } + // read header + h, err := d.readInts(6, 16) + if err != nil { + return nil, err + } + var numWidth int + // check magic + switch { + case h[fieldMagic] == magic: + numWidth = 16 + case h[fieldMagic] == magicExtended: + numWidth = 32 + default: + return nil, ErrInvalidMagic + } + // check header + if hasInvalidCaps(h) { + return nil, ErrInvalidHeader + } + // check remaining length + if d.n-d.pos < capLength(h) { + return nil, ErrUnexpectedFileEnd + } + // read names + names, err := d.readBytes(h[fieldNameSize]) + if err != nil { + return nil, err + } + // check name is terminated properly + i := findNull(names, 0) + if i == -1 { + return nil, ErrInvalidNames + } + names = names[:i] + // read bool caps + bools, boolsM, err := d.readBools(h[fieldBoolCount]) + if err != nil { + return nil, err + } + // read num caps + nums, numsM, err := d.readNums(h[fieldNumCount], numWidth) + if err != nil { + return nil, err + } + // read string caps + strs, strsM, err := d.readStrings(h[fieldStringCount], h[fieldTableSize]) + if err != nil { + return nil, err + } + ti := &Terminfo{ + Names: strings.Split(string(names), "|"), + Bools: bools, + BoolsM: boolsM, + Nums: nums, + NumsM: numsM, + Strings: strs, + StringsM: strsM, + } + // at the end of file, so no extended caps + if d.pos >= d.n { + return ti, nil + } + // decode extended header + eh, err := d.readInts(5, 16) + if err != nil { + return nil, err + } + // check extended offset field + if hasInvalidExtOffset(eh) { + return nil, ErrInvalidExtendedHeader + } + // check extended cap lengths + if d.n-d.pos != extCapLength(eh, numWidth) { + return nil, ErrInvalidExtendedHeader + } + // read extended bool caps + ti.ExtBools, _, err = d.readBools(eh[fieldExtBoolCount]) + if err != nil { + return nil, err + } + // read extended num caps + ti.ExtNums, _, err = d.readNums(eh[fieldExtNumCount], numWidth) + if err != nil { + return nil, err + } + // read extended string data table indexes + extIndexes, err := d.readInts(eh[fieldExtOffsetCount], 16) + if err != nil { + return nil, err + } + // read string data table + extData, err := d.readBytes(eh[fieldExtTableSize]) + if err != nil { + return nil, err + } + // precautionary check that exactly at end of file + if d.pos != d.n { + return nil, ErrUnexpectedFileEnd + } + var last int + // read extended string caps + ti.ExtStrings, last, err = readStrings(extIndexes, extData, eh[fieldExtStringCount]) + if err != nil { + return nil, err + } + extIndexes, extData = extIndexes[eh[fieldExtStringCount]:], extData[last:] + // read extended bool names + ti.ExtBoolNames, _, err = readStrings(extIndexes, extData, eh[fieldExtBoolCount]) + if err != nil { + return nil, err + } + extIndexes = extIndexes[eh[fieldExtBoolCount]:] + // read extended num names + ti.ExtNumNames, _, err = readStrings(extIndexes, extData, eh[fieldExtNumCount]) + if err != nil { + return nil, err + } + extIndexes = extIndexes[eh[fieldExtNumCount]:] + // read extended string names + ti.ExtStringNames, _, err = readStrings(extIndexes, extData, eh[fieldExtStringCount]) + if err != nil { + return nil, err + } + // extIndexes = extIndexes[eh[fieldExtStringCount]:] + return ti, nil +} + +// Open reads the terminfo file name from the specified directory dir. +func Open(dir, name string) (*Terminfo, error) { + var err error + var buf []byte + var filename string + for _, f := range []string{ + path.Join(dir, name[0:1], name), + path.Join(dir, strconv.FormatUint(uint64(name[0]), 16), name), + } { + buf, err = ioutil.ReadFile(f) + if err == nil { + filename = f + break + } + } + if buf == nil { + return nil, ErrFileNotFound + } + // decode + ti, err := Decode(buf) + if err != nil { + return nil, err + } + // save original file name + ti.File = filename + // add to cache + termCache.Lock() + for _, n := range ti.Names { + termCache.db[n] = ti + } + termCache.Unlock() + return ti, nil +} + +// boolCaps returns all bool and extended capabilities using f to format the +// index key. +func (ti *Terminfo) boolCaps(f func(int) string, extended bool) map[string]bool { + m := make(map[string]bool, len(ti.Bools)+len(ti.ExtBools)) + if !extended { + for k, v := range ti.Bools { + m[f(k)] = v + } + } else { + for k, v := range ti.ExtBools { + m[string(ti.ExtBoolNames[k])] = v + } + } + return m +} + +// BoolCaps returns all bool capabilities. +func (ti *Terminfo) BoolCaps() map[string]bool { + return ti.boolCaps(BoolCapName, false) +} + +// BoolCapsShort returns all bool capabilities, using the short name as the +// index. +func (ti *Terminfo) BoolCapsShort() map[string]bool { + return ti.boolCaps(BoolCapNameShort, false) +} + +// ExtBoolCaps returns all extended bool capabilities. +func (ti *Terminfo) ExtBoolCaps() map[string]bool { + return ti.boolCaps(BoolCapName, true) +} + +// ExtBoolCapsShort returns all extended bool capabilities, using the short +// name as the index. +func (ti *Terminfo) ExtBoolCapsShort() map[string]bool { + return ti.boolCaps(BoolCapNameShort, true) +} + +// numCaps returns all num and extended capabilities using f to format the +// index key. +func (ti *Terminfo) numCaps(f func(int) string, extended bool) map[string]int { + m := make(map[string]int, len(ti.Nums)+len(ti.ExtNums)) + if !extended { + for k, v := range ti.Nums { + m[f(k)] = v + } + } else { + for k, v := range ti.ExtNums { + m[string(ti.ExtNumNames[k])] = v + } + } + return m +} + +// NumCaps returns all num capabilities. +func (ti *Terminfo) NumCaps() map[string]int { + return ti.numCaps(NumCapName, false) +} + +// NumCapsShort returns all num capabilities, using the short name as the +// index. +func (ti *Terminfo) NumCapsShort() map[string]int { + return ti.numCaps(NumCapNameShort, false) +} + +// ExtNumCaps returns all extended num capabilities. +func (ti *Terminfo) ExtNumCaps() map[string]int { + return ti.numCaps(NumCapName, true) +} + +// ExtNumCapsShort returns all extended num capabilities, using the short +// name as the index. +func (ti *Terminfo) ExtNumCapsShort() map[string]int { + return ti.numCaps(NumCapNameShort, true) +} + +// stringCaps returns all string and extended capabilities using f to format the +// index key. +func (ti *Terminfo) stringCaps(f func(int) string, extended bool) map[string][]byte { + m := make(map[string][]byte, len(ti.Strings)+len(ti.ExtStrings)) + if !extended { + for k, v := range ti.Strings { + m[f(k)] = v + } + } else { + for k, v := range ti.ExtStrings { + m[string(ti.ExtStringNames[k])] = v + } + } + return m +} + +// StringCaps returns all string capabilities. +func (ti *Terminfo) StringCaps() map[string][]byte { + return ti.stringCaps(StringCapName, false) +} + +// StringCapsShort returns all string capabilities, using the short name as the +// index. +func (ti *Terminfo) StringCapsShort() map[string][]byte { + return ti.stringCaps(StringCapNameShort, false) +} + +// ExtStringCaps returns all extended string capabilities. +func (ti *Terminfo) ExtStringCaps() map[string][]byte { + return ti.stringCaps(StringCapName, true) +} + +// ExtStringCapsShort returns all extended string capabilities, using the short +// name as the index. +func (ti *Terminfo) ExtStringCapsShort() map[string][]byte { + return ti.stringCaps(StringCapNameShort, true) +} + +// Has determines if the bool cap i is present. +func (ti *Terminfo) Has(i int) bool { + return ti.Bools[i] +} + +// Num returns the num cap i, or -1 if not present. +func (ti *Terminfo) Num(i int) int { + n, ok := ti.Nums[i] + if !ok { + return -1 + } + return n +} + +// Printf formats the string cap i, interpolating parameters v. +func (ti *Terminfo) Printf(i int, v ...interface{}) string { + return Printf(ti.Strings[i], v...) +} + +// Fprintf prints the string cap i to writer w, interpolating parameters v. +func (ti *Terminfo) Fprintf(w io.Writer, i int, v ...interface{}) { + Fprintf(w, ti.Strings[i], v...) +} + +// Color takes a foreground and background color and returns string that sets +// them for this terminal. +func (ti *Terminfo) Colorf(fg, bg int, str string) string { + maxColors := int(ti.Nums[MaxColors]) + // map bright colors to lower versions if the color table only holds 8. + if maxColors == 8 { + if fg > 7 && fg < 16 { + fg -= 8 + } + if bg > 7 && bg < 16 { + bg -= 8 + } + } + var s string + if maxColors > fg && fg >= 0 { + s += ti.Printf(SetAForeground, fg) + } + if maxColors > bg && bg >= 0 { + s += ti.Printf(SetABackground, bg) + } + return s + str + ti.Printf(ExitAttributeMode) +} + +// Goto returns a string suitable for addressing the cursor at the given +// row and column. The origin 0, 0 is in the upper left corner of the screen. +func (ti *Terminfo) Goto(row, col int) string { + return Printf(ti.Strings[CursorAddress], row, col) +} + +// Puts emits the string to the writer, but expands inline padding indications +// (of the form $<[delay]> where [delay] is msec) to a suitable number of +// padding characters (usually null bytes) based upon the supplied baud. At +// high baud rates, more padding characters will be inserted. +/*func (ti *Terminfo) Puts(w io.Writer, s string, lines, baud int) (int, error) { + var err error + for { + start := strings.Index(s, "$<") + if start == -1 { + // most strings don't need padding, which is good news! + return io.WriteString(w, s) + } + end := strings.Index(s, ">") + if end == -1 { + // unterminated... just emit bytes unadulterated. + return io.WriteString(w, "$<"+s) + } + var c int + c, err = io.WriteString(w, s[:start]) + if err != nil { + return n + c, err + } + n += c + s = s[start+2:] + val := s[:end] + s = s[end+1:] + var ms int + var dot, mandatory, asterisk bool + unit := 1000 + for _, ch := range val { + switch { + case ch >= '0' && ch <= '9': + ms = (ms * 10) + int(ch-'0') + if dot { + unit *= 10 + } + case ch == '.' && !dot: + dot = true + case ch == '*' && !asterisk: + ms *= lines + asterisk = true + case ch == '/': + mandatory = true + default: + break + } + } + z, pad := ((baud/8)/unit)*ms, ti.Strings[PadChar] + b := make([]byte, len(pad)*z) + for bp := copy(b, pad); bp < len(b); bp *= 2 { + copy(b[bp:], b[:bp]) + } + if (!ti.Bools[XonXoff] && baud > int(ti.Nums[PaddingBaudRate])) || mandatory { + c, err = w.Write(b) + if err != nil { + return n + c, err + } + n += c + } + } + return n, nil +}*/ diff --git a/vendor/golang.design/x/clipboard/.gitignore b/vendor/golang.design/x/clipboard/.gitignore new file mode 100644 index 00000000..66fd13c9 --- /dev/null +++ b/vendor/golang.design/x/clipboard/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/vendor/golang.design/x/clipboard/Dockerfile b/vendor/golang.design/x/clipboard/Dockerfile new file mode 100644 index 00000000..b810346f --- /dev/null +++ b/vendor/golang.design/x/clipboard/Dockerfile @@ -0,0 +1,13 @@ +# Copyright 2021 The golang.design Initiative Authors. +# All rights reserved. Use of this source code is governed +# by a MIT license that can be found in the LICENSE file. +# +# Written by Changkun Ou + +FROM golang:1.24 +RUN apt-get update && apt-get install -y \ + xvfb libx11-dev libegl1-mesa-dev libgles2-mesa-dev \ + && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* +WORKDIR /app +COPY . . +CMD [ "sh", "-c", "./tests/test-docker.sh" ] diff --git a/vendor/golang.design/x/clipboard/LICENSE b/vendor/golang.design/x/clipboard/LICENSE new file mode 100644 index 00000000..7f2bbe29 --- /dev/null +++ b/vendor/golang.design/x/clipboard/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Changkun Ou + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/vendor/golang.design/x/clipboard/README.md b/vendor/golang.design/x/clipboard/README.md new file mode 100644 index 00000000..d7120070 --- /dev/null +++ b/vendor/golang.design/x/clipboard/README.md @@ -0,0 +1,162 @@ +# clipboard [![PkgGoDev](https://pkg.go.dev/badge/golang.design/x/clipboard)](https://pkg.go.dev/golang.design/x/clipboard) ![](https://changkun.de/urlstat?mode=github&repo=golang-design/clipboard) ![clipboard](https://github.com/golang-design/clipboard/workflows/clipboard/badge.svg?branch=main) + +Cross platform (macOS/Linux/Windows/Android/iOS) clipboard package in Go + +```go +import "golang.design/x/clipboard" +``` + +## Features + +- Cross platform supports: **macOS, Linux (X11), Windows, iOS, and Android** +- Copy/paste UTF-8 text +- Copy/paste PNG encoded images (Desktop-only) +- Command `gclip` as a demo application +- Mobile app `gclip-gui` as a demo application + +## API Usage + +Package clipboard provides cross platform clipboard access and supports +macOS/Linux/Windows/Android/iOS platform. Before interacting with the +clipboard, one must call Init to assert if it is possible to use this +package: + +```go +// Init returns an error if the package is not ready for use. +err := clipboard.Init() +if err != nil { + panic(err) +} +``` + +The most common operations are `Read` and `Write`. To use them: + +```go +// write/read text format data of the clipboard, and +// the byte buffer regarding the text are UTF8 encoded. +clipboard.Write(clipboard.FmtText, []byte("text data")) +clipboard.Read(clipboard.FmtText) + +// write/read image format data of the clipboard, and +// the byte buffer regarding the image are PNG encoded. +clipboard.Write(clipboard.FmtImage, []byte("image data")) +clipboard.Read(clipboard.FmtImage) +``` + +Note that read/write regarding image format assumes that the bytes are +PNG encoded since it serves the alpha blending purpose that might be +used in other graphical software. + +In addition, `clipboard.Write` returns a channel that can receive an +empty struct as a signal, which indicates the corresponding write call +to the clipboard is outdated, meaning the clipboard has been overwritten +by others and the previously written data is lost. For instance: + +```go +changed := clipboard.Write(clipboard.FmtText, []byte("text data")) + +select { +case <-changed: + println(`"text data" is no longer available from clipboard.`) +} +``` + +You can ignore the returning channel if you don't need this type of +notification. Furthermore, when you need more than just knowing whether +clipboard data is changed, use the watcher API: + +```go +ch := clipboard.Watch(context.TODO(), clipboard.FmtText) +for data := range ch { + // print out clipboard data whenever it is changed + println(string(data)) +} +``` + +## Demos + +- A command line tool `gclip` for command line clipboard accesses, see document [here](./cmd/gclip/README.md). +- A GUI application `gclip-gui` for functionality verifications on mobile systems, see a document [here](./cmd/gclip-gui/README.md). + + +## Command Usage + +`gclip` command offers the ability to interact with the system clipboard +from the shell. To install: + +```bash +$ go install golang.design/x/clipboard/cmd/gclip@latest +``` + +```bash +$ gclip +gclip is a command that provides clipboard interaction. + +usage: gclip [-copy|-paste] [-f ] + +options: + -copy + copy data to clipboard + -f string + source or destination to a given file path + -paste + paste data from clipboard + +examples: +gclip -paste paste from clipboard and prints the content +gclip -paste -f x.txt paste from clipboard and save as text to x.txt +gclip -paste -f x.png paste from clipboard and save as image to x.png + +cat x.txt | gclip -copy copy content from x.txt to clipboard +gclip -copy -f x.txt copy content from x.txt to clipboard +gclip -copy -f x.png copy x.png as image data to clipboard +``` + +If `-copy` is used, the command will exit when the data is no longer +available from the clipboard. You can always send the command to the +background using a shell `&` operator, for example: + +```bash +$ cat x.txt | gclip -copy & +``` + +## Platform Specific Details + +This package spent efforts to provide cross platform abstraction regarding +accessing system clipboards, but here are a few details you might need to know. + +### Dependency + +- macOS: require Cgo, no dependency + - Linux: require X11 dev package. For instance, install `libx11-dev` or `xorg-dev` or `libX11-devel` to access X window system. + Wayland sessions are currently unsupported; running under Wayland + typically requires an XWayland bridge and `DISPLAY` to be set. +- Windows: no Cgo, no dependency +- iOS/Android: collaborate with [`gomobile`](https://golang.org/x/mobile) + +### Screenshot + +In general, when you need test your implementation regarding images, +There are system level shortcuts to put screenshot image into your system clipboard: + +- On macOS, use `Ctrl+Shift+Cmd+4` +- On Linux/Ubuntu, use `Ctrl+Shift+PrintScreen` +- On Windows, use `Shift+Win+s` + +As described in the API documentation, the package supports read/write +UTF8 encoded plain text or PNG encoded image data. Thus, +the other types of data are not supported yet, i.e. undefined behavior. + +## Who is using this package? + +The main purpose of building this package is to support the +[midgard](https://changkun.de/s/midgard) project, which offers +clipboard-based features like universal clipboard service that syncs +clipboard content across multiple systems, allocating public accessible +for clipboard content, etc. + +To know more projects, check our [wiki](https://github.com/golang-design/clipboard/wiki) page. + +## License + +MIT | © 2021 The golang.design Initiative Authors, written by [Changkun Ou](https://changkun.de). \ No newline at end of file diff --git a/vendor/golang.design/x/clipboard/clipboard.go b/vendor/golang.design/x/clipboard/clipboard.go new file mode 100644 index 00000000..bd7c6984 --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard.go @@ -0,0 +1,155 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +/* +Package clipboard provides cross platform clipboard access and supports +macOS/Linux/Windows/Android/iOS platform. Before interacting with the +clipboard, one must call Init to assert if it is possible to use this +package: + + err := clipboard.Init() + if err != nil { + panic(err) + } + +The most common operations are `Read` and `Write`. To use them: + + // write/read text format data of the clipboard, and + // the byte buffer regarding the text are UTF8 encoded. + clipboard.Write(clipboard.FmtText, []byte("text data")) + clipboard.Read(clipboard.FmtText) + + // write/read image format data of the clipboard, and + // the byte buffer regarding the image are PNG encoded. + clipboard.Write(clipboard.FmtImage, []byte("image data")) + clipboard.Read(clipboard.FmtImage) + +Note that read/write regarding image format assumes that the bytes are +PNG encoded since it serves the alpha blending purpose that might be +used in other graphical software. + +In addition, `clipboard.Write` returns a channel that can receive an +empty struct as a signal, which indicates the corresponding write call +to the clipboard is outdated, meaning the clipboard has been overwritten +by others and the previously written data is lost. For instance: + + changed := clipboard.Write(clipboard.FmtText, []byte("text data")) + + select { + case <-changed: + println(`"text data" is no longer available from clipboard.`) + } + +You can ignore the returning channel if you don't need this type of +notification. Furthermore, when you need more than just knowing whether +clipboard data is changed, use the watcher API: + + ch := clipboard.Watch(context.TODO(), clipboard.FmtText) + for data := range ch { + // print out clipboard data whenever it is changed + println(string(data)) + } +*/ +package clipboard // import "golang.design/x/clipboard" + +import ( + "context" + "errors" + "fmt" + "os" + "sync" +) + +var ( + // activate only for running tests. + debug = false + errUnavailable = errors.New("clipboard unavailable") + errUnsupported = errors.New("unsupported format") + errNoCgo = errors.New("clipboard: cannot use when CGO_ENABLED=0") +) + +// Format represents the format of clipboard data. +type Format int + +// All sorts of supported clipboard data +const ( + // FmtText indicates plain text clipboard format + FmtText Format = iota + // FmtImage indicates image/png clipboard format + FmtImage +) + +var ( + // Due to the limitation on operating systems (such as darwin), + // concurrent read can even cause panic, use a global lock to + // guarantee one read at a time. + lock = sync.Mutex{} + initOnce sync.Once + initError error +) + +// Init initializes the clipboard package. It returns an error +// if the clipboard is not available to use. This may happen if the +// target system lacks required dependency, such as libx11-dev in X11 +// environment. For example, +// +// err := clipboard.Init() +// if err != nil { +// panic(err) +// } +// +// If Init returns an error, any subsequent Read/Write/Watch call +// may result in an unrecoverable panic. +func Init() error { + initOnce.Do(func() { + initError = initialize() + }) + return initError +} + +// Read returns a chunk of bytes of the clipboard data if it presents +// in the desired format t presents. Otherwise, it returns nil. +func Read(t Format) []byte { + lock.Lock() + defer lock.Unlock() + + buf, err := read(t) + if err != nil { + if debug { + fmt.Fprintf(os.Stderr, "read clipboard err: %v\n", err) + } + return nil + } + return buf +} + +// Write writes a given buffer to the clipboard in a specified format. +// Write returned a receive-only channel can receive an empty struct +// as a signal, which indicates the clipboard has been overwritten from +// this write. +// If format t indicates an image, then the given buf assumes +// the image data is PNG encoded. +func Write(t Format, buf []byte) <-chan struct{} { + lock.Lock() + defer lock.Unlock() + + changed, err := write(t, buf) + if err != nil { + if debug { + fmt.Fprintf(os.Stderr, "write to clipboard err: %v\n", err) + } + return nil + } + return changed +} + +// Watch returns a receive-only channel that received the clipboard data +// whenever any change of clipboard data in the desired format happens. +// +// The returned channel will be closed if the given context is canceled. +func Watch(ctx context.Context, t Format) <-chan []byte { + return watch(ctx, t) +} diff --git a/vendor/golang.design/x/clipboard/clipboard_android.c b/vendor/golang.design/x/clipboard/clipboard_android.c new file mode 100644 index 00000000..9dc34f6d --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_android.c @@ -0,0 +1,80 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build android + +#include +#include +#include +#include + +#define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, \ + "GOLANG.DESIGN/X/CLIPBOARD", __VA_ARGS__) + +static jmethodID find_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) { + jmethodID m = (*env)->GetMethodID(env, clazz, name, sig); + if (m == 0) { + (*env)->ExceptionClear(env); + LOG_FATAL("cannot find method %s %s", name, sig); + return 0; + } + return m; +} + +jobject get_clipboard(uintptr_t jni_env, uintptr_t ctx) { + JNIEnv *env = (JNIEnv*)jni_env; + jclass ctxClass = (*env)->GetObjectClass(env, (jobject)ctx); + jmethodID getSystemService = find_method(env, ctxClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;"); + + jstring service = (*env)->NewStringUTF(env, "clipboard"); + jobject ret = (jobject)(*env)->CallObjectMethod(env, (jobject)ctx, getSystemService, service); + jthrowable err = (*env)->ExceptionOccurred(env); + + if (err != NULL) { + LOG_FATAL("cannot find clipboard"); + (*env)->ExceptionClear(env); + return NULL; + } + return ret; +} + +char *clipboard_read_string(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx) { + JNIEnv *env = (JNIEnv*)jni_env; + jobject mgr = get_clipboard(jni_env, ctx); + if (mgr == NULL) { + return NULL; + } + + jclass mgrClass = (*env)->GetObjectClass(env, mgr); + jmethodID getText = find_method(env, mgrClass, "getText", "()Ljava/lang/CharSequence;"); + + jobject content = (jstring)(*env)->CallObjectMethod(env, mgr, getText); + if (content == NULL) { + return NULL; + } + + jclass clzCharSequence = (*env)->GetObjectClass(env, content); + jmethodID toString = (*env)->GetMethodID(env, clzCharSequence, "toString", "()Ljava/lang/String;"); + jobject s = (*env)->CallObjectMethod(env, content, toString); + + const char *chars = (*env)->GetStringUTFChars(env, s, NULL); + char *copy = strdup(chars); + (*env)->ReleaseStringUTFChars(env, s, chars); + return copy; +} + +void clipboard_write_string(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx, char *str) { + JNIEnv *env = (JNIEnv*)jni_env; + jobject mgr = get_clipboard(jni_env, ctx); + if (mgr == NULL) { + return; + } + + jclass mgrClass = (*env)->GetObjectClass(env, mgr); + jmethodID setText = find_method(env, mgrClass, "setText", "(Ljava/lang/CharSequence;)V"); + + (*env)->CallVoidMethod(env, mgr, setText, (*env)->NewStringUTF(env, str)); +} diff --git a/vendor/golang.design/x/clipboard/clipboard_android.go b/vendor/golang.design/x/clipboard/clipboard_android.go new file mode 100644 index 00000000..c9ce78fc --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_android.go @@ -0,0 +1,102 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build android + +package clipboard + +/* +#cgo LDFLAGS: -landroid -llog + +#include +char *clipboard_read_string(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx); +void clipboard_write_string(uintptr_t java_vm, uintptr_t jni_env, uintptr_t ctx, char *str); + +*/ +import "C" +import ( + "bytes" + "context" + "time" + "unsafe" + + "golang.org/x/mobile/app" +) + +func initialize() error { return nil } + +func read(t Format) (buf []byte, err error) { + switch t { + case FmtText: + s := "" + if err := app.RunOnJVM(func(vm, env, ctx uintptr) error { + cs := C.clipboard_read_string(C.uintptr_t(vm), C.uintptr_t(env), C.uintptr_t(ctx)) + if cs == nil { + return nil + } + + s = C.GoString(cs) + C.free(unsafe.Pointer(cs)) + return nil + }); err != nil { + return nil, err + } + return []byte(s), nil + case FmtImage: + return nil, errUnsupported + default: + return nil, errUnsupported + } +} + +// write writes the given data to clipboard and +// returns true if success or false if failed. +func write(t Format, buf []byte) (<-chan struct{}, error) { + done := make(chan struct{}, 1) + switch t { + case FmtText: + cs := C.CString(string(buf)) + defer C.free(unsafe.Pointer(cs)) + + if err := app.RunOnJVM(func(vm, env, ctx uintptr) error { + C.clipboard_write_string(C.uintptr_t(vm), C.uintptr_t(env), C.uintptr_t(ctx), cs) + done <- struct{}{} + return nil + }); err != nil { + return nil, err + } + return done, nil + case FmtImage: + return nil, errUnsupported + default: + return nil, errUnsupported + } +} + +func watch(ctx context.Context, t Format) <-chan []byte { + recv := make(chan []byte, 1) + ti := time.NewTicker(time.Second) + last := Read(t) + go func() { + for { + select { + case <-ctx.Done(): + close(recv) + return + case <-ti.C: + b := Read(t) + if b == nil { + continue + } + if bytes.Compare(last, b) != 0 { + recv <- b + last = b + } + } + } + }() + return recv +} diff --git a/vendor/golang.design/x/clipboard/clipboard_darwin.go b/vendor/golang.design/x/clipboard/clipboard_darwin.go new file mode 100644 index 00000000..bcda1272 --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_darwin.go @@ -0,0 +1,122 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build darwin && !ios + +package clipboard + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework Foundation -framework Cocoa +#import +#import + +unsigned int clipboard_read_string(void **out); +unsigned int clipboard_read_image(void **out); +int clipboard_write_string(const void *bytes, NSInteger n); +int clipboard_write_image(const void *bytes, NSInteger n); +NSInteger clipboard_change_count(); +*/ +import "C" +import ( + "context" + "time" + "unsafe" +) + +func initialize() error { return nil } + +func read(t Format) (buf []byte, err error) { + var ( + data unsafe.Pointer + n C.uint + ) + switch t { + case FmtText: + n = C.clipboard_read_string(&data) + case FmtImage: + n = C.clipboard_read_image(&data) + } + if data == nil { + return nil, errUnavailable + } + defer C.free(unsafe.Pointer(data)) + if n == 0 { + return nil, nil + } + return C.GoBytes(data, C.int(n)), nil +} + +// write writes the given data to clipboard and +// returns true if success or false if failed. +func write(t Format, buf []byte) (<-chan struct{}, error) { + var ok C.int + switch t { + case FmtText: + if len(buf) == 0 { + ok = C.clipboard_write_string(unsafe.Pointer(nil), 0) + } else { + ok = C.clipboard_write_string(unsafe.Pointer(&buf[0]), + C.NSInteger(len(buf))) + } + case FmtImage: + if len(buf) == 0 { + ok = C.clipboard_write_image(unsafe.Pointer(nil), 0) + } else { + ok = C.clipboard_write_image(unsafe.Pointer(&buf[0]), + C.NSInteger(len(buf))) + } + default: + return nil, errUnsupported + } + if ok != 0 { + return nil, errUnavailable + } + + // use unbuffered data to prevent goroutine leak + changed := make(chan struct{}, 1) + cnt := C.long(C.clipboard_change_count()) + go func() { + for { + // not sure if we are too slow or the user too fast :) + time.Sleep(time.Second) + cur := C.long(C.clipboard_change_count()) + if cnt != cur { + changed <- struct{}{} + close(changed) + return + } + } + }() + return changed, nil +} + +func watch(ctx context.Context, t Format) <-chan []byte { + recv := make(chan []byte, 1) + // not sure if we are too slow or the user too fast :) + ti := time.NewTicker(time.Second) + lastCount := C.long(C.clipboard_change_count()) + go func() { + for { + select { + case <-ctx.Done(): + close(recv) + return + case <-ti.C: + this := C.long(C.clipboard_change_count()) + if lastCount != this { + b := Read(t) + if b == nil { + continue + } + recv <- b + lastCount = this + } + } + } + }() + return recv +} diff --git a/vendor/golang.design/x/clipboard/clipboard_darwin.m b/vendor/golang.design/x/clipboard/clipboard_darwin.m new file mode 100644 index 00000000..177e7715 --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_darwin.m @@ -0,0 +1,62 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build darwin && !ios + +// Interact with NSPasteboard using Objective-C +// https://developer.apple.com/documentation/appkit/nspasteboard?language=objc + +#import +#import + +unsigned int clipboard_read_string(void **out) { + NSPasteboard * pasteboard = [NSPasteboard generalPasteboard]; + NSData *data = [pasteboard dataForType:NSPasteboardTypeString]; + if (data == nil) { + return 0; + } + NSUInteger siz = [data length]; + *out = malloc(siz); + [data getBytes: *out length: siz]; + return siz; +} + +unsigned int clipboard_read_image(void **out) { + NSPasteboard * pasteboard = [NSPasteboard generalPasteboard]; + NSData *data = [pasteboard dataForType:NSPasteboardTypePNG]; + if (data == nil) { + return 0; + } + NSUInteger siz = [data length]; + *out = malloc(siz); + [data getBytes: *out length: siz]; + return siz; +} + +int clipboard_write_string(const void *bytes, NSInteger n) { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSData *data = [NSData dataWithBytes: bytes length: n]; + [pasteboard clearContents]; + BOOL ok = [pasteboard setData: data forType:NSPasteboardTypeString]; + if (!ok) { + return -1; + } + return 0; +} +int clipboard_write_image(const void *bytes, NSInteger n) { + NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; + NSData *data = [NSData dataWithBytes: bytes length: n]; + [pasteboard clearContents]; + BOOL ok = [pasteboard setData: data forType:NSPasteboardTypePNG]; + if (!ok) { + return -1; + } + return 0; +} + +NSInteger clipboard_change_count() { + return [[NSPasteboard generalPasteboard] changeCount]; +} diff --git a/vendor/golang.design/x/clipboard/clipboard_ios.go b/vendor/golang.design/x/clipboard/clipboard_ios.go new file mode 100644 index 00000000..e027b8c2 --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_ios.go @@ -0,0 +1,80 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build ios + +package clipboard + +/* +#cgo CFLAGS: -x objective-c +#cgo LDFLAGS: -framework Foundation -framework UIKit -framework MobileCoreServices + +#import +void clipboard_write_string(char *s); +char *clipboard_read_string(); +*/ +import "C" +import ( + "bytes" + "context" + "time" + "unsafe" +) + +func initialize() error { return nil } + +func read(t Format) (buf []byte, err error) { + switch t { + case FmtText: + return []byte(C.GoString(C.clipboard_read_string())), nil + case FmtImage: + return nil, errUnsupported + default: + return nil, errUnsupported + } +} + +// SetContent sets the clipboard content for iOS +func write(t Format, buf []byte) (<-chan struct{}, error) { + done := make(chan struct{}, 1) + switch t { + case FmtText: + cs := C.CString(string(buf)) + defer C.free(unsafe.Pointer(cs)) + + C.clipboard_write_string(cs) + return done, nil + case FmtImage: + return nil, errUnsupported + default: + return nil, errUnsupported + } +} + +func watch(ctx context.Context, t Format) <-chan []byte { + recv := make(chan []byte, 1) + ti := time.NewTicker(time.Second) + last := Read(t) + go func() { + for { + select { + case <-ctx.Done(): + close(recv) + return + case <-ti.C: + b := Read(t) + if b == nil { + continue + } + if bytes.Compare(last, b) != 0 { + recv <- b + last = b + } + } + } + }() + return recv +} diff --git a/vendor/golang.design/x/clipboard/clipboard_ios.m b/vendor/golang.design/x/clipboard/clipboard_ios.m new file mode 100644 index 00000000..15eb122b --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_ios.m @@ -0,0 +1,20 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build ios + +#import +#import + +void clipboard_write_string(char *s) { + NSString *value = [NSString stringWithUTF8String:s]; + [[UIPasteboard generalPasteboard] setString:value]; +} + +char *clipboard_read_string() { + NSString *str = [[UIPasteboard generalPasteboard] string]; + return (char *)[str UTF8String]; +} diff --git a/vendor/golang.design/x/clipboard/clipboard_linux.c b/vendor/golang.design/x/clipboard/clipboard_linux.c new file mode 100644 index 00000000..d23934b4 --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_linux.c @@ -0,0 +1,263 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build linux && !android + +#include +#include +#include +#include +#include +#include +#include + +// syncStatus is a function from the Go side. +extern void syncStatus(uintptr_t handle, int status); + +void *libX11; + +Display* (*P_XOpenDisplay)(int); +void (*P_XCloseDisplay)(Display*); +Window (*P_XDefaultRootWindow)(Display*); +Window (*P_XCreateSimpleWindow)(Display*, Window, int, int, int, int, int, int, int); +Atom (*P_XInternAtom)(Display*, char*, int); +void (*P_XSetSelectionOwner)(Display*, Atom, Window, unsigned long); +Window (*P_XGetSelectionOwner)(Display*, Atom); +void (*P_XNextEvent)(Display*, XEvent*); +int (*P_XChangeProperty)(Display*, Window, Atom, Atom, int, int, unsigned char*, int); +void (*P_XSendEvent)(Display*, Window, int, long , XEvent*); +int (*P_XGetWindowProperty) (Display*, Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long *, unsigned long *, unsigned char **); +void (*P_XFree) (void*); +void (*P_XDeleteProperty) (Display*, Window, Atom); +void (*P_XConvertSelection)(Display*, Atom, Atom, Atom, Window, Time); + +int initX11() { + if (libX11) { + return 1; + } + libX11 = dlopen("libX11.so", RTLD_LAZY); + if (!libX11) { + return 0; + } + P_XOpenDisplay = (Display* (*)(int)) dlsym(libX11, "XOpenDisplay"); + P_XCloseDisplay = (void (*)(Display*)) dlsym(libX11, "XCloseDisplay"); + P_XDefaultRootWindow = (Window (*)(Display*)) dlsym(libX11, "XDefaultRootWindow"); + P_XCreateSimpleWindow = (Window (*)(Display*, Window, int, int, int, int, int, int, int)) dlsym(libX11, "XCreateSimpleWindow"); + P_XInternAtom = (Atom (*)(Display*, char*, int)) dlsym(libX11, "XInternAtom"); + P_XSetSelectionOwner = (void (*)(Display*, Atom, Window, unsigned long)) dlsym(libX11, "XSetSelectionOwner"); + P_XGetSelectionOwner = (Window (*)(Display*, Atom)) dlsym(libX11, "XGetSelectionOwner"); + P_XNextEvent = (void (*)(Display*, XEvent*)) dlsym(libX11, "XNextEvent"); + P_XChangeProperty = (int (*)(Display*, Window, Atom, Atom, int, int, unsigned char*, int)) dlsym(libX11, "XChangeProperty"); + P_XSendEvent = (void (*)(Display*, Window, int, long , XEvent*)) dlsym(libX11, "XSendEvent"); + P_XGetWindowProperty = (int (*)(Display*, Window, Atom, long, long, Bool, Atom, Atom*, int*, unsigned long *, unsigned long *, unsigned char **)) dlsym(libX11, "XGetWindowProperty"); + P_XFree = (void (*)(void*)) dlsym(libX11, "XFree"); + P_XDeleteProperty = (void (*)(Display*, Window, Atom)) dlsym(libX11, "XDeleteProperty"); + P_XConvertSelection = (void (*)(Display*, Atom, Atom, Atom, Window, Time)) dlsym(libX11, "XConvertSelection"); + return 1; +} + +int clipboard_test() { + if (!initX11()) { + return -1; + } + + Display* d = NULL; + for (int i = 0; i < 42; i++) { + d = (*P_XOpenDisplay)(0); + if (d == NULL) { + continue; + } + break; + } + if (d == NULL) { + return -1; + } + (*P_XCloseDisplay)(d); + return 0; +} + +// clipboard_write writes the given buf of size n as type typ. +// if start is provided, the value of start will be changed to 1 to indicate +// if the write is availiable for reading. +int clipboard_write(char *typ, unsigned char *buf, size_t n, uintptr_t handle) { + if (!initX11()) { + return -1; + } + + Display* d = NULL; + for (int i = 0; i < 42; i++) { + d = (*P_XOpenDisplay)(0); + if (d == NULL) { + continue; + } + break; + } + if (d == NULL) { + syncStatus(handle, -1); + return -1; + } + Window w = (*P_XCreateSimpleWindow)(d, (*P_XDefaultRootWindow)(d), 0, 0, 1, 1, 0, 0, 0); + + // Use False because these may not available for the first time. + Atom sel = (*P_XInternAtom)(d, "CLIPBOARD", 0); + Atom atomString = (*P_XInternAtom)(d, "UTF8_STRING", 0); + Atom atomImage = (*P_XInternAtom)(d, "image/png", 0); + Atom targetsAtom = (*P_XInternAtom)(d, "TARGETS", 0); + + // Use True to makesure the requested type is a valid type. + Atom target = (*P_XInternAtom)(d, typ, 1); + if (target == None) { + (*P_XCloseDisplay)(d); + syncStatus(handle, -2); + return -2; + } + + (*P_XSetSelectionOwner)(d, sel, w, CurrentTime); + if ((*P_XGetSelectionOwner)(d, sel) != w) { + (*P_XCloseDisplay)(d); + syncStatus(handle, -3); + return -3; + } + + XEvent event; + XSelectionRequestEvent* xsr; + int notified = 0; + for (;;) { + if (notified == 0) { + syncStatus(handle, 1); // notify Go side + notified = 1; + } + + (*P_XNextEvent)(d, &event); + switch (event.type) { + case SelectionClear: + // For debugging: + // printf("x11write: lost ownership of clipboard selection.\n"); + // fflush(stdout); + (*P_XCloseDisplay)(d); + return 0; + case SelectionNotify: + // For debugging: + // printf("x11write: notify.\n"); + // fflush(stdout); + break; + case SelectionRequest: + if (event.xselectionrequest.selection != sel) { + break; + } + + XSelectionRequestEvent * xsr = &event.xselectionrequest; + XSelectionEvent ev = {0}; + int R = 0; + + ev.type = SelectionNotify; + ev.display = xsr->display; + ev.requestor = xsr->requestor; + ev.selection = xsr->selection; + ev.time = xsr->time; + ev.target = xsr->target; + ev.property = xsr->property; + + if (ev.target == atomString && ev.target == target) { + R = (*P_XChangeProperty)(ev.display, ev.requestor, ev.property, + atomString, 8, PropModeReplace, buf, n); + } else if (ev.target == atomImage && ev.target == target) { + R = (*P_XChangeProperty)(ev.display, ev.requestor, ev.property, + atomImage, 8, PropModeReplace, buf, n); + } else if (ev.target == targetsAtom) { + // Reply atoms for supported targets, other clients should + // request the clipboard again and obtain the data if their + // implementation is correct. + Atom targets[] = { atomString, atomImage }; + R = (*P_XChangeProperty)(ev.display, ev.requestor, ev.property, + XA_ATOM, 32, PropModeReplace, + (unsigned char *)&targets, sizeof(targets)/sizeof(Atom)); + } else { + ev.property = None; + } + + if ((R & 2) == 0) (*P_XSendEvent)(d, ev.requestor, 0, 0, (XEvent *)&ev); + break; + } + } +} + +// read_data reads the property of a selection if the target atom matches +// the actual atom. +unsigned long read_data(XSelectionEvent *sev, Atom sel, Atom prop, Atom target, char **buf) { + if (!initX11()) { + return -1; + } + + unsigned char *data; + Atom actual; + int format; + unsigned long n = 0; + unsigned long size = 0; + if (sev->property == None || sev->selection != sel || sev->property != prop) { + return 0; + } + + int ret = (*P_XGetWindowProperty)(sev->display, sev->requestor, sev->property, + 0L, (~0L), 0, AnyPropertyType, &actual, &format, &size, &n, &data); + if (ret != Success) { + return 0; + } + + if (actual == target && buf != NULL) { + *buf = (char *)malloc(size * sizeof(char)); + memcpy(*buf, data, size*sizeof(char)); + } + (*P_XFree)(data); + (*P_XDeleteProperty)(sev->display, sev->requestor, sev->property); + return size * sizeof(char); +} + +// clipboard_read reads the clipboard selection in given format typ. +// the read bytes are written into buf and returns the size of the buffer. +// +// The caller of this function should responsible for the free of the buf. +unsigned long clipboard_read(char* typ, char **buf) { + if (!initX11()) { + return -1; + } + + Display* d = NULL; + for (int i = 0; i < 42; i++) { + d = (*P_XOpenDisplay)(0); + if (d == NULL) { + continue; + } + break; + } + if (d == NULL) { + return -1; + } + + Window w = (*P_XCreateSimpleWindow)(d, (*P_XDefaultRootWindow)(d), 0, 0, 1, 1, 0, 0, 0); + + // Use False because these may not available for the first time. + Atom sel = (*P_XInternAtom)(d, "CLIPBOARD", False); + Atom prop = (*P_XInternAtom)(d, "GOLANG_DESIGN_DATA", False); + + // Use True to makesure the requested type is a valid type. + Atom target = (*P_XInternAtom)(d, typ, True); + if (target == None) { + (*P_XCloseDisplay)(d); + return -2; + } + + (*P_XConvertSelection)(d, sel, target, prop, w, CurrentTime); + XEvent event; + for (;;) { + (*P_XNextEvent)(d, &event); + if (event.type != SelectionNotify) continue; + break; + } + unsigned long n = read_data((XSelectionEvent *)&event.xselection, sel, prop, target, buf); + (*P_XCloseDisplay)(d); + return n; +} diff --git a/vendor/golang.design/x/clipboard/clipboard_linux.go b/vendor/golang.design/x/clipboard/clipboard_linux.go new file mode 100644 index 00000000..7bfa6697 --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_linux.go @@ -0,0 +1,172 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build linux && !android + +package clipboard + +/* +#cgo LDFLAGS: -ldl +#include +#include +#include +#include + +int clipboard_test(); +int clipboard_write( + char* typ, + unsigned char* buf, + size_t n, + uintptr_t handle +); +unsigned long clipboard_read(char* typ, char **out); +*/ +import "C" +import ( + "bytes" + "context" + "fmt" + "os" + "runtime" + "runtime/cgo" + "time" + "unsafe" +) + +var helpmsg = `%w: Failed to initialize the X11 display, and the clipboard package +will not work properly. Install the following dependency may help: + + apt install -y libx11-dev + +If the clipboard package is in an environment without a frame buffer, +such as a cloud server, it may also be necessary to install xvfb: + + apt install -y xvfb + +and initialize a virtual frame buffer: + + Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + export DISPLAY=:99.0 + +Then this package should be ready to use. +` + +func initialize() error { + ok := C.clipboard_test() + if ok != 0 { + return fmt.Errorf(helpmsg, errUnavailable) + } + return nil +} + +func read(t Format) (buf []byte, err error) { + switch t { + case FmtText: + return readc("UTF8_STRING") + case FmtImage: + return readc("image/png") + } + return nil, errUnsupported +} + +func readc(t string) ([]byte, error) { + ct := C.CString(t) + defer C.free(unsafe.Pointer(ct)) + + var data *C.char + n := C.clipboard_read(ct, &data) + switch C.long(n) { + case -1: + return nil, errUnavailable + case -2: + return nil, errUnsupported + } + if data == nil { + return nil, errUnavailable + } + defer C.free(unsafe.Pointer(data)) + switch { + case n == 0: + return nil, nil + default: + return C.GoBytes(unsafe.Pointer(data), C.int(n)), nil + } +} + +// write writes the given data to clipboard and +// returns true if success or false if failed. +func write(t Format, buf []byte) (<-chan struct{}, error) { + var s string + switch t { + case FmtText: + s = "UTF8_STRING" + case FmtImage: + s = "image/png" + } + + start := make(chan int) + done := make(chan struct{}, 1) + + go func() { // serve as a daemon until the ownership is terminated. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + cs := C.CString(s) + defer C.free(unsafe.Pointer(cs)) + + h := cgo.NewHandle(start) + var ok C.int + if len(buf) == 0 { + ok = C.clipboard_write(cs, nil, 0, C.uintptr_t(h)) + } else { + ok = C.clipboard_write(cs, (*C.uchar)(unsafe.Pointer(&(buf[0]))), C.size_t(len(buf)), C.uintptr_t(h)) + } + if ok != C.int(0) { + fmt.Fprintf(os.Stderr, "write failed with status: %d\n", int(ok)) + } + done <- struct{}{} + close(done) + }() + + status := <-start + if status < 0 { + return nil, errUnavailable + } + // wait until enter event loop + return done, nil +} + +func watch(ctx context.Context, t Format) <-chan []byte { + recv := make(chan []byte, 1) + ti := time.NewTicker(time.Second) + last := Read(t) + go func() { + for { + select { + case <-ctx.Done(): + close(recv) + return + case <-ti.C: + b := Read(t) + if b == nil { + continue + } + if !bytes.Equal(last, b) { + recv <- b + last = b + } + } + } + }() + return recv +} + +//export syncStatus +func syncStatus(h uintptr, val int) { + v := cgo.Handle(h).Value().(chan int) + v <- val + cgo.Handle(h).Delete() +} diff --git a/vendor/golang.design/x/clipboard/clipboard_nocgo.go b/vendor/golang.design/x/clipboard/clipboard_nocgo.go new file mode 100644 index 00000000..16dc865b --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_nocgo.go @@ -0,0 +1,25 @@ +//go:build !windows && !cgo + +package clipboard + +import "context" + +func initialize() error { + return errNoCgo +} + +func read(t Format) (buf []byte, err error) { + panic("clipboard: cannot use when CGO_ENABLED=0") +} + +func readc(t string) ([]byte, error) { + panic("clipboard: cannot use when CGO_ENABLED=0") +} + +func write(t Format, buf []byte) (<-chan struct{}, error) { + panic("clipboard: cannot use when CGO_ENABLED=0") +} + +func watch(ctx context.Context, t Format) <-chan []byte { + panic("clipboard: cannot use when CGO_ENABLED=0") +} diff --git a/vendor/golang.design/x/clipboard/clipboard_windows.go b/vendor/golang.design/x/clipboard/clipboard_windows.go new file mode 100644 index 00000000..bd042cda --- /dev/null +++ b/vendor/golang.design/x/clipboard/clipboard_windows.go @@ -0,0 +1,551 @@ +// Copyright 2021 The golang.design Initiative Authors. +// All rights reserved. Use of this source code is governed +// by a MIT license that can be found in the LICENSE file. +// +// Written by Changkun Ou + +//go:build windows + +package clipboard + +// Interacting with Clipboard on Windows: +// https://docs.microsoft.com/zh-cn/windows/win32/dataxchg/using-the-clipboard + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "image" + "image/color" + "image/png" + "reflect" + "runtime" + "syscall" + "time" + "unicode/utf16" + "unsafe" + + "golang.org/x/image/bmp" +) + +func initialize() error { return nil } + +// readText reads the clipboard and returns the text data if presents. +// The caller is responsible for opening/closing the clipboard before +// calling this function. +func readText() (buf []byte, err error) { + hMem, _, err := getClipboardData.Call(cFmtUnicodeText) + if hMem == 0 { + return nil, err + } + p, _, err := gLock.Call(hMem) + if p == 0 { + return nil, err + } + defer gUnlock.Call(hMem) + + // Find NUL terminator + n := 0 + for ptr := unsafe.Pointer(p); *(*uint16)(ptr) != 0; n++ { + ptr = unsafe.Pointer(uintptr(ptr) + + unsafe.Sizeof(*((*uint16)(unsafe.Pointer(p))))) + } + + var s []uint16 + h := (*reflect.SliceHeader)(unsafe.Pointer(&s)) + h.Data = p + h.Len = n + h.Cap = n + return []byte(string(utf16.Decode(s))), nil +} + +// writeText writes given data to the clipboard. It is the caller's +// responsibility for opening/closing the clipboard before calling +// this function. +func writeText(buf []byte) error { + r, _, err := emptyClipboard.Call() + if r == 0 { + return fmt.Errorf("failed to clear clipboard: %w", err) + } + + // empty text, we are done here. + if len(buf) == 0 { + return nil + } + + s, err := syscall.UTF16FromString(string(buf)) + if err != nil { + return fmt.Errorf("failed to convert given string: %w", err) + } + + hMem, _, err := gAlloc.Call(gmemMoveable, uintptr(len(s)*int(unsafe.Sizeof(s[0])))) + if hMem == 0 { + return fmt.Errorf("failed to alloc global memory: %w", err) + } + + p, _, err := gLock.Call(hMem) + if p == 0 { + return fmt.Errorf("failed to lock global memory: %w", err) + } + defer gUnlock.Call(hMem) + + // no return value + memMove.Call(p, uintptr(unsafe.Pointer(&s[0])), + uintptr(len(s)*int(unsafe.Sizeof(s[0])))) + + v, _, err := setClipboardData.Call(cFmtUnicodeText, hMem) + if v == 0 { + gFree.Call(hMem) + return fmt.Errorf("failed to set text to clipboard: %w", err) + } + + return nil +} + +// readImage reads the clipboard and returns PNG encoded image data +// if presents. The caller is responsible for opening/closing the +// clipboard before calling this function. +func readImage() ([]byte, error) { + hMem, _, err := getClipboardData.Call(cFmtDIBV5) + if hMem == 0 { + // second chance to try FmtDIB + return readImageDib() + } + p, _, err := gLock.Call(hMem) + if p == 0 { + return nil, err + } + defer gUnlock.Call(hMem) + + // inspect header information + info := (*bitmapV5Header)(unsafe.Pointer(p)) + + // maybe deal with other formats? + if info.BitCount != 32 { + return nil, errUnsupported + } + + var data []byte + sh := (*reflect.SliceHeader)(unsafe.Pointer(&data)) + sh.Data = uintptr(p) + sh.Cap = int(info.Size + 4*uint32(info.Width)*uint32(info.Height)) + sh.Len = int(info.Size + 4*uint32(info.Width)*uint32(info.Height)) + img := image.NewRGBA(image.Rect(0, 0, int(info.Width), int(info.Height))) + offset := int(info.Size) + stride := int(info.Width) + for y := 0; y < int(info.Height); y++ { + for x := 0; x < int(info.Width); x++ { + idx := offset + 4*(y*stride+x) + xhat := (x + int(info.Width)) % int(info.Width) + yhat := int(info.Height) - 1 - y + r := data[idx+2] + g := data[idx+1] + b := data[idx+0] + a := data[idx+3] + img.SetRGBA(xhat, yhat, color.RGBA{r, g, b, a}) + } + } + // always use PNG encoding. + var buf bytes.Buffer + png.Encode(&buf, img) + return buf.Bytes(), nil +} + +func readImageDib() ([]byte, error) { + const ( + fileHeaderLen = 14 + infoHeaderLen = 40 + cFmtDIB = 8 + ) + + hClipDat, _, err := getClipboardData.Call(cFmtDIB) + if err != nil { + return nil, errors.New("not dib format data: " + err.Error()) + } + pMemBlk, _, err := gLock.Call(hClipDat) + if pMemBlk == 0 { + return nil, errors.New("failed to call global lock: " + err.Error()) + } + defer gUnlock.Call(hClipDat) + + bmpHeader := (*bitmapHeader)(unsafe.Pointer(pMemBlk)) + dataSize := bmpHeader.SizeImage + fileHeaderLen + infoHeaderLen + + if bmpHeader.SizeImage == 0 && bmpHeader.Compression == 0 { + iSizeImage := bmpHeader.Height * ((bmpHeader.Width*uint32(bmpHeader.BitCount)/8 + 3) &^ 3) + dataSize += iSizeImage + } + buf := new(bytes.Buffer) + binary.Write(buf, binary.LittleEndian, uint16('B')|(uint16('M')<<8)) + binary.Write(buf, binary.LittleEndian, uint32(dataSize)) + binary.Write(buf, binary.LittleEndian, uint32(0)) + const sizeof_colorbar = 0 + binary.Write(buf, binary.LittleEndian, uint32(fileHeaderLen+infoHeaderLen+sizeof_colorbar)) + j := 0 + for i := fileHeaderLen; i < int(dataSize); i++ { + binary.Write(buf, binary.BigEndian, *(*byte)(unsafe.Pointer(pMemBlk + uintptr(j)))) + j++ + } + return bmpToPng(buf) +} + +func bmpToPng(bmpBuf *bytes.Buffer) (buf []byte, err error) { + var f bytes.Buffer + original_image, err := bmp.Decode(bmpBuf) + if err != nil { + return nil, err + } + err = png.Encode(&f, original_image) + if err != nil { + return nil, err + } + return f.Bytes(), nil +} + +func writeImage(buf []byte) error { + r, _, err := emptyClipboard.Call() + if r == 0 { + return fmt.Errorf("failed to clear clipboard: %w", err) + } + + // empty text, we are done here. + if len(buf) == 0 { + return nil + } + + img, err := png.Decode(bytes.NewReader(buf)) + if err != nil { + return fmt.Errorf("input bytes is not PNG encoded: %w", err) + } + + offset := unsafe.Sizeof(bitmapV5Header{}) + width := img.Bounds().Dx() + height := img.Bounds().Dy() + imageSize := 4 * width * height + + data := make([]byte, int(offset)+imageSize) + for y := 0; y < height; y++ { + for x := 0; x < width; x++ { + idx := int(offset) + 4*(y*width+x) + r, g, b, a := img.At(x, height-1-y).RGBA() + data[idx+2] = uint8(r) + data[idx+1] = uint8(g) + data[idx+0] = uint8(b) + data[idx+3] = uint8(a) + } + } + + info := bitmapV5Header{} + info.Size = uint32(offset) + info.Width = int32(width) + info.Height = int32(height) + info.Planes = 1 + info.Compression = 0 // BI_RGB + info.SizeImage = uint32(4 * info.Width * info.Height) + info.RedMask = 0xff0000 // default mask + info.GreenMask = 0xff00 + info.BlueMask = 0xff + info.AlphaMask = 0xff000000 + info.BitCount = 32 // we only deal with 32 bpp at the moment. + // Use calibrated RGB values as Go's image/png assumes linear color space. + // Other options: + // - LCS_CALIBRATED_RGB = 0x00000000 + // - LCS_sRGB = 0x73524742 + // - LCS_WINDOWS_COLOR_SPACE = 0x57696E20 + // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/eb4bbd50-b3ce-4917-895c-be31f214797f + info.CSType = 0x73524742 + // Use GL_IMAGES for GamutMappingIntent + // Other options: + // - LCS_GM_ABS_COLORIMETRIC = 0x00000008 + // - LCS_GM_BUSINESS = 0x00000001 + // - LCS_GM_GRAPHICS = 0x00000002 + // - LCS_GM_IMAGES = 0x00000004 + // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wmf/9fec0834-607d-427d-abd5-ab240fb0db38 + info.Intent = 4 // LCS_GM_IMAGES + + infob := make([]byte, int(unsafe.Sizeof(info))) + for i, v := range *(*[unsafe.Sizeof(info)]byte)(unsafe.Pointer(&info)) { + infob[i] = v + } + copy(data[:], infob[:]) + + hMem, _, err := gAlloc.Call(gmemMoveable, + uintptr(len(data)*int(unsafe.Sizeof(data[0])))) + if hMem == 0 { + return fmt.Errorf("failed to alloc global memory: %w", err) + } + + p, _, err := gLock.Call(hMem) + if p == 0 { + return fmt.Errorf("failed to lock global memory: %w", err) + } + defer gUnlock.Call(hMem) + + memMove.Call(p, uintptr(unsafe.Pointer(&data[0])), + uintptr(len(data)*int(unsafe.Sizeof(data[0])))) + + v, _, err := setClipboardData.Call(cFmtDIBV5, hMem) + if v == 0 { + gFree.Call(hMem) + return fmt.Errorf("failed to set text to clipboard: %w", err) + } + + return nil +} + +func read(t Format) (buf []byte, err error) { + // On Windows, OpenClipboard and CloseClipboard must be executed on + // the same thread. Thus, lock the OS thread for further execution. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + var format uintptr + switch t { + case FmtImage: + format = cFmtDIBV5 + case FmtText: + fallthrough + default: + format = cFmtUnicodeText + } + + // check if clipboard is avaliable for the requested format + r, _, err := isClipboardFormatAvailable.Call(format) + if r == 0 { + return nil, errUnavailable + } + + // try again until open clipboard successed + for { + r, _, _ = openClipboard.Call() + if r == 0 { + continue + } + break + } + defer closeClipboard.Call() + + switch format { + case cFmtDIBV5: + return readImage() + case cFmtUnicodeText: + fallthrough + default: + return readText() + } +} + +// write writes the given data to clipboard and +// returns true if success or false if failed. +func write(t Format, buf []byte) (<-chan struct{}, error) { + errch := make(chan error) + changed := make(chan struct{}, 1) + go func() { + // make sure GetClipboardSequenceNumber happens with + // OpenClipboard on the same thread. + runtime.LockOSThread() + defer runtime.UnlockOSThread() + for { + r, _, _ := openClipboard.Call(0) + if r == 0 { + continue + } + break + } + + // var param uintptr + switch t { + case FmtImage: + err := writeImage(buf) + if err != nil { + errch <- err + closeClipboard.Call() + return + } + case FmtText: + fallthrough + default: + // param = cFmtUnicodeText + err := writeText(buf) + if err != nil { + errch <- err + closeClipboard.Call() + return + } + } + // Close the clipboard otherwise other applications cannot + // paste the data. + closeClipboard.Call() + + cnt, _, _ := getClipboardSequenceNumber.Call() + errch <- nil + for { + time.Sleep(time.Second) + cur, _, _ := getClipboardSequenceNumber.Call() + if cur != cnt { + changed <- struct{}{} + close(changed) + return + } + } + }() + err := <-errch + if err != nil { + return nil, err + } + return changed, nil +} + +func watch(ctx context.Context, t Format) <-chan []byte { + recv := make(chan []byte, 1) + ready := make(chan struct{}) + go func() { + // not sure if we are too slow or the user too fast :) + ti := time.NewTicker(time.Second) + cnt, _, _ := getClipboardSequenceNumber.Call() + ready <- struct{}{} + for { + select { + case <-ctx.Done(): + close(recv) + return + case <-ti.C: + cur, _, _ := getClipboardSequenceNumber.Call() + if cnt != cur { + b := Read(t) + if b == nil { + continue + } + recv <- b + cnt = cur + } + } + } + }() + <-ready + return recv +} + +const ( + cFmtBitmap = 2 // Win+PrintScreen + cFmtUnicodeText = 13 + cFmtDIBV5 = 17 + // Screenshot taken from special shortcut is in different format (why??), see: + // https://jpsoft.com/forums/threads/detecting-clipboard-format.5225/ + cFmtDataObject = 49161 // Shift+Win+s, returned from enumClipboardFormats + gmemMoveable = 0x0002 +) + +// BITMAPV5Header structure, see: +// https://docs.microsoft.com/en-us/windows/win32/api/wingdi/ns-wingdi-bitmapv5header +type bitmapV5Header struct { + Size uint32 + Width int32 + Height int32 + Planes uint16 + BitCount uint16 + Compression uint32 + SizeImage uint32 + XPelsPerMeter int32 + YPelsPerMeter int32 + ClrUsed uint32 + ClrImportant uint32 + RedMask uint32 + GreenMask uint32 + BlueMask uint32 + AlphaMask uint32 + CSType uint32 + Endpoints struct { + CiexyzRed, CiexyzGreen, CiexyzBlue struct { + CiexyzX, CiexyzY, CiexyzZ int32 // FXPT2DOT30 + } + } + GammaRed uint32 + GammaGreen uint32 + GammaBlue uint32 + Intent uint32 + ProfileData uint32 + ProfileSize uint32 + Reserved uint32 +} + +type bitmapHeader struct { + Size uint32 + Width uint32 + Height uint32 + PLanes uint16 + BitCount uint16 + Compression uint32 + SizeImage uint32 + XPelsPerMeter uint32 + YPelsPerMeter uint32 + ClrUsed uint32 + ClrImportant uint32 +} + +// Calling a Windows DLL, see: +// https://github.com/golang/go/wiki/WindowsDLLs +var ( + user32 = syscall.MustLoadDLL("user32") + // Opens the clipboard for examination and prevents other + // applications from modifying the clipboard content. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-openclipboard + openClipboard = user32.MustFindProc("OpenClipboard") + // Closes the clipboard. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-closeclipboard + closeClipboard = user32.MustFindProc("CloseClipboard") + // Empties the clipboard and frees handles to data in the clipboard. + // The function then assigns ownership of the clipboard to the + // window that currently has the clipboard open. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-emptyclipboard + emptyClipboard = user32.MustFindProc("EmptyClipboard") + // Retrieves data from the clipboard in a specified format. + // The clipboard must have been opened previously. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclipboarddata + getClipboardData = user32.MustFindProc("GetClipboardData") + // Places data on the clipboard in a specified clipboard format. + // The window must be the current clipboard owner, and the + // application must have called the OpenClipboard function. (When + // responding to the WM_RENDERFORMAT message, the clipboard owner + // must not call OpenClipboard before calling SetClipboardData.) + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setclipboarddata + setClipboardData = user32.MustFindProc("SetClipboardData") + // Determines whether the clipboard contains data in the specified format. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isclipboardformatavailable + isClipboardFormatAvailable = user32.MustFindProc("IsClipboardFormatAvailable") + // Clipboard data formats are stored in an ordered list. To perform + // an enumeration of clipboard data formats, you make a series of + // calls to the EnumClipboardFormats function. For each call, the + // format parameter specifies an available clipboard format, and the + // function returns the next available clipboard format. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-isclipboardformatavailable + enumClipboardFormats = user32.MustFindProc("EnumClipboardFormats") + // Retrieves the clipboard sequence number for the current window station. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclipboardsequencenumber + getClipboardSequenceNumber = user32.MustFindProc("GetClipboardSequenceNumber") + // Registers a new clipboard format. This format can then be used as + // a valid clipboard format. + // https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-registerclipboardformata + registerClipboardFormatA = user32.MustFindProc("RegisterClipboardFormatA") + + kernel32 = syscall.NewLazyDLL("kernel32") + + // Locks a global memory object and returns a pointer to the first + // byte of the object's memory block. + // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globallock + gLock = kernel32.NewProc("GlobalLock") + // Decrements the lock count associated with a memory object that was + // allocated with GMEM_MOVEABLE. This function has no effect on memory + // objects allocated with GMEM_FIXED. + // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalunlock + gUnlock = kernel32.NewProc("GlobalUnlock") + // Allocates the specified number of bytes from the heap. + // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalalloc + gAlloc = kernel32.NewProc("GlobalAlloc") + // Frees the specified global memory object and invalidates its handle. + // https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalfree + gFree = kernel32.NewProc("GlobalFree") + memMove = kernel32.NewProc("RtlMoveMemory") +) diff --git a/vendor/golang.org/x/exp/shiny/LICENSE b/vendor/golang.org/x/exp/shiny/LICENSE new file mode 100644 index 00000000..2a7cf70d --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/buffer.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/buffer.go new file mode 100644 index 00000000..94b4b9a3 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/buffer.go @@ -0,0 +1,32 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gldriver + +import "image" + +type bufferImpl struct { + // buf should always be equal to (i.e. the same ptr, len, cap as) rgba.Pix. + // It is a separate, redundant field in order to detect modifications to + // the rgba field that are invalid as per the screen.Buffer documentation. + buf []byte + rgba image.RGBA + size image.Point +} + +func (b *bufferImpl) Release() {} +func (b *bufferImpl) Size() image.Point { return b.size } +func (b *bufferImpl) Bounds() image.Rectangle { return image.Rectangle{Max: b.size} } +func (b *bufferImpl) RGBA() *image.RGBA { return &b.rgba } + +func (b *bufferImpl) preUpload() { + // Check that the program hasn't tried to modify the rgba field via the + // pointer returned by the bufferImpl.RGBA method. This check doesn't catch + // 100% of all cases; it simply tries to detect some invalid uses of a + // screen.Buffer such as: + // *buffer.RGBA() = anotherImageRGBA + if len(b.buf) != 0 && len(b.rgba.Pix) != 0 && &b.buf[0] != &b.rgba.Pix[0] { + panic("gldriver: invalid Buffer.RGBA modification") + } +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.go new file mode 100644 index 00000000..99dad131 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.go @@ -0,0 +1,670 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios + +package gldriver + +/* +#cgo CFLAGS: -x objective-c -DGL_SILENCE_DEPRECATION +#cgo LDFLAGS: -framework Cocoa -framework OpenGL +#include +#import // for HIToolbox/Events.h +#import +#include +#include +#include + +void startDriver(); +void stopDriver(); +void makeCurrentContext(uintptr_t ctx); +void flushContext(uintptr_t ctx); +uintptr_t doNewWindow(int width, int height, char* title); +void doShowWindow(uintptr_t id); +void doCloseWindow(uintptr_t id); +uint64_t threadID(); +*/ +import "C" + +import ( + "errors" + "fmt" + "log" + "runtime" + "unsafe" + + "golang.org/x/exp/shiny/driver/internal/lifecycler" + "golang.org/x/exp/shiny/screen" + "golang.org/x/mobile/event/key" + "golang.org/x/mobile/event/mouse" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/geom" + "golang.org/x/mobile/gl" +) + +const useLifecycler = true + +// TODO: change this to true, after manual testing on OS X. +const handleSizeEventsAtChannelReceive = false + +var initThreadID C.uint64_t + +func init() { + // Lock the goroutine responsible for initialization to an OS thread. + // This means the goroutine running main (and calling startDriver below) + // is locked to the OS thread that started the program. This is + // necessary for the correct delivery of Cocoa events to the process. + // + // A discussion on this topic: + // https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ + runtime.LockOSThread() + initThreadID = C.threadID() +} + +func newWindow(opts *screen.NewWindowOptions) (uintptr, error) { + width, height := optsSize(opts) + + title := C.CString(opts.GetTitle()) + defer C.free(unsafe.Pointer(title)) + + return uintptr(C.doNewWindow(C.int(width), C.int(height), title)), nil +} + +func initWindow(w *windowImpl) { + w.glctx, w.worker = gl.NewContext() +} + +func showWindow(w *windowImpl) { + C.doShowWindow(C.uintptr_t(w.id)) +} + +//export preparedOpenGL +func preparedOpenGL(id, ctx, vba uintptr) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + w.ctx = ctx + go drawLoop(w, vba) +} + +func closeWindow(id uintptr) { + C.doCloseWindow(C.uintptr_t(id)) +} + +var mainCallback func(screen.Screen) + +func main(f func(screen.Screen)) error { + if tid := C.threadID(); tid != initThreadID { + log.Fatalf("gldriver.Main called on thread %d, but gldriver.init ran on %d", tid, initThreadID) + } + + mainCallback = f + C.startDriver() + return nil +} + +//export driverStarted +func driverStarted() { + go func() { + mainCallback(theScreen) + C.stopDriver() + }() +} + +//export drawgl +func drawgl(id uintptr) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return // closing window + } + + // TODO: is this necessary? + w.lifecycler.SetVisible(true) + w.lifecycler.SendEvent(w, w.glctx) + + w.Send(paint.Event{External: true}) + <-w.drawDone +} + +// drawLoop is the primary drawing loop. +// +// After Cocoa has created an NSWindow and called prepareOpenGL, +// it starts drawLoop on a locked goroutine to handle OpenGL calls. +// +// The screen is drawn every time a paint.Event is received, which can be +// triggered either by the user or by Cocoa via drawgl (for example, when +// the window is resized). +func drawLoop(w *windowImpl, vba uintptr) { + runtime.LockOSThread() + C.makeCurrentContext(C.uintptr_t(w.ctx.(uintptr))) + + // Starting in OS X 10.11 (El Capitan), the vertex array is + // occasionally getting unbound when the context changes threads. + // + // Avoid this by binding it again. + C.glBindVertexArray(C.GLuint(vba)) + if errno := C.glGetError(); errno != 0 { + panic(fmt.Sprintf("gldriver: glBindVertexArray failed: %d", errno)) + } + + workAvailable := w.worker.WorkAvailable() + + // TODO(crawshaw): exit this goroutine on Release. + for { + select { + case <-workAvailable: + w.worker.DoWork() + case <-w.publish: + loop: + for { + select { + case <-workAvailable: + w.worker.DoWork() + default: + break loop + } + } + C.flushContext(C.uintptr_t(w.ctx.(uintptr))) + w.publishDone <- screen.PublishResult{} + } + } +} + +//export setGeom +func setGeom(id uintptr, ppp float32, widthPx, heightPx int) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return // closing window + } + + sz := size.Event{ + WidthPx: widthPx, + HeightPx: heightPx, + WidthPt: geom.Pt(float32(widthPx) / ppp), + HeightPt: geom.Pt(float32(heightPx) / ppp), + PixelsPerPt: ppp, + } + + if !handleSizeEventsAtChannelReceive { + w.szMu.Lock() + w.sz = sz + w.szMu.Unlock() + } + + w.Send(sz) +} + +//export windowClosing +func windowClosing(id uintptr) { + sendLifecycle(id, (*lifecycler.State).SetDead, true) +} + +func sendWindowEvent(id uintptr, e interface{}) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return // closing window + } + w.Send(e) +} + +var mods = [...]struct { + flags uint32 + code uint16 + mod key.Modifiers +}{ + // Left and right variants of modifier keys have their own masks, + // but they are not documented. These were determined empirically. + {1<<17 | 0x102, C.kVK_Shift, key.ModShift}, + {1<<17 | 0x104, C.kVK_RightShift, key.ModShift}, + {1<<18 | 0x101, C.kVK_Control, key.ModControl}, + {33<<13 | 0x100, C.kVK_RightControl, key.ModControl}, + {1<<19 | 0x120, C.kVK_Option, key.ModAlt}, + {1<<19 | 0x140, C.kVK_RightOption, key.ModAlt}, + {1<<20 | 0x108, C.kVK_Command, key.ModMeta}, + {1<<20 | 0x110, 0x36 /* kVK_RightCommand */, key.ModMeta}, +} + +func cocoaMods(flags uint32) (m key.Modifiers) { + for _, mod := range mods { + if flags&mod.flags == mod.flags { + m |= mod.mod + } + } + return m +} + +func cocoaMouseDir(ty int32) mouse.Direction { + switch ty { + case C.NSLeftMouseDown, C.NSRightMouseDown, C.NSOtherMouseDown: + return mouse.DirPress + case C.NSLeftMouseUp, C.NSRightMouseUp, C.NSOtherMouseUp: + return mouse.DirRelease + default: // dragged + return mouse.DirNone + } +} + +func cocoaMouseButton(button int32) mouse.Button { + switch button { + case 0: + return mouse.ButtonLeft + case 1: + return mouse.ButtonRight + case 2: + return mouse.ButtonMiddle + default: + return mouse.ButtonNone + } +} + +//export mouseEvent +func mouseEvent(id uintptr, x, y, dx, dy float32, ty, button int32, flags uint32) { + cmButton := mouse.ButtonNone + switch ty { + default: + cmButton = cocoaMouseButton(button) + case C.NSMouseMoved, C.NSLeftMouseDragged, C.NSRightMouseDragged, C.NSOtherMouseDragged: + // No-op. + case C.NSScrollWheel: + // Note that the direction of scrolling is inverted by default + // on OS X by the "natural scrolling" setting. At the Cocoa + // level this inversion is applied to trackpads and mice behind + // the scenes, and the value of dy goes in the direction the OS + // wants scrolling to go. + // + // This means the same trackpad/mouse motion on OS X and Linux + // can produce wheel events in opposite directions, but the + // direction matches what other programs on the OS do. + // + // If we wanted to expose the physical device motion in the + // event we could use [NSEvent isDirectionInvertedFromDevice] + // to know if "natural scrolling" is enabled. + // + // TODO: On a trackpad, a scroll can be a drawn-out affair with a + // distinct beginning and end. Should the intermediate events be + // DirNone? + // + // TODO: handle horizontal scrolling + button := mouse.ButtonWheelUp + if dy < 0 { + dy = -dy + button = mouse.ButtonWheelDown + } + e := mouse.Event{ + X: x, + Y: y, + Button: button, + Direction: mouse.DirStep, + Modifiers: cocoaMods(flags), + } + for delta := int(dy); delta != 0; delta-- { + sendWindowEvent(id, e) + } + return + } + sendWindowEvent(id, mouse.Event{ + X: x, + Y: y, + Button: cmButton, + Direction: cocoaMouseDir(ty), + Modifiers: cocoaMods(flags), + }) +} + +//export keyEvent +func keyEvent(id uintptr, runeVal rune, dir uint8, code uint16, flags uint32) { + sendWindowEvent(id, key.Event{ + Rune: cocoaRune(runeVal), + Direction: key.Direction(dir), + Code: cocoaKeyCode(code), + Modifiers: cocoaMods(flags), + }) +} + +//export flagEvent +func flagEvent(id uintptr, flags uint32) { + for _, mod := range mods { + if flags&mod.flags == mod.flags && lastFlags&mod.flags != mod.flags { + keyEvent(id, -1, C.NSKeyDown, mod.code, flags) + } + if lastFlags&mod.flags == mod.flags && flags&mod.flags != mod.flags { + keyEvent(id, -1, C.NSKeyUp, mod.code, flags) + } + } + lastFlags = flags +} + +var lastFlags uint32 + +func sendLifecycle(id uintptr, setter func(*lifecycler.State, bool), val bool) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return + } + setter(&w.lifecycler, val) + w.lifecycler.SendEvent(w, w.glctx) +} + +func sendLifecycleAll(dead bool) { + windows := []*windowImpl{} + + theScreen.mu.Lock() + for _, w := range theScreen.windows { + windows = append(windows, w) + } + theScreen.mu.Unlock() + + for _, w := range windows { + w.lifecycler.SetFocused(false) + w.lifecycler.SetVisible(false) + if dead { + w.lifecycler.SetDead(true) + } + w.lifecycler.SendEvent(w, w.glctx) + } +} + +//export lifecycleDeadAll +func lifecycleDeadAll() { sendLifecycleAll(true) } + +//export lifecycleHideAll +func lifecycleHideAll() { sendLifecycleAll(false) } + +//export lifecycleVisible +func lifecycleVisible(id uintptr, val bool) { + sendLifecycle(id, (*lifecycler.State).SetVisible, val) +} + +//export lifecycleFocused +func lifecycleFocused(id uintptr, val bool) { + sendLifecycle(id, (*lifecycler.State).SetFocused, val) +} + +// cocoaRune marks the Carbon/Cocoa private-range unicode rune representing +// a non-unicode key event to -1, used for Rune in the key package. +// +// http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT +func cocoaRune(r rune) rune { + if '\uE000' <= r && r <= '\uF8FF' { + return -1 + } + return r +} + +// cocoaKeyCode converts a Carbon/Cocoa virtual key code number +// into the standard keycodes used by the key package. +// +// To get a sense of the key map, see the diagram on +// +// http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes +func cocoaKeyCode(vkcode uint16) key.Code { + switch vkcode { + case C.kVK_ANSI_A: + return key.CodeA + case C.kVK_ANSI_B: + return key.CodeB + case C.kVK_ANSI_C: + return key.CodeC + case C.kVK_ANSI_D: + return key.CodeD + case C.kVK_ANSI_E: + return key.CodeE + case C.kVK_ANSI_F: + return key.CodeF + case C.kVK_ANSI_G: + return key.CodeG + case C.kVK_ANSI_H: + return key.CodeH + case C.kVK_ANSI_I: + return key.CodeI + case C.kVK_ANSI_J: + return key.CodeJ + case C.kVK_ANSI_K: + return key.CodeK + case C.kVK_ANSI_L: + return key.CodeL + case C.kVK_ANSI_M: + return key.CodeM + case C.kVK_ANSI_N: + return key.CodeN + case C.kVK_ANSI_O: + return key.CodeO + case C.kVK_ANSI_P: + return key.CodeP + case C.kVK_ANSI_Q: + return key.CodeQ + case C.kVK_ANSI_R: + return key.CodeR + case C.kVK_ANSI_S: + return key.CodeS + case C.kVK_ANSI_T: + return key.CodeT + case C.kVK_ANSI_U: + return key.CodeU + case C.kVK_ANSI_V: + return key.CodeV + case C.kVK_ANSI_W: + return key.CodeW + case C.kVK_ANSI_X: + return key.CodeX + case C.kVK_ANSI_Y: + return key.CodeY + case C.kVK_ANSI_Z: + return key.CodeZ + case C.kVK_ANSI_1: + return key.Code1 + case C.kVK_ANSI_2: + return key.Code2 + case C.kVK_ANSI_3: + return key.Code3 + case C.kVK_ANSI_4: + return key.Code4 + case C.kVK_ANSI_5: + return key.Code5 + case C.kVK_ANSI_6: + return key.Code6 + case C.kVK_ANSI_7: + return key.Code7 + case C.kVK_ANSI_8: + return key.Code8 + case C.kVK_ANSI_9: + return key.Code9 + case C.kVK_ANSI_0: + return key.Code0 + // TODO: move the rest of these codes to constants in key.go + // if we are happy with them. + case C.kVK_Return: + return key.CodeReturnEnter + case C.kVK_Escape: + return key.CodeEscape + case C.kVK_Delete: + return key.CodeDeleteBackspace + case C.kVK_Tab: + return key.CodeTab + case C.kVK_Space: + return key.CodeSpacebar + case C.kVK_ANSI_Minus: + return key.CodeHyphenMinus + case C.kVK_ANSI_Equal: + return key.CodeEqualSign + case C.kVK_ANSI_LeftBracket: + return key.CodeLeftSquareBracket + case C.kVK_ANSI_RightBracket: + return key.CodeRightSquareBracket + case C.kVK_ANSI_Backslash: + return key.CodeBackslash + // 50: Keyboard Non-US "#" and ~ + case C.kVK_ANSI_Semicolon: + return key.CodeSemicolon + case C.kVK_ANSI_Quote: + return key.CodeApostrophe + case C.kVK_ANSI_Grave: + return key.CodeGraveAccent + case C.kVK_ANSI_Comma: + return key.CodeComma + case C.kVK_ANSI_Period: + return key.CodeFullStop + case C.kVK_ANSI_Slash: + return key.CodeSlash + case C.kVK_CapsLock: + return key.CodeCapsLock + case C.kVK_F1: + return key.CodeF1 + case C.kVK_F2: + return key.CodeF2 + case C.kVK_F3: + return key.CodeF3 + case C.kVK_F4: + return key.CodeF4 + case C.kVK_F5: + return key.CodeF5 + case C.kVK_F6: + return key.CodeF6 + case C.kVK_F7: + return key.CodeF7 + case C.kVK_F8: + return key.CodeF8 + case C.kVK_F9: + return key.CodeF9 + case C.kVK_F10: + return key.CodeF10 + case C.kVK_F11: + return key.CodeF11 + case C.kVK_F12: + return key.CodeF12 + // 70: PrintScreen + // 71: Scroll Lock + // 72: Pause + // 73: Insert + case C.kVK_Home: + return key.CodeHome + case C.kVK_PageUp: + return key.CodePageUp + case C.kVK_ForwardDelete: + return key.CodeDeleteForward + case C.kVK_End: + return key.CodeEnd + case C.kVK_PageDown: + return key.CodePageDown + case C.kVK_RightArrow: + return key.CodeRightArrow + case C.kVK_LeftArrow: + return key.CodeLeftArrow + case C.kVK_DownArrow: + return key.CodeDownArrow + case C.kVK_UpArrow: + return key.CodeUpArrow + case C.kVK_ANSI_KeypadClear: + return key.CodeKeypadNumLock + case C.kVK_ANSI_KeypadDivide: + return key.CodeKeypadSlash + case C.kVK_ANSI_KeypadMultiply: + return key.CodeKeypadAsterisk + case C.kVK_ANSI_KeypadMinus: + return key.CodeKeypadHyphenMinus + case C.kVK_ANSI_KeypadPlus: + return key.CodeKeypadPlusSign + case C.kVK_ANSI_KeypadEnter: + return key.CodeKeypadEnter + case C.kVK_ANSI_Keypad1: + return key.CodeKeypad1 + case C.kVK_ANSI_Keypad2: + return key.CodeKeypad2 + case C.kVK_ANSI_Keypad3: + return key.CodeKeypad3 + case C.kVK_ANSI_Keypad4: + return key.CodeKeypad4 + case C.kVK_ANSI_Keypad5: + return key.CodeKeypad5 + case C.kVK_ANSI_Keypad6: + return key.CodeKeypad6 + case C.kVK_ANSI_Keypad7: + return key.CodeKeypad7 + case C.kVK_ANSI_Keypad8: + return key.CodeKeypad8 + case C.kVK_ANSI_Keypad9: + return key.CodeKeypad9 + case C.kVK_ANSI_Keypad0: + return key.CodeKeypad0 + case C.kVK_ANSI_KeypadDecimal: + return key.CodeKeypadFullStop + case C.kVK_ANSI_KeypadEquals: + return key.CodeKeypadEqualSign + case C.kVK_F13: + return key.CodeF13 + case C.kVK_F14: + return key.CodeF14 + case C.kVK_F15: + return key.CodeF15 + case C.kVK_F16: + return key.CodeF16 + case C.kVK_F17: + return key.CodeF17 + case C.kVK_F18: + return key.CodeF18 + case C.kVK_F19: + return key.CodeF19 + case C.kVK_F20: + return key.CodeF20 + // 116: Keyboard Execute + case C.kVK_Help: + return key.CodeHelp + // 118: Keyboard Menu + // 119: Keyboard Select + // 120: Keyboard Stop + // 121: Keyboard Again + // 122: Keyboard Undo + // 123: Keyboard Cut + // 124: Keyboard Copy + // 125: Keyboard Paste + // 126: Keyboard Find + case C.kVK_Mute: + return key.CodeMute + case C.kVK_VolumeUp: + return key.CodeVolumeUp + case C.kVK_VolumeDown: + return key.CodeVolumeDown + // 130: Keyboard Locking Caps Lock + // 131: Keyboard Locking Num Lock + // 132: Keyboard Locking Scroll Lock + // 133: Keyboard Comma + // 134: Keyboard Equal Sign + // ...: Bunch of stuff + case C.kVK_Control: + return key.CodeLeftControl + case C.kVK_Shift: + return key.CodeLeftShift + case C.kVK_Option: + return key.CodeLeftAlt + case C.kVK_Command: + return key.CodeLeftGUI + case C.kVK_RightControl: + return key.CodeRightControl + case C.kVK_RightShift: + return key.CodeRightShift + case C.kVK_RightOption: + return key.CodeRightAlt + // TODO key.CodeRightGUI + default: + return key.CodeUnknown + } +} + +func surfaceCreate() error { + return errors.New("gldriver: surface creation not implemented on darwin") +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.m b/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.m new file mode 100644 index 00000000..1ae33973 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/cocoa.m @@ -0,0 +1,332 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build darwin +// +build !ios + +#include "_cgo_export.h" +#include +#include + +#import +#import +#import + +// The variables did not exist on older OS X releases, +// we use the old variables deprecated on macOS to define them. +#if __MAC_OS_X_VERSION_MAX_ALLOWED < 101200 +enum +{ + NSEventTypeScrollWheel = NSScrollWheel, + NSEventTypeKeyDown = NSKeyDown +}; +enum +{ + NSWindowStyleMaskTitled = NSTitledWindowMask, + NSWindowStyleMaskResizable = NSResizableWindowMask, + NSWindowStyleMaskMiniaturizable = NSMiniaturizableWindowMask, + NSWindowStyleMaskClosable = NSClosableWindowMask +}; +#endif + +void makeCurrentContext(uintptr_t context) { + NSOpenGLContext* ctx = (NSOpenGLContext*)context; + [ctx makeCurrentContext]; +} + +void flushContext(uintptr_t context) { + NSOpenGLContext* ctx = (NSOpenGLContext*)context; + [ctx flushBuffer]; +} + +uint64 threadID() { + uint64 id; + if (pthread_threadid_np(pthread_self(), &id)) { + abort(); + } + return id; +} + +@interface ScreenGLView : NSOpenGLView +{ +} +@end + +@implementation ScreenGLView +- (void)prepareOpenGL { + [super prepareOpenGL]; + + [self setWantsBestResolutionOpenGLSurface:YES]; + GLint swapInt = 1; + NSOpenGLContext *ctx = [self openGLContext]; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [ctx setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; +#pragma clang diagnostic pop + + // Using attribute arrays in OpenGL 3.3 requires the use of a VBA. + // But VBAs don't exist in ES 2. So we bind a default one. + GLuint vba; + glGenVertexArrays(1, &vba); + glBindVertexArray(vba); + + preparedOpenGL((GoUintptr)self, (GoUintptr)ctx, (GoUintptr)vba); +} + +- (void)callSetGeom { + // Calculate screen PPI. + // + // Note that the backingScaleFactor converts from logical + // pixels to actual pixels, but both of these units vary + // independently from real world size. E.g. + // + // 13" Retina Macbook Pro, 2560x1600, 227ppi, backingScaleFactor=2, scale=3.15 + // 15" Retina Macbook Pro, 2880x1800, 220ppi, backingScaleFactor=2, scale=3.06 + // 27" iMac, 2560x1440, 109ppi, backingScaleFactor=1, scale=1.51 + // 27" Retina iMac, 5120x2880, 218ppi, backingScaleFactor=2, scale=3.03 + NSScreen *screen = self.window.screen; + double screenPixW = [screen frame].size.width * [screen backingScaleFactor]; + + CGDirectDisplayID display = (CGDirectDisplayID)[[[screen deviceDescription] valueForKey:@"NSScreenNumber"] intValue]; + CGSize screenSizeMM = CGDisplayScreenSize(display); // in millimeters + float ppi = 25.4 * screenPixW / screenSizeMM.width; + float pixelsPerPt = ppi/72.0; + + // The width and height reported to the geom package are the + // bounds of the OpenGL view. Several steps are necessary. + // First, [self bounds] gives us the number of logical pixels + // in the view. Multiplying this by the backingScaleFactor + // gives us the number of actual pixels. + NSRect r = [self bounds]; + int w = r.size.width * [screen backingScaleFactor]; + int h = r.size.height * [screen backingScaleFactor]; + + setGeom((GoUintptr)self, pixelsPerPt, w, h); +} + +- (void)reshape { + [super reshape]; + [self callSetGeom]; +} + +- (void)drawRect:(NSRect)theRect { + // Called during resize. Do an extra draw if we are visible. + // This gets rid of flicker when resizing. + drawgl((GoUintptr)self); +} + +- (void)mouseEventNS:(NSEvent *)theEvent { + NSPoint p = [theEvent locationInWindow]; + double h = self.frame.size.height; + + // Both h and p are measured in Cocoa pixels, which are a fraction of + // physical pixels, so we multiply by backingScaleFactor. + double scale = [self.window.screen backingScaleFactor]; + + double x = p.x * scale; + double y = (h - p.y) * scale - 1; // flip origin from bottom-left to top-left. + + double dx, dy; + if (theEvent.type == NSEventTypeScrollWheel) { + dx = theEvent.scrollingDeltaX; + dy = theEvent.scrollingDeltaY; + } + + mouseEvent((GoUintptr)self, x, y, dx, dy, theEvent.type, theEvent.buttonNumber, theEvent.modifierFlags); +} + +- (void)mouseMoved:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)mouseDown:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)mouseUp:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)mouseDragged:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)rightMouseDown:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)rightMouseUp:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)rightMouseDragged:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)otherMouseDown:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)otherMouseUp:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)otherMouseDragged:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } +- (void)scrollWheel:(NSEvent *)theEvent { [self mouseEventNS:theEvent]; } + +// raw modifier key presses +- (void)flagsChanged:(NSEvent *)theEvent { + flagEvent((GoUintptr)self, theEvent.modifierFlags); +} + +// overrides special handling of escape and tab +- (BOOL)performKeyEquivalent:(NSEvent *)theEvent { + [self key:theEvent]; + return YES; +} + +- (void)keyDown:(NSEvent *)theEvent { [self key:theEvent]; } +- (void)keyUp:(NSEvent *)theEvent { [self key:theEvent]; } + +- (void)key:(NSEvent *)theEvent { + NSRange range = [theEvent.characters rangeOfComposedCharacterSequenceAtIndex:0]; + + uint8_t buf[4] = {0, 0, 0, 0}; + if (![theEvent.characters getBytes:buf + maxLength:4 + usedLength:nil + encoding:NSUTF32LittleEndianStringEncoding + options:NSStringEncodingConversionAllowLossy + range:range + remainingRange:nil]) { + NSLog(@"failed to read key event %@", theEvent); + return; + } + + uint32_t rune = (uint32_t)buf[0]<<0 | (uint32_t)buf[1]<<8 | (uint32_t)buf[2]<<16 | (uint32_t)buf[3]<<24; + + uint8_t direction; + if ([theEvent isARepeat]) { + direction = 0; + } else if (theEvent.type == NSEventTypeKeyDown) { + direction = 1; + } else { + direction = 2; + } + keyEvent((GoUintptr)self, (int32_t)rune, direction, theEvent.keyCode, theEvent.modifierFlags); +} + +- (void)windowDidChangeScreenProfile:(NSNotification *)notification { + [self callSetGeom]; +} + +// TODO: catch windowDidMiniaturize? + +- (void)windowDidExpose:(NSNotification *)notification { + lifecycleVisible((GoUintptr)self, true); +} + +- (void)windowDidBecomeKey:(NSNotification *)notification { + lifecycleFocused((GoUintptr)self, true); +} + +- (void)windowDidResignKey:(NSNotification *)notification { + lifecycleFocused((GoUintptr)self, false); + if ([NSApp isHidden]) { + lifecycleVisible((GoUintptr)self, false); + } +} + +- (void)windowWillClose:(NSNotification *)notification { + // TODO: is this right? Closing a window via the top-left red button + // seems to return early without ever calling windowClosing. + if (self.window.nextResponder == NULL) { + return; // already called close + } + + windowClosing((GoUintptr)self); + [self.window.nextResponder release]; + self.window.nextResponder = NULL; +} +@end + +@interface AppDelegate : NSObject +{ +} +@end + +@implementation AppDelegate +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + driverStarted(); + [[NSRunningApplication currentApplication] activateWithOptions:NSApplicationActivateAllWindows]; +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + lifecycleDeadAll(); +} + +- (void)applicationWillHide:(NSNotification *)aNotification { + lifecycleHideAll(); +} +@end + +uintptr_t doNewWindow(int width, int height, char* title) { + NSScreen *screen = [NSScreen mainScreen]; + double w = (double)width / [screen backingScaleFactor]; + double h = (double)height / [screen backingScaleFactor]; + __block ScreenGLView* view = NULL; + + dispatch_sync(dispatch_get_main_queue(), ^{ + id menuBar = [NSMenu new]; + id menuItem = [NSMenuItem new]; + [menuBar addItem:menuItem]; + [NSApp setMainMenu:menuBar]; + + id menu = [NSMenu new]; + NSString* name = [[NSString alloc] initWithUTF8String:title]; + + id hideMenuItem = [[NSMenuItem alloc] initWithTitle:@"Hide" + action:@selector(hide:) keyEquivalent:@"h"]; + [menu addItem:hideMenuItem]; + + id quitMenuItem = [[NSMenuItem alloc] initWithTitle:@"Quit" + action:@selector(terminate:) keyEquivalent:@"q"]; + [menu addItem:quitMenuItem]; + [menuItem setSubmenu:menu]; + + NSRect rect = NSMakeRect(0, 0, w, h); + + NSWindow* window = [[NSWindow alloc] initWithContentRect:rect + styleMask:NSWindowStyleMaskTitled + backing:NSBackingStoreBuffered + defer:NO]; + window.styleMask |= NSWindowStyleMaskResizable; + window.styleMask |= NSWindowStyleMaskMiniaturizable; + window.styleMask |= NSWindowStyleMaskClosable; + window.title = name; + window.displaysWhenScreenProfileChanges = YES; + [window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; + [window setAcceptsMouseMovedEvents:YES]; + + NSOpenGLPixelFormatAttribute attr[] = { + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 16, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAllowOfflineRenderers, + 0 + }; + id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; + view = [[ScreenGLView alloc] initWithFrame:rect pixelFormat:pixFormat]; + [window setContentView:view]; + [window setDelegate:view]; + [window makeFirstResponder:view]; + }); + + return (uintptr_t)view; +} + +void doShowWindow(uintptr_t viewID) { + ScreenGLView* view = (ScreenGLView*)viewID; + dispatch_async(dispatch_get_main_queue(), ^{ + [view.window makeKeyAndOrderFront:view.window]; + }); +} + +void doCloseWindow(uintptr_t viewID) { + ScreenGLView* view = (ScreenGLView*)viewID; + dispatch_sync(dispatch_get_main_queue(), ^{ + [view.window performClose:view]; + }); +} + +void startDriver() { + [NSAutoreleasePool new]; + [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + AppDelegate* delegate = [[AppDelegate alloc] init]; + [NSApp setDelegate:delegate]; + [NSApp run]; +} + +void stopDriver() { + dispatch_async(dispatch_get_main_queue(), ^{ + [NSApp terminate:nil]; + }); +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/context.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/context.go new file mode 100644 index 00000000..488a3886 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/context.go @@ -0,0 +1,37 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !android + +package gldriver + +import ( + "runtime" + + "golang.org/x/mobile/gl" +) + +// NewContext creates an OpenGL ES context with a dedicated processing thread. +func NewContext() (gl.Context, error) { + glctx, worker := gl.NewContext() + + errCh := make(chan error) + workAvailable := worker.WorkAvailable() + go func() { + runtime.LockOSThread() + err := surfaceCreate() + errCh <- err + if err != nil { + return + } + + for range workAvailable { + worker.DoWork() + } + }() + if err := <-errCh; err != nil { + return nil, err + } + return glctx, nil +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/egl.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/egl.go new file mode 100644 index 00000000..6f5d3d7b --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/egl.go @@ -0,0 +1,106 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gldriver + +// These constants match the values found in the EGL 1.4 headers, +// egl.h, eglext.h, and eglplatform.h. +const ( + _EGL_DONT_CARE = -1 + + _EGL_NO_SURFACE = 0 + _EGL_NO_CONTEXT = 0 + _EGL_NO_DISPLAY = 0 + + _EGL_OPENGL_ES2_BIT = 0x04 // EGL_RENDERABLE_TYPE mask + _EGL_WINDOW_BIT = 0x04 // EGL_SURFACE_TYPE mask + + _EGL_OPENGL_ES_API = 0x30A0 + _EGL_RENDERABLE_TYPE = 0x3040 + _EGL_SURFACE_TYPE = 0x3033 + _EGL_BUFFER_SIZE = 0x3020 + _EGL_ALPHA_SIZE = 0x3021 + _EGL_BLUE_SIZE = 0x3022 + _EGL_GREEN_SIZE = 0x3023 + _EGL_RED_SIZE = 0x3024 + _EGL_DEPTH_SIZE = 0x3025 + _EGL_STENCIL_SIZE = 0x3026 + _EGL_SAMPLE_BUFFERS = 0x3032 + _EGL_CONFIG_CAVEAT = 0x3027 + _EGL_NONE = 0x3038 + + _EGL_CONTEXT_CLIENT_VERSION = 0x3098 +) + +// ANGLE specific options found in eglext.h +const ( + _EGL_PLATFORM_ANGLE_ANGLE = 0x3202 + _EGL_PLATFORM_ANGLE_TYPE_ANGLE = 0x3203 + _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204 + _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205 + _EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206 + + _EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE = 0x3207 + _EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE = 0x3208 + _EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209 + _EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A + _EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE = 0x320B + + _EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE = 0x320D + _EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE = 0x320E +) + +const ( + _EGL_SUCCESS = 0x3000 + _EGL_NOT_INITIALIZED = 0x3001 + _EGL_BAD_ACCESS = 0x3002 + _EGL_BAD_ALLOC = 0x3003 + _EGL_BAD_ATTRIBUTE = 0x3004 + _EGL_BAD_CONFIG = 0x3005 + _EGL_BAD_CONTEXT = 0x3006 + _EGL_BAD_CURRENT_SURFACE = 0x3007 + _EGL_BAD_DISPLAY = 0x3008 + _EGL_BAD_MATCH = 0x3009 + _EGL_BAD_NATIVE_PIXMAP = 0x300A + _EGL_BAD_NATIVE_WINDOW = 0x300B + _EGL_BAD_PARAMETER = 0x300C + _EGL_BAD_SURFACE = 0x300D + _EGL_CONTEXT_LOST = 0x300E +) + +func eglErrString(errno uintptr) string { + switch errno { + case _EGL_SUCCESS: + return "EGL_SUCCESS" + case _EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED" + case _EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS" + case _EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC" + case _EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE" + case _EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG" + case _EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT" + case _EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE" + case _EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY" + case _EGL_BAD_MATCH: + return "EGL_BAD_MATCH" + case _EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP" + case _EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW" + case _EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER" + case _EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE" + case _EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST" + } + return "EGL: unknown error" +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go new file mode 100644 index 00000000..37eb4674 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/gldriver.go @@ -0,0 +1,133 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package gldriver provides an OpenGL driver for accessing a screen. +package gldriver // import "golang.org/x/exp/shiny/driver/gldriver" + +import ( + "encoding/binary" + "fmt" + "math" + + "golang.org/x/exp/shiny/driver/internal/errscreen" + "golang.org/x/exp/shiny/screen" + "golang.org/x/image/math/f64" + "golang.org/x/mobile/gl" +) + +// Main is called by the program's main function to run the graphical +// application. +// +// It calls f on the Screen, possibly in a separate goroutine, as some OS- +// specific libraries require being on 'the main thread'. It returns when f +// returns. +func Main(f func(screen.Screen)) { + if err := main(f); err != nil { + f(errscreen.Stub(err)) + } +} + +func mul(a, b f64.Aff3) f64.Aff3 { + return f64.Aff3{ + a[0]*b[0] + a[1]*b[3], + a[0]*b[1] + a[1]*b[4], + a[0]*b[2] + a[1]*b[5] + a[2], + + a[3]*b[0] + a[4]*b[3], + a[3]*b[1] + a[4]*b[4], + a[3]*b[2] + a[4]*b[5] + a[5], + } +} + +// writeAff3 must only be called while holding windowImpl.glctxMu. +func writeAff3(glctx gl.Context, u gl.Uniform, a f64.Aff3) { + var m [9]float32 + m[0*3+0] = float32(a[0*3+0]) + m[0*3+1] = float32(a[1*3+0]) + m[0*3+2] = 0 + m[1*3+0] = float32(a[0*3+1]) + m[1*3+1] = float32(a[1*3+1]) + m[1*3+2] = 0 + m[2*3+0] = float32(a[0*3+2]) + m[2*3+1] = float32(a[1*3+2]) + m[2*3+2] = 1 + glctx.UniformMatrix3fv(u, m[:]) +} + +// f32Bytes returns the byte representation of float32 values in the given byte +// order. byteOrder must be either binary.BigEndian or binary.LittleEndian. +func f32Bytes(byteOrder binary.ByteOrder, values ...float32) []byte { + le := false + switch byteOrder { + case binary.BigEndian: + case binary.LittleEndian: + le = true + default: + panic(fmt.Sprintf("invalid byte order %v", byteOrder)) + } + + b := make([]byte, 4*len(values)) + for i, v := range values { + u := math.Float32bits(v) + if le { + b[4*i+0] = byte(u >> 0) + b[4*i+1] = byte(u >> 8) + b[4*i+2] = byte(u >> 16) + b[4*i+3] = byte(u >> 24) + } else { + b[4*i+0] = byte(u >> 24) + b[4*i+1] = byte(u >> 16) + b[4*i+2] = byte(u >> 8) + b[4*i+3] = byte(u >> 0) + } + } + return b +} + +// compileProgram must only be called while holding windowImpl.glctxMu. +func compileProgram(glctx gl.Context, vSrc, fSrc string) (gl.Program, error) { + program := glctx.CreateProgram() + if program.Value == 0 { + return gl.Program{}, fmt.Errorf("gldriver: no programs available") + } + + vertexShader, err := compileShader(glctx, gl.VERTEX_SHADER, vSrc) + if err != nil { + return gl.Program{}, err + } + fragmentShader, err := compileShader(glctx, gl.FRAGMENT_SHADER, fSrc) + if err != nil { + glctx.DeleteShader(vertexShader) + return gl.Program{}, err + } + + glctx.AttachShader(program, vertexShader) + glctx.AttachShader(program, fragmentShader) + glctx.LinkProgram(program) + + // Flag shaders for deletion when program is unlinked. + glctx.DeleteShader(vertexShader) + glctx.DeleteShader(fragmentShader) + + if glctx.GetProgrami(program, gl.LINK_STATUS) == 0 { + defer glctx.DeleteProgram(program) + return gl.Program{}, fmt.Errorf("gldriver: program compile: %s", glctx.GetProgramInfoLog(program)) + } + return program, nil +} + +// compileShader must only be called while holding windowImpl.glctxMu. +func compileShader(glctx gl.Context, shaderType gl.Enum, src string) (gl.Shader, error) { + shader := glctx.CreateShader(shaderType) + if shader.Value == 0 { + return gl.Shader{}, fmt.Errorf("gldriver: could not create shader (type %v)", shaderType) + } + glctx.ShaderSource(shader, src) + glctx.CompileShader(shader) + if glctx.GetShaderi(shader, gl.COMPILE_STATUS) == 0 { + defer glctx.DeleteShader(shader) + return gl.Shader{}, fmt.Errorf("gldriver: shader compile: %s", glctx.GetShaderInfoLog(shader)) + } + return shader, nil +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/other.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/other.go new file mode 100644 index 00000000..f762750a --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/other.go @@ -0,0 +1,29 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!darwin || ios || !cgo) && (!linux || android || !cgo) && (!openbsd || !cgo) && !windows + +package gldriver + +import ( + "fmt" + "runtime" + + "golang.org/x/exp/shiny/screen" +) + +const useLifecycler = true +const handleSizeEventsAtChannelReceive = true + +var errUnsupported = fmt.Errorf("gldriver: unsupported GOOS/GOARCH %s/%s or cgo not enabled", runtime.GOOS, runtime.GOARCH) + +func newWindow(opts *screen.NewWindowOptions) (uintptr, error) { return 0, errUnsupported } + +func initWindow(id *windowImpl) {} +func showWindow(id *windowImpl) {} +func closeWindow(id uintptr) {} +func drawLoop(w *windowImpl) {} + +func surfaceCreate() error { return errUnsupported } +func main(f func(screen.Screen)) error { return errUnsupported } diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/screen.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/screen.go new file mode 100644 index 00000000..f6f18f1b --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/screen.go @@ -0,0 +1,149 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gldriver + +import ( + "fmt" + "image" + "sync" + + "golang.org/x/exp/shiny/screen" + "golang.org/x/mobile/gl" +) + +var theScreen = &screenImpl{ + windows: make(map[uintptr]*windowImpl), +} + +type screenImpl struct { + texture struct { + program gl.Program + pos gl.Attrib + mvp gl.Uniform + uvp gl.Uniform + inUV gl.Attrib + sample gl.Uniform + quad gl.Buffer + } + fill struct { + program gl.Program + pos gl.Attrib + mvp gl.Uniform + color gl.Uniform + quad gl.Buffer + } + + mu sync.Mutex + windows map[uintptr]*windowImpl +} + +func (s *screenImpl) NewBuffer(size image.Point) (retBuf screen.Buffer, retErr error) { + m := image.NewRGBA(image.Rectangle{Max: size}) + return &bufferImpl{ + buf: m.Pix, + rgba: *m, + size: size, + }, nil +} + +func (s *screenImpl) NewTexture(size image.Point) (screen.Texture, error) { + // TODO: can we compile these programs eagerly instead of lazily? + + // Find a GL context for this texture. + // TODO: this might be correct. Some GL objects can be shared + // across contexts. But this needs a review of the spec to make + // sure it's correct, and some testing would be nice. + var w *windowImpl + + s.mu.Lock() + for _, window := range s.windows { + w = window + break + } + s.mu.Unlock() + + if w == nil { + return nil, fmt.Errorf("gldriver: no window available") + } + + w.glctxMu.Lock() + defer w.glctxMu.Unlock() + glctx := w.glctx + if glctx == nil { + return nil, fmt.Errorf("gldriver: no GL context available") + } + + if !glctx.IsProgram(s.texture.program) { + p, err := compileProgram(glctx, textureVertexSrc, textureFragmentSrc) + if err != nil { + return nil, err + } + s.texture.program = p + s.texture.pos = glctx.GetAttribLocation(p, "pos") + s.texture.mvp = glctx.GetUniformLocation(p, "mvp") + s.texture.uvp = glctx.GetUniformLocation(p, "uvp") + s.texture.inUV = glctx.GetAttribLocation(p, "inUV") + s.texture.sample = glctx.GetUniformLocation(p, "sample") + s.texture.quad = glctx.CreateBuffer() + + glctx.BindBuffer(gl.ARRAY_BUFFER, s.texture.quad) + glctx.BufferData(gl.ARRAY_BUFFER, quadCoords, gl.STATIC_DRAW) + } + + t := &textureImpl{ + w: w, + id: glctx.CreateTexture(), + size: size, + } + + glctx.BindTexture(gl.TEXTURE_2D, t.id) + glctx.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size.X, size.Y, gl.RGBA, gl.UNSIGNED_BYTE, nil) + glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) + glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) + glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) + glctx.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) + + return t, nil +} + +func optsSize(opts *screen.NewWindowOptions) (width, height int) { + width, height = 1024, 768 + if opts != nil { + if opts.Width > 0 { + width = opts.Width + } + if opts.Height > 0 { + height = opts.Height + } + } + return width, height +} + +func (s *screenImpl) NewWindow(opts *screen.NewWindowOptions) (screen.Window, error) { + id, err := newWindow(opts) + if err != nil { + return nil, err + } + w := &windowImpl{ + s: s, + id: id, + publish: make(chan struct{}), + publishDone: make(chan screen.PublishResult), + drawDone: make(chan struct{}), + } + initWindow(w) + + s.mu.Lock() + s.windows[id] = w + s.mu.Unlock() + + if useLifecycler { + w.lifecycler.SendEvent(w, nil) + } + + showWindow(w) + + return w, nil +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/texture.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/texture.go new file mode 100644 index 00000000..a691ed85 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/texture.go @@ -0,0 +1,160 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gldriver + +import ( + "encoding/binary" + "image" + "image/color" + "image/draw" + + "golang.org/x/exp/shiny/screen" + "golang.org/x/mobile/gl" +) + +type textureImpl struct { + w *windowImpl + id gl.Texture + fb gl.Framebuffer + size image.Point +} + +func (t *textureImpl) Size() image.Point { return t.size } +func (t *textureImpl) Bounds() image.Rectangle { return image.Rectangle{Max: t.size} } + +func (t *textureImpl) Release() { + t.w.glctxMu.Lock() + defer t.w.glctxMu.Unlock() + + if t.fb.Value != 0 { + t.w.glctx.DeleteFramebuffer(t.fb) + t.fb = gl.Framebuffer{} + } + t.w.glctx.DeleteTexture(t.id) + t.id = gl.Texture{} +} + +func (t *textureImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { + buf := src.(*bufferImpl) + buf.preUpload() + + // src2dst is added to convert from the src coordinate space to the dst + // coordinate space. It is subtracted to convert the other way. + src2dst := dp.Sub(sr.Min) + + // Clip to the source. + sr = sr.Intersect(buf.Bounds()) + + // Clip to the destination. + dr := sr.Add(src2dst) + dr = dr.Intersect(t.Bounds()) + if dr.Empty() { + return + } + + // Bring dr.Min in dst-space back to src-space to get the pixel buffer offset. + pix := buf.rgba.Pix[buf.rgba.PixOffset(dr.Min.X-src2dst.X, dr.Min.Y-src2dst.Y):] + + t.w.glctxMu.Lock() + defer t.w.glctxMu.Unlock() + + t.w.glctx.BindTexture(gl.TEXTURE_2D, t.id) + + width := dr.Dx() + if width*4 == buf.rgba.Stride { + t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, dr.Min.X, dr.Min.Y, width, dr.Dy(), gl.RGBA, gl.UNSIGNED_BYTE, pix) + return + } + // TODO: can we use GL_UNPACK_ROW_LENGTH with glPixelStorei for stride in + // ES 3.0, instead of uploading the pixels row-by-row? + for y, p := dr.Min.Y, 0; y < dr.Max.Y; y++ { + t.w.glctx.TexSubImage2D(gl.TEXTURE_2D, 0, dr.Min.X, y, width, 1, gl.RGBA, gl.UNSIGNED_BYTE, pix[p:]) + p += buf.rgba.Stride + } +} + +func (t *textureImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) { + minX := float64(dr.Min.X) + minY := float64(dr.Min.Y) + maxX := float64(dr.Max.X) + maxY := float64(dr.Max.Y) + mvp := calcMVP( + t.size.X, t.size.Y, + minX, minY, + maxX, minY, + minX, maxY, + ) + + glctx := t.w.glctx + + t.w.glctxMu.Lock() + defer t.w.glctxMu.Unlock() + + create := t.fb.Value == 0 + if create { + t.fb = glctx.CreateFramebuffer() + } + glctx.BindFramebuffer(gl.FRAMEBUFFER, t.fb) + if create { + glctx.FramebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, t.id, 0) + } + + glctx.Viewport(0, 0, t.size.X, t.size.Y) + doFill(t.w.s, t.w.glctx, mvp, src, op) + + // We can't restore the GL state (i.e. bind the back buffer, also known as + // gl.Framebuffer{Value: 0}) right away, since we don't necessarily know + // the right viewport size yet. It is valid to call textureImpl.Fill before + // we've gotten our first size.Event. We bind it lazily instead. + t.w.backBufferBound = false +} + +var quadCoords = f32Bytes(binary.LittleEndian, + 0, 0, // top left + 1, 0, // top right + 0, 1, // bottom left + 1, 1, // bottom right +) + +const textureVertexSrc = `#version 100 +uniform mat3 mvp; +uniform mat3 uvp; +attribute vec3 pos; +attribute vec2 inUV; +varying vec2 uv; +void main() { + vec3 p = pos; + p.z = 1.0; + gl_Position = vec4(mvp * p, 1); + uv = (uvp * vec3(inUV, 1)).xy; +} +` + +const textureFragmentSrc = `#version 100 +precision mediump float; +varying vec2 uv; +uniform sampler2D sample; +void main() { + gl_FragColor = texture2D(sample, uv); +} +` + +const fillVertexSrc = `#version 100 +uniform mat3 mvp; +attribute vec3 pos; +void main() { + vec3 p = pos; + p.z = 1.0; + gl_Position = vec4(mvp * p, 1); +} +` + +const fillFragmentSrc = `#version 100 +precision mediump float; +uniform vec4 color; +void main() { + gl_FragColor = color; +} +` diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/win32.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/win32.go new file mode 100644 index 00000000..c94549ed --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/win32.go @@ -0,0 +1,357 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package gldriver + +import ( + "errors" + "fmt" + "runtime" + "syscall" + "unsafe" + + "golang.org/x/exp/shiny/driver/internal/win32" + "golang.org/x/exp/shiny/screen" + "golang.org/x/mobile/event/key" + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/mouse" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/gl" +) + +// TODO: change this to true, after manual testing on Win32. +const useLifecycler = false + +// TODO: change this to true, after manual testing on Win32. +const handleSizeEventsAtChannelReceive = false + +func main(f func(screen.Screen)) error { + return win32.Main(func() { f(theScreen) }) +} + +var ( + eglGetPlatformDisplayEXT = gl.LibEGL.NewProc("eglGetPlatformDisplayEXT") + eglInitialize = gl.LibEGL.NewProc("eglInitialize") + eglChooseConfig = gl.LibEGL.NewProc("eglChooseConfig") + eglGetError = gl.LibEGL.NewProc("eglGetError") + eglBindAPI = gl.LibEGL.NewProc("eglBindAPI") + eglCreateWindowSurface = gl.LibEGL.NewProc("eglCreateWindowSurface") + eglCreateContext = gl.LibEGL.NewProc("eglCreateContext") + eglMakeCurrent = gl.LibEGL.NewProc("eglMakeCurrent") + eglSwapInterval = gl.LibEGL.NewProc("eglSwapInterval") + eglDestroySurface = gl.LibEGL.NewProc("eglDestroySurface") + eglSwapBuffers = gl.LibEGL.NewProc("eglSwapBuffers") +) + +type eglConfig uintptr // void* + +type eglInt int32 + +var rgb888 = [...]eglInt{ + _EGL_RENDERABLE_TYPE, _EGL_OPENGL_ES2_BIT, + _EGL_SURFACE_TYPE, _EGL_WINDOW_BIT, + _EGL_BLUE_SIZE, 8, + _EGL_GREEN_SIZE, 8, + _EGL_RED_SIZE, 8, + _EGL_DEPTH_SIZE, 16, + _EGL_STENCIL_SIZE, 8, + _EGL_NONE, +} + +type ctxWin32 struct { + ctx uintptr + display uintptr // EGLDisplay + surface uintptr // EGLSurface +} + +func newWindow(opts *screen.NewWindowOptions) (uintptr, error) { + w, err := win32.NewWindow(opts) + if err != nil { + return 0, err + } + return uintptr(w), nil +} + +func initWindow(w *windowImpl) { + w.glctx, w.worker = gl.NewContext() +} + +func showWindow(w *windowImpl) { + // Show makes an initial call to sizeEvent (via win32.SizeEvent), where + // we setup the EGL surface and GL context. + win32.Show(syscall.Handle(w.id)) +} + +func closeWindow(id uintptr) {} // TODO + +func drawLoop(w *windowImpl) { + runtime.LockOSThread() + + display := w.ctx.(ctxWin32).display + surface := w.ctx.(ctxWin32).surface + ctx := w.ctx.(ctxWin32).ctx + + if ret, _, _ := eglMakeCurrent.Call(display, surface, surface, ctx); ret == 0 { + panic(fmt.Sprintf("eglMakeCurrent failed: %v", eglErr())) + } + + // TODO(crawshaw): exit this goroutine on Release. + workAvailable := w.worker.WorkAvailable() + for { + select { + case <-workAvailable: + w.worker.DoWork() + case <-w.publish: + loop: + for { + select { + case <-workAvailable: + w.worker.DoWork() + default: + break loop + } + } + if ret, _, _ := eglSwapBuffers.Call(display, surface); ret == 0 { + panic(fmt.Sprintf("eglSwapBuffers failed: %v", eglErr())) + } + w.publishDone <- screen.PublishResult{} + } + } +} + +func init() { + win32.SizeEvent = sizeEvent + win32.PaintEvent = paintEvent + win32.MouseEvent = mouseEvent + win32.KeyEvent = keyEvent + win32.LifecycleEvent = lifecycleEvent +} + +func lifecycleEvent(hwnd syscall.Handle, to lifecycle.Stage) { + theScreen.mu.Lock() + w := theScreen.windows[uintptr(hwnd)] + theScreen.mu.Unlock() + + if w.lifecycleStage == to { + return + } + w.Send(lifecycle.Event{ + From: w.lifecycleStage, + To: to, + DrawContext: w.glctx, + }) + w.lifecycleStage = to +} + +func mouseEvent(hwnd syscall.Handle, e mouse.Event) { + theScreen.mu.Lock() + w := theScreen.windows[uintptr(hwnd)] + theScreen.mu.Unlock() + + w.Send(e) +} + +func keyEvent(hwnd syscall.Handle, e key.Event) { + theScreen.mu.Lock() + w := theScreen.windows[uintptr(hwnd)] + theScreen.mu.Unlock() + + w.Send(e) +} + +func paintEvent(hwnd syscall.Handle, e paint.Event) { + theScreen.mu.Lock() + w := theScreen.windows[uintptr(hwnd)] + theScreen.mu.Unlock() + + if w.ctx == nil { + // Sometimes a paint event comes in before initial + // window size is set. Ignore it. + return + } + + // TODO: the paint.Event should have External: true. + w.Send(paint.Event{}) +} + +func sizeEvent(hwnd syscall.Handle, e size.Event) { + theScreen.mu.Lock() + w := theScreen.windows[uintptr(hwnd)] + theScreen.mu.Unlock() + + if w.ctx == nil { + // This is the initial size event on window creation. + // Create an EGL surface and spin up a GL context. + if err := createEGLSurface(hwnd, w); err != nil { + panic(err) + } + go drawLoop(w) + } + + if !handleSizeEventsAtChannelReceive { + w.szMu.Lock() + w.sz = e + w.szMu.Unlock() + } + + w.Send(e) + + if handleSizeEventsAtChannelReceive { + return + } + + // Screen is dirty, generate a paint event. + // + // The sizeEvent function is called on the goroutine responsible for + // calling the GL worker.DoWork. When compiling with -tags gldebug, + // these GL calls are blocking (so we can read the error message), so + // to make progress they need to happen on another goroutine. + go func() { + // TODO: this call to Viewport is not right, but is very hard to + // do correctly with our async events channel model. We want + // the call to Viewport to be made the instant before the + // paint.Event is received. + w.glctxMu.Lock() + w.glctx.Viewport(0, 0, e.WidthPx, e.HeightPx) + w.glctx.ClearColor(0, 0, 0, 1) + w.glctx.Clear(gl.COLOR_BUFFER_BIT) + w.glctxMu.Unlock() + + w.Send(paint.Event{}) + }() +} + +func eglErr() error { + if ret, _, _ := eglGetError.Call(); ret != _EGL_SUCCESS { + return errors.New(eglErrString(ret)) + } + return nil +} + +func createEGLSurface(hwnd syscall.Handle, w *windowImpl) error { + var displayAttribPlatforms = [][]eglInt{ + // Default + []eglInt{ + _EGL_PLATFORM_ANGLE_TYPE_ANGLE, + _EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE, + _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE, + _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE, + _EGL_NONE, + }, + // Direct3D 11 + []eglInt{ + _EGL_PLATFORM_ANGLE_TYPE_ANGLE, + _EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE, + _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE, + _EGL_NONE, + }, + // Direct3D 9 + []eglInt{ + _EGL_PLATFORM_ANGLE_TYPE_ANGLE, + _EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, + _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE, + _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE, + _EGL_NONE, + }, + // Direct3D 11 with WARP + // https://msdn.microsoft.com/en-us/library/windows/desktop/gg615082.aspx + []eglInt{ + _EGL_PLATFORM_ANGLE_TYPE_ANGLE, + _EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, + _EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, + _EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, + _EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, _EGL_DONT_CARE, + _EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, _EGL_DONT_CARE, + _EGL_NONE, + }, + } + + dc, err := win32.GetDC(hwnd) + if err != nil { + return fmt.Errorf("win32.GetDC failed: %v", err) + } + + var display uintptr = _EGL_NO_DISPLAY + for i, displayAttrib := range displayAttribPlatforms { + lastTry := i == len(displayAttribPlatforms)-1 + + display, _, _ = eglGetPlatformDisplayEXT.Call( + _EGL_PLATFORM_ANGLE_ANGLE, + uintptr(dc), + uintptr(unsafe.Pointer(&displayAttrib[0])), + ) + + if display == _EGL_NO_DISPLAY { + if !lastTry { + continue + } + return fmt.Errorf("eglGetPlatformDisplayEXT failed: %v", eglErr()) + } + + if ret, _, _ := eglInitialize.Call(display, 0, 0); ret == 0 { + if !lastTry { + continue + } + return fmt.Errorf("eglInitialize failed: %v", eglErr()) + } + } + + eglBindAPI.Call(_EGL_OPENGL_ES_API) + if err := eglErr(); err != nil { + return err + } + + var numConfigs eglInt + var config eglConfig + ret, _, _ := eglChooseConfig.Call( + display, + uintptr(unsafe.Pointer(&rgb888[0])), + uintptr(unsafe.Pointer(&config)), + 1, + uintptr(unsafe.Pointer(&numConfigs)), + ) + if ret == 0 { + return fmt.Errorf("eglChooseConfig failed: %v", eglErr()) + } + if numConfigs <= 0 { + return errors.New("eglChooseConfig found no valid config") + } + + surface, _, _ := eglCreateWindowSurface.Call(display, uintptr(config), uintptr(hwnd), 0, 0) + if surface == _EGL_NO_SURFACE { + return fmt.Errorf("eglCreateWindowSurface failed: %v", eglErr()) + } + + contextAttribs := [...]eglInt{ + _EGL_CONTEXT_CLIENT_VERSION, 2, + _EGL_NONE, + } + context, _, _ := eglCreateContext.Call( + display, + uintptr(config), + _EGL_NO_CONTEXT, + uintptr(unsafe.Pointer(&contextAttribs[0])), + ) + if context == _EGL_NO_CONTEXT { + return fmt.Errorf("eglCreateContext failed: %v", eglErr()) + } + + eglSwapInterval.Call(display, 1) + + w.ctx = ctxWin32{ + ctx: context, + display: display, + surface: surface, + } + + return nil +} + +func surfaceCreate() error { + return errors.New("gldriver: surface creation not implemented on windows") +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/window.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/window.go new file mode 100644 index 00000000..82baf2c2 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/window.go @@ -0,0 +1,389 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gldriver + +import ( + "image" + "image/color" + "image/draw" + "sync" + + "golang.org/x/exp/shiny/driver/internal/drawer" + "golang.org/x/exp/shiny/driver/internal/event" + "golang.org/x/exp/shiny/driver/internal/lifecycler" + "golang.org/x/exp/shiny/screen" + "golang.org/x/image/math/f64" + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/gl" +) + +type windowImpl struct { + s *screenImpl + + // id is an OS-specific data structure for the window. + // - Cocoa: ScreenGLView* + // - X11: Window + // - Windows: win32.HWND + id uintptr + + // ctx is a C data structure for the GL context. + // - Cocoa: uintptr holding a NSOpenGLContext*. + // - X11: uintptr holding an EGLSurface. + // - Windows: ctxWin32 + ctx interface{} + + lifecycler lifecycler.State + // TODO: Delete the field below (and the useLifecycler constant), and use + // the field above for cocoa and win32. + lifecycleStage lifecycle.Stage // current stage + + event.Deque + publish chan struct{} + publishDone chan screen.PublishResult + drawDone chan struct{} + + // glctxMu is a mutex that enforces the atomicity of methods like + // Texture.Upload or Window.Draw that are conceptually one operation + // but are implemented by multiple OpenGL calls. OpenGL is a stateful + // API, so interleaving OpenGL calls from separate higher-level + // operations causes inconsistencies. + glctxMu sync.Mutex + glctx gl.Context + worker gl.Worker + // backBufferBound is whether the default Framebuffer, with ID 0, also + // known as the back buffer or the window's Framebuffer, is bound and its + // viewport is known to equal the window size. It can become false when we + // bind to a texture's Framebuffer or when the window size changes. + backBufferBound bool + + // szMu protects only sz. If you need to hold both glctxMu and szMu, the + // lock ordering is to lock glctxMu first (and unlock it last). + szMu sync.Mutex + sz size.Event +} + +// NextEvent implements the screen.EventDeque interface. +func (w *windowImpl) NextEvent() interface{} { + e := w.Deque.NextEvent() + if handleSizeEventsAtChannelReceive { + if sz, ok := e.(size.Event); ok { + w.glctxMu.Lock() + w.backBufferBound = false + w.szMu.Lock() + w.sz = sz + w.szMu.Unlock() + w.glctxMu.Unlock() + } + } + return e +} + +func (w *windowImpl) Release() { + // There are two ways a window can be closed: the Operating System or + // Desktop Environment can initiate (e.g. in response to a user clicking a + // red button), or the Go app can programatically close the window (by + // calling Window.Release). + // + // When the OS closes a window: + // - Cocoa: Obj-C's windowWillClose calls Go's windowClosing. + // - X11: the X11 server sends a WM_DELETE_WINDOW message. + // - Windows: TODO: implement and document this. + // + // This should send a lifecycle event (To: StageDead) to the Go app's event + // loop, which should respond by calling Window.Release (this method). + // Window.Release is where system resources are actually cleaned up. + // + // When Window.Release is called, the closeWindow call below: + // - Cocoa: calls Obj-C's performClose, which emulates the red button + // being clicked. (TODO: document how this actually cleans up + // resources??) + // - X11: calls C's XDestroyWindow. + // - Windows: TODO: implement and document this. + // + // On Cocoa, if these two approaches race, experiments suggest that the + // race is won by performClose (which is called serially on the main + // thread). Even if that isn't true, the windowWillClose handler is + // idempotent. + + theScreen.mu.Lock() + delete(theScreen.windows, w.id) + theScreen.mu.Unlock() + + closeWindow(w.id) +} + +func (w *windowImpl) Upload(dp image.Point, src screen.Buffer, sr image.Rectangle) { + originalSRMin := sr.Min + sr = sr.Intersect(src.Bounds()) + if sr.Empty() { + return + } + dp = dp.Add(sr.Min.Sub(originalSRMin)) + // TODO: keep a texture around for this purpose? + t, err := w.s.NewTexture(sr.Size()) + if err != nil { + panic(err) + } + t.Upload(image.Point{}, src, sr) + w.Draw(f64.Aff3{ + 1, 0, float64(dp.X), + 0, 1, float64(dp.Y), + }, t, t.Bounds(), draw.Src, nil) + t.Release() +} + +func useOp(glctx gl.Context, op draw.Op) { + if op == draw.Over { + glctx.Enable(gl.BLEND) + glctx.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA) + } else { + glctx.Disable(gl.BLEND) + } +} + +func (w *windowImpl) bindBackBuffer() { + w.szMu.Lock() + sz := w.sz + w.szMu.Unlock() + + w.backBufferBound = true + w.glctx.BindFramebuffer(gl.FRAMEBUFFER, gl.Framebuffer{Value: 0}) + w.glctx.Viewport(0, 0, sz.WidthPx, sz.HeightPx) +} + +func (w *windowImpl) fill(mvp f64.Aff3, src color.Color, op draw.Op) { + w.glctxMu.Lock() + defer w.glctxMu.Unlock() + + if !w.backBufferBound { + w.bindBackBuffer() + } + + doFill(w.s, w.glctx, mvp, src, op) +} + +func doFill(s *screenImpl, glctx gl.Context, mvp f64.Aff3, src color.Color, op draw.Op) { + useOp(glctx, op) + if !glctx.IsProgram(s.fill.program) { + p, err := compileProgram(glctx, fillVertexSrc, fillFragmentSrc) + if err != nil { + // TODO: initialize this somewhere else we can better handle the error. + panic(err.Error()) + } + s.fill.program = p + s.fill.pos = glctx.GetAttribLocation(p, "pos") + s.fill.mvp = glctx.GetUniformLocation(p, "mvp") + s.fill.color = glctx.GetUniformLocation(p, "color") + s.fill.quad = glctx.CreateBuffer() + + glctx.BindBuffer(gl.ARRAY_BUFFER, s.fill.quad) + glctx.BufferData(gl.ARRAY_BUFFER, quadCoords, gl.STATIC_DRAW) + } + glctx.UseProgram(s.fill.program) + + writeAff3(glctx, s.fill.mvp, mvp) + + r, g, b, a := src.RGBA() + glctx.Uniform4f( + s.fill.color, + float32(r)/65535, + float32(g)/65535, + float32(b)/65535, + float32(a)/65535, + ) + + glctx.BindBuffer(gl.ARRAY_BUFFER, s.fill.quad) + glctx.EnableVertexAttribArray(s.fill.pos) + glctx.VertexAttribPointer(s.fill.pos, 2, gl.FLOAT, false, 0, 0) + + glctx.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) + + glctx.DisableVertexAttribArray(s.fill.pos) +} + +func (w *windowImpl) Fill(dr image.Rectangle, src color.Color, op draw.Op) { + minX := float64(dr.Min.X) + minY := float64(dr.Min.Y) + maxX := float64(dr.Max.X) + maxY := float64(dr.Max.Y) + w.fill(w.mvp( + minX, minY, + maxX, minY, + minX, maxY, + ), src, op) +} + +func (w *windowImpl) DrawUniform(src2dst f64.Aff3, src color.Color, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { + minX := float64(sr.Min.X) + minY := float64(sr.Min.Y) + maxX := float64(sr.Max.X) + maxY := float64(sr.Max.Y) + w.fill(w.mvp( + src2dst[0]*minX+src2dst[1]*minY+src2dst[2], + src2dst[3]*minX+src2dst[4]*minY+src2dst[5], + src2dst[0]*maxX+src2dst[1]*minY+src2dst[2], + src2dst[3]*maxX+src2dst[4]*minY+src2dst[5], + src2dst[0]*minX+src2dst[1]*maxY+src2dst[2], + src2dst[3]*minX+src2dst[4]*maxY+src2dst[5], + ), src, op) +} + +func (w *windowImpl) Draw(src2dst f64.Aff3, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { + t := src.(*textureImpl) + sr = sr.Intersect(t.Bounds()) + if sr.Empty() { + return + } + + w.glctxMu.Lock() + defer w.glctxMu.Unlock() + + if !w.backBufferBound { + w.bindBackBuffer() + } + + useOp(w.glctx, op) + w.glctx.UseProgram(w.s.texture.program) + + // Start with src-space left, top, right and bottom. + srcL := float64(sr.Min.X) + srcT := float64(sr.Min.Y) + srcR := float64(sr.Max.X) + srcB := float64(sr.Max.Y) + // Transform to dst-space via the src2dst matrix, then to a MVP matrix. + writeAff3(w.glctx, w.s.texture.mvp, w.mvp( + src2dst[0]*srcL+src2dst[1]*srcT+src2dst[2], + src2dst[3]*srcL+src2dst[4]*srcT+src2dst[5], + src2dst[0]*srcR+src2dst[1]*srcT+src2dst[2], + src2dst[3]*srcR+src2dst[4]*srcT+src2dst[5], + src2dst[0]*srcL+src2dst[1]*srcB+src2dst[2], + src2dst[3]*srcL+src2dst[4]*srcB+src2dst[5], + )) + + // OpenGL's fragment shaders' UV coordinates run from (0,0)-(1,1), + // unlike vertex shaders' XY coordinates running from (-1,+1)-(+1,-1). + // + // We are drawing a rectangle PQRS, defined by two of its + // corners, onto the entire texture. The two quads may actually + // be equal, but in the general case, PQRS can be smaller. + // + // (0,0) +---------------+ (1,0) + // | P +-----+ Q | + // | | | | + // | S +-----+ R | + // (0,1) +---------------+ (1,1) + // + // The PQRS quad is always axis-aligned. First of all, convert + // from pixel space to texture space. + tw := float64(t.size.X) + th := float64(t.size.Y) + px := float64(sr.Min.X-0) / tw + py := float64(sr.Min.Y-0) / th + qx := float64(sr.Max.X-0) / tw + sy := float64(sr.Max.Y-0) / th + // Due to axis alignment, qy = py and sx = px. + // + // The simultaneous equations are: + // 0 + 0 + a02 = px + // 0 + 0 + a12 = py + // a00 + 0 + a02 = qx + // a10 + 0 + a12 = qy = py + // 0 + a01 + a02 = sx = px + // 0 + a11 + a12 = sy + writeAff3(w.glctx, w.s.texture.uvp, f64.Aff3{ + qx - px, 0, px, + 0, sy - py, py, + }) + + w.glctx.ActiveTexture(gl.TEXTURE0) + w.glctx.BindTexture(gl.TEXTURE_2D, t.id) + w.glctx.Uniform1i(w.s.texture.sample, 0) + + w.glctx.BindBuffer(gl.ARRAY_BUFFER, w.s.texture.quad) + w.glctx.EnableVertexAttribArray(w.s.texture.pos) + w.glctx.VertexAttribPointer(w.s.texture.pos, 2, gl.FLOAT, false, 0, 0) + + w.glctx.BindBuffer(gl.ARRAY_BUFFER, w.s.texture.quad) + w.glctx.EnableVertexAttribArray(w.s.texture.inUV) + w.glctx.VertexAttribPointer(w.s.texture.inUV, 2, gl.FLOAT, false, 0, 0) + + w.glctx.DrawArrays(gl.TRIANGLE_STRIP, 0, 4) + + w.glctx.DisableVertexAttribArray(w.s.texture.pos) + w.glctx.DisableVertexAttribArray(w.s.texture.inUV) +} + +func (w *windowImpl) Copy(dp image.Point, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { + drawer.Copy(w, dp, src, sr, op, opts) +} + +func (w *windowImpl) Scale(dr image.Rectangle, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { + drawer.Scale(w, dr, src, sr, op, opts) +} + +func (w *windowImpl) mvp(tlx, tly, trx, try, blx, bly float64) f64.Aff3 { + w.szMu.Lock() + sz := w.sz + w.szMu.Unlock() + + return calcMVP(sz.WidthPx, sz.HeightPx, tlx, tly, trx, try, blx, bly) +} + +// calcMVP returns the Model View Projection matrix that maps the quadCoords +// unit square, (0, 0) to (1, 1), to a quad QV, such that QV in vertex shader +// space corresponds to the quad QP in pixel space, where QP is defined by +// three of its four corners - the arguments to this function. The three +// corners are nominally the top-left, top-right and bottom-left, but there is +// no constraint that e.g. tlx < trx. +// +// In pixel space, the window ranges from (0, 0) to (widthPx, heightPx). The +// Y-axis points downwards. +// +// In vertex shader space, the window ranges from (-1, +1) to (+1, -1), which +// is a 2-unit by 2-unit square. The Y-axis points upwards. +func calcMVP(widthPx, heightPx int, tlx, tly, trx, try, blx, bly float64) f64.Aff3 { + // Convert from pixel coords to vertex shader coords. + invHalfWidth := +2 / float64(widthPx) + invHalfHeight := -2 / float64(heightPx) + tlx = tlx*invHalfWidth - 1 + tly = tly*invHalfHeight + 1 + trx = trx*invHalfWidth - 1 + try = try*invHalfHeight + 1 + blx = blx*invHalfWidth - 1 + bly = bly*invHalfHeight + 1 + + // The resultant affine matrix: + // - maps (0, 0) to (tlx, tly). + // - maps (1, 0) to (trx, try). + // - maps (0, 1) to (blx, bly). + return f64.Aff3{ + trx - tlx, blx - tlx, tlx, + try - tly, bly - tly, tly, + } +} + +func (w *windowImpl) Publish() screen.PublishResult { + // gl.Flush is a lightweight (on modern GL drivers) blocking call + // that ensures all GL functions pending in the gl package have + // been passed onto the GL driver before the app package attempts + // to swap the screen buffer. + // + // This enforces that the final receive (for this paint cycle) on + // gl.WorkAvailable happens before the send on publish. + w.glctxMu.Lock() + w.glctx.Flush() + w.glctxMu.Unlock() + + w.publish <- struct{}{} + res := <-w.publishDone + + select { + case w.drawDone <- struct{}{}: + default: + } + + return res +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.c b/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.c new file mode 100644 index 00000000..e7fb2896 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.c @@ -0,0 +1,330 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// +build linux,!android openbsd + +#include "_cgo_export.h" +#include +#include // for Atom, Colormap, Display, Window +#include // for XVisualInfo +#include +#include +#include + +Atom net_wm_name; +Atom utf8_string; +Atom wm_delete_window; +Atom wm_protocols; +Atom wm_take_focus; + +EGLConfig e_config; +EGLContext e_ctx; +EGLDisplay e_dpy; +Colormap x_colormap; +Display *x_dpy; +XVisualInfo *x_visual_info; +Window x_root; + +// TODO: share code with eglErrString +char * +eglGetErrorStr() { + switch (eglGetError()) { + case EGL_SUCCESS: + return "EGL_SUCCESS"; + case EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED"; + case EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS"; + case EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC"; + case EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE"; + case EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG"; + case EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT"; + case EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE"; + case EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY"; + case EGL_BAD_MATCH: + return "EGL_BAD_MATCH"; + case EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP"; + case EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW"; + case EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER"; + case EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE"; + case EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST"; + } + return "unknown EGL error"; +} + +void +startDriver() { + x_dpy = XOpenDisplay(NULL); + if (!x_dpy) { + fprintf(stderr, "XOpenDisplay failed\n"); + exit(1); + } + e_dpy = eglGetDisplay(x_dpy); + if (!e_dpy) { + fprintf(stderr, "eglGetDisplay failed: %s\n", eglGetErrorStr()); + exit(1); + } + EGLint e_major, e_minor; + if (!eglInitialize(e_dpy, &e_major, &e_minor)) { + fprintf(stderr, "eglInitialize failed: %s\n", eglGetErrorStr()); + exit(1); + } + if (!eglBindAPI(EGL_OPENGL_ES_API)) { + fprintf(stderr, "eglBindAPI failed: %s\n", eglGetErrorStr()); + exit(1); + } + + static const EGLint attribs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_NONE + }; + EGLint num_configs; + if (!eglChooseConfig(e_dpy, attribs, &e_config, 1, &num_configs)) { + fprintf(stderr, "eglChooseConfig failed: %s\n", eglGetErrorStr()); + exit(1); + } + EGLint vid; + if (!eglGetConfigAttrib(e_dpy, e_config, EGL_NATIVE_VISUAL_ID, &vid)) { + fprintf(stderr, "eglGetConfigAttrib failed: %s\n", eglGetErrorStr()); + exit(1); + } + + XVisualInfo visTemplate; + visTemplate.visualid = vid; + int num_visuals; + x_visual_info = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals); + if (!x_visual_info) { + fprintf(stderr, "XGetVisualInfo failed\n"); + exit(1); + } + + x_root = RootWindow(x_dpy, DefaultScreen(x_dpy)); + x_colormap = XCreateColormap(x_dpy, x_root, x_visual_info->visual, AllocNone); + if (!x_colormap) { + fprintf(stderr, "XCreateColormap failed\n"); + exit(1); + } + + static const EGLint ctx_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_NONE + }; + e_ctx = eglCreateContext(e_dpy, e_config, EGL_NO_CONTEXT, ctx_attribs); + if (!e_ctx) { + fprintf(stderr, "eglCreateContext failed: %s\n", eglGetErrorStr()); + exit(1); + } + + net_wm_name = XInternAtom(x_dpy, "_NET_WM_NAME", False); + utf8_string = XInternAtom(x_dpy, "UTF8_STRING", False); + wm_delete_window = XInternAtom(x_dpy, "WM_DELETE_WINDOW", False); + wm_protocols = XInternAtom(x_dpy, "WM_PROTOCOLS", False); + wm_take_focus = XInternAtom(x_dpy, "WM_TAKE_FOCUS", False); + + const int key_lo = 8; + const int key_hi = 255; + int keysyms_per_keycode; + KeySym *keysyms = XGetKeyboardMapping(x_dpy, key_lo, key_hi-key_lo+1, &keysyms_per_keycode); + if (keysyms_per_keycode < 2) { + fprintf(stderr, "XGetKeyboardMapping returned too few keysyms per keycode: %d\n", keysyms_per_keycode); + exit(1); + } + int k; + for (k = key_lo; k <= key_hi; k++) { + onKeysym(k, + keysyms[(k-key_lo)*keysyms_per_keycode + 0], + keysyms[(k-key_lo)*keysyms_per_keycode + 1]); + } + //TODO: use GetModifierMapping to figure out which modifier is the numlock modifier. +} + +void +processEvents() { + while (XPending(x_dpy)) { + XEvent ev; + XNextEvent(x_dpy, &ev); + switch (ev.type) { + case KeyPress: + case KeyRelease: + onKey(ev.xkey.window, ev.xkey.state, ev.xkey.keycode, ev.type == KeyPress ? 1 : 2); + break; + case ButtonPress: + case ButtonRelease: + onMouse(ev.xbutton.window, ev.xbutton.x, ev.xbutton.y, ev.xbutton.state, ev.xbutton.button, + ev.type == ButtonPress ? 1 : 2); + break; + case MotionNotify: + onMouse(ev.xmotion.window, ev.xmotion.x, ev.xmotion.y, ev.xmotion.state, 0, 0); + break; + case FocusIn: + case FocusOut: + onFocus(ev.xmotion.window, ev.type == FocusIn); + break; + case Expose: + // A non-zero Count means that there are more expose events coming. For + // example, a non-rectangular exposure (e.g. from a partially overlapped + // window) will result in multiple expose events whose dirty rectangles + // combine to define the dirty region. Go's paint events do not provide + // dirty regions, so we only pass on the final X11 expose event. + if (ev.xexpose.count == 0) { + onExpose(ev.xexpose.window); + } + break; + case ConfigureNotify: + onConfigure(ev.xconfigure.window, ev.xconfigure.x, ev.xconfigure.y, + ev.xconfigure.width, ev.xconfigure.height, + DisplayWidth(x_dpy, DefaultScreen(x_dpy)), + DisplayWidthMM(x_dpy, DefaultScreen(x_dpy))); + break; + case ClientMessage: + if ((ev.xclient.message_type != wm_protocols) || (ev.xclient.format != 32)) { + break; + } + Atom a = ev.xclient.data.l[0]; + if (a == wm_delete_window) { + onDeleteWindow(ev.xclient.window); + } else if (a == wm_take_focus) { + XSetInputFocus(x_dpy, ev.xclient.window, RevertToParent, ev.xclient.data.l[1]); + } + break; + } + } +} + +void +makeCurrent(uintptr_t surface) { + EGLSurface surf = (EGLSurface)(surface); + if (!eglMakeCurrent(e_dpy, surf, surf, e_ctx)) { + fprintf(stderr, "eglMakeCurrent failed: %s\n", eglGetErrorStr()); + exit(1); + } +} + +void +swapBuffers(uintptr_t surface) { + EGLSurface surf = (EGLSurface)(surface); + if (!eglSwapBuffers(e_dpy, surf)) { + fprintf(stderr, "eglSwapBuffers failed: %s\n", eglGetErrorStr()); + exit(1); + } +} + +void +doCloseWindow(uintptr_t id) { + Window win = (Window)(id); + XDestroyWindow(x_dpy, win); +} + +uintptr_t +doNewWindow(int width, int height, char* title, int title_len) { + XSetWindowAttributes attr; + attr.colormap = x_colormap; + attr.event_mask = + KeyPressMask | + KeyReleaseMask | + ButtonPressMask | + ButtonReleaseMask | + PointerMotionMask | + ExposureMask | + StructureNotifyMask | + FocusChangeMask; + + Window win = XCreateWindow( + x_dpy, x_root, 0, 0, width, height, 0, x_visual_info->depth, InputOutput, + x_visual_info->visual, CWColormap | CWEventMask, &attr); + + XSizeHints sizehints; + sizehints.width = width; + sizehints.height = height; + sizehints.flags = USSize; + XSetNormalHints(x_dpy, win, &sizehints); + + Atom atoms[2]; + atoms[0] = wm_delete_window; + atoms[1] = wm_take_focus; + XSetWMProtocols(x_dpy, win, atoms, 2); + + XSetStandardProperties(x_dpy, win, "", "App", None, (char **)NULL, 0, &sizehints); + XChangeProperty(x_dpy, win, net_wm_name, utf8_string, 8, PropModeReplace, title, title_len); + + return win; +} + +uintptr_t +doShowWindow(uintptr_t id) { + Window win = (Window)(id); + XMapWindow(x_dpy, win); + EGLSurface surf = eglCreateWindowSurface(e_dpy, e_config, win, NULL); + if (!surf) { + fprintf(stderr, "eglCreateWindowSurface failed: %s\n", eglGetErrorStr()); + exit(1); + } + return (uintptr_t)(surf); +} + +uintptr_t +surfaceCreate() { + static const EGLint ctx_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_NONE + }; + EGLContext ctx = eglCreateContext(e_dpy, e_config, EGL_NO_CONTEXT, ctx_attribs); + if (!ctx) { + fprintf(stderr, "surface eglCreateContext failed: %s\n", eglGetErrorStr()); + return 0; + } + + static const EGLint cfg_attribs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_NONE + }; + EGLConfig cfg; + EGLint num_configs; + if (!eglChooseConfig(e_dpy, cfg_attribs, &cfg, 1, &num_configs)) { + fprintf(stderr, "gldriver: surface eglChooseConfig failed: %s\n", eglGetErrorStr()); + return 0; + } + + // TODO: use the size of the monitor as a bound for texture size. + static const EGLint attribs[] = { + EGL_WIDTH, 4096, + EGL_HEIGHT, 3072, + EGL_NONE + }; + EGLSurface surface = eglCreatePbufferSurface(e_dpy, cfg, attribs); + if (!surface) { + fprintf(stderr, "gldriver: surface eglCreatePbufferSurface failed: %s\n", eglGetErrorStr()); + return 0; + } + + if (!eglMakeCurrent(e_dpy, surface, surface, ctx)) { + fprintf(stderr, "gldriver: surface eglMakeCurrent failed: %s\n", eglGetErrorStr()); + return 0; + } + + return (uintptr_t)surface; +} diff --git a/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.go b/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.go new file mode 100644 index 00000000..0ccdd59f --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/gldriver/x11.go @@ -0,0 +1,318 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (linux && !android) || openbsd + +package gldriver + +/* +#cgo linux LDFLAGS: -lEGL -lGLESv2 -lX11 +#cgo openbsd LDFLAGS: -L/usr/X11R6/lib/ -lEGL -lGLESv2 -lX11 + +#cgo openbsd CFLAGS: -I/usr/X11R6/include/ + +#include +#include +#include + +char *eglGetErrorStr(); +void startDriver(); +void processEvents(); +void makeCurrent(uintptr_t ctx); +void swapBuffers(uintptr_t ctx); +void doCloseWindow(uintptr_t id); +uintptr_t doNewWindow(int width, int height, char* title, int title_len); +uintptr_t doShowWindow(uintptr_t id); +uintptr_t surfaceCreate(); +*/ +import "C" +import ( + "errors" + "runtime" + "time" + "unsafe" + + "golang.org/x/exp/shiny/driver/internal/x11key" + "golang.org/x/exp/shiny/screen" + "golang.org/x/mobile/event/key" + "golang.org/x/mobile/event/mouse" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/geom" + "golang.org/x/mobile/gl" +) + +const useLifecycler = true + +const handleSizeEventsAtChannelReceive = true + +var theKeysyms x11key.KeysymTable + +func init() { + // It might not be necessary, but it probably doesn't hurt to try to make + // 'the main thread' be 'the X11 / OpenGL thread'. + runtime.LockOSThread() +} + +func newWindow(opts *screen.NewWindowOptions) (uintptr, error) { + width, height := optsSize(opts) + + title := opts.GetTitle() + ctitle := C.CString(title) + defer C.free(unsafe.Pointer(ctitle)) + + retc := make(chan uintptr) + uic <- uiClosure{ + f: func() uintptr { + return uintptr(C.doNewWindow(C.int(width), C.int(height), ctitle, C.int(len(title)))) + }, + retc: retc, + } + return <-retc, nil +} + +func initWindow(w *windowImpl) { + w.glctx, w.worker = glctx, worker +} + +func showWindow(w *windowImpl) { + retc := make(chan uintptr) + uic <- uiClosure{ + f: func() uintptr { + return uintptr(C.doShowWindow(C.uintptr_t(w.id))) + }, + retc: retc, + } + w.ctx = <-retc + go drawLoop(w) +} + +func closeWindow(id uintptr) { + uic <- uiClosure{ + f: func() uintptr { + C.doCloseWindow(C.uintptr_t(id)) + return 0 + }, + } +} + +func drawLoop(w *windowImpl) { + glcontextc <- w.ctx.(uintptr) + go func() { + for range w.publish { + publishc <- w + } + }() +} + +var ( + glcontextc = make(chan uintptr) + publishc = make(chan *windowImpl) + uic = make(chan uiClosure) + + // TODO: don't assume that there is only one window, and hence only + // one (global) GL context. + // + // TODO: should we be able to make a shiny.Texture before having a + // shiny.Window's GL context? Should something like gl.IsProgram be a + // method instead of a function, and have each shiny.Window have its own + // gl.Context? + glctx gl.Context + worker gl.Worker +) + +// uiClosure is a closure to be run on C's UI thread. +type uiClosure struct { + f func() uintptr + retc chan uintptr +} + +func main(f func(screen.Screen)) error { + if gl.Version() == "GL_ES_2_0" { + return errors.New("gldriver: ES 3 required on X11") + } + C.startDriver() + glctx, worker = gl.NewContext() + + closec := make(chan struct{}) + go func() { + f(theScreen) + close(closec) + }() + + // heartbeat is a channel that, at regular intervals, directs the select + // below to also consider X11 events, not just Go events (channel + // communications). + // + // TODO: select instead of poll. Note that knowing whether to call + // C.processEvents needs to select on a file descriptor, and the other + // cases below select on Go channels. + heartbeat := time.NewTicker(time.Second / 60) + workAvailable := worker.WorkAvailable() + + for { + select { + case <-closec: + return nil + case ctx := <-glcontextc: + // TODO: do we need to synchronize with seeing a size event for + // this window's context before or after calling makeCurrent? + // Otherwise, are we racing with the gl.Viewport call? I've + // occasionally seen a stale viewport, if the window manager sets + // the window width and height to something other than that + // requested by XCreateWindow, but it's not easily reproducible. + C.makeCurrent(C.uintptr_t(ctx)) + case w := <-publishc: + C.swapBuffers(C.uintptr_t(w.ctx.(uintptr))) + w.publishDone <- screen.PublishResult{} + case req := <-uic: + ret := req.f() + if req.retc != nil { + req.retc <- ret + } + case <-heartbeat.C: + C.processEvents() + case <-workAvailable: + worker.DoWork() + } + } +} + +//export onExpose +func onExpose(id uintptr) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return + } + + w.Send(paint.Event{External: true}) +} + +//export onKeysym +func onKeysym(k, unshifted, shifted uint32) { + theKeysyms.Table[k][0] = unshifted + theKeysyms.Table[k][1] = shifted +} + +//export onKey +func onKey(id uintptr, state uint16, detail, dir uint8) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return + } + + r, c := theKeysyms.Lookup(detail, state) + w.Send(key.Event{ + Rune: r, + Code: c, + Modifiers: x11key.KeyModifiers(state), + Direction: key.Direction(dir), + }) +} + +//export onMouse +func onMouse(id uintptr, x, y int32, state uint16, button, dir uint8) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return + } + + // TODO: should a mouse.Event have a separate MouseModifiers field, for + // which buttons are pressed during a mouse move? + btn := mouse.Button(button) + switch btn { + case 4: + btn = mouse.ButtonWheelUp + case 5: + btn = mouse.ButtonWheelDown + case 6: + btn = mouse.ButtonWheelLeft + case 7: + btn = mouse.ButtonWheelRight + } + if btn.IsWheel() { + if dir != uint8(mouse.DirPress) { + return + } + dir = uint8(mouse.DirStep) + } + w.Send(mouse.Event{ + X: float32(x), + Y: float32(y), + Button: btn, + Modifiers: x11key.KeyModifiers(state), + Direction: mouse.Direction(dir), + }) +} + +//export onFocus +func onFocus(id uintptr, focused bool) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return + } + + w.lifecycler.SetFocused(focused) + w.lifecycler.SendEvent(w, w.glctx) +} + +//export onConfigure +func onConfigure(id uintptr, x, y, width, height, displayWidth, displayWidthMM int32) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return + } + + w.lifecycler.SetVisible(x+width > 0 && y+height > 0) + w.lifecycler.SendEvent(w, w.glctx) + + const ( + mmPerInch = 25.4 + ptPerInch = 72 + ) + pixelsPerMM := float32(displayWidth) / float32(displayWidthMM) + w.Send(size.Event{ + WidthPx: int(width), + HeightPx: int(height), + WidthPt: geom.Pt(width), + HeightPt: geom.Pt(height), + PixelsPerPt: pixelsPerMM * mmPerInch / ptPerInch, + }) +} + +//export onDeleteWindow +func onDeleteWindow(id uintptr) { + theScreen.mu.Lock() + w := theScreen.windows[id] + theScreen.mu.Unlock() + + if w == nil { + return + } + + w.lifecycler.SetDead(true) + w.lifecycler.SendEvent(w, w.glctx) +} + +func surfaceCreate() error { + if C.surfaceCreate() == 0 { + return errors.New("gldriver: surface creation failed") + } + return nil +} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/drawer/drawer.go b/vendor/golang.org/x/exp/shiny/driver/internal/drawer/drawer.go new file mode 100644 index 00000000..230a174b --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/drawer/drawer.go @@ -0,0 +1,34 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package drawer provides functions that help implement screen.Drawer methods. +package drawer // import "golang.org/x/exp/shiny/driver/internal/drawer" + +import ( + "image" + "image/draw" + + "golang.org/x/exp/shiny/screen" + "golang.org/x/image/math/f64" +) + +// Copy implements the Copy method of the screen.Drawer interface by calling +// the Draw method of that same interface. +func Copy(dst screen.Drawer, dp image.Point, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { + dst.Draw(f64.Aff3{ + 1, 0, float64(dp.X - sr.Min.X), + 0, 1, float64(dp.Y - sr.Min.Y), + }, src, sr, op, opts) +} + +// Scale implements the Scale method of the screen.Drawer interface by calling +// the Draw method of that same interface. +func Scale(dst screen.Drawer, dr image.Rectangle, src screen.Texture, sr image.Rectangle, op draw.Op, opts *screen.DrawOptions) { + rx := float64(dr.Dx()) / float64(sr.Dx()) + ry := float64(dr.Dy()) / float64(sr.Dy()) + dst.Draw(f64.Aff3{ + rx, 0, float64(dr.Min.X) - rx*float64(sr.Min.X), + 0, ry, float64(dr.Min.Y) - ry*float64(sr.Min.Y), + }, src, sr, op, opts) +} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/errscreen/errscreen.go b/vendor/golang.org/x/exp/shiny/driver/internal/errscreen/errscreen.go new file mode 100644 index 00000000..97f9773d --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/errscreen/errscreen.go @@ -0,0 +1,25 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package errscreen provides a stub Screen implementation. +package errscreen // import "golang.org/x/exp/shiny/driver/internal/errscreen" + +import ( + "image" + + "golang.org/x/exp/shiny/screen" +) + +// Stub returns a Screen whose methods all return the given error. +func Stub(err error) screen.Screen { + return stub{err} +} + +type stub struct { + err error +} + +func (s stub) NewBuffer(size image.Point) (screen.Buffer, error) { return nil, s.err } +func (s stub) NewTexture(size image.Point) (screen.Texture, error) { return nil, s.err } +func (s stub) NewWindow(opts *screen.NewWindowOptions) (screen.Window, error) { return nil, s.err } diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/event/event.go b/vendor/golang.org/x/exp/shiny/driver/internal/event/event.go new file mode 100644 index 00000000..686a123b --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/event/event.go @@ -0,0 +1,68 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package event provides an infinitely buffered double-ended queue of events. +package event // import "golang.org/x/exp/shiny/driver/internal/event" + +import ( + "sync" +) + +// Deque is an infinitely buffered double-ended queue of events. The zero value +// is usable, but a Deque value must not be copied. +type Deque struct { + mu sync.Mutex + cond sync.Cond // cond.L is lazily initialized to &Deque.mu. + back []interface{} // FIFO. + front []interface{} // LIFO. +} + +func (q *Deque) lockAndInit() { + q.mu.Lock() + if q.cond.L == nil { + q.cond.L = &q.mu + } +} + +// NextEvent implements the screen.EventDeque interface. +func (q *Deque) NextEvent() interface{} { + q.lockAndInit() + defer q.mu.Unlock() + + for { + if n := len(q.front); n > 0 { + e := q.front[n-1] + q.front[n-1] = nil + q.front = q.front[:n-1] + return e + } + + if n := len(q.back); n > 0 { + e := q.back[0] + q.back[0] = nil + q.back = q.back[1:] + return e + } + + q.cond.Wait() + } +} + +// Send implements the screen.EventDeque interface. +func (q *Deque) Send(event interface{}) { + q.lockAndInit() + defer q.mu.Unlock() + + q.back = append(q.back, event) + q.cond.Signal() +} + +// SendFirst implements the screen.EventDeque interface. +func (q *Deque) SendFirst(event interface{}) { + q.lockAndInit() + defer q.mu.Unlock() + + q.front = append(q.front, event) + q.cond.Signal() +} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/lifecycler/lifecycler.go b/vendor/golang.org/x/exp/shiny/driver/internal/lifecycler/lifecycler.go new file mode 100644 index 00000000..53d3543d --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/lifecycler/lifecycler.go @@ -0,0 +1,80 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package lifecycler tracks a window's lifecycle state. +// +// It eliminates sending redundant lifecycle events, ones where the From and To +// stages are equal. For example, moving a window from one part of the screen +// to another should not send multiple events from StageVisible to +// StageVisible, even though the underlying window system's message might only +// hold the new position, and not whether the window was previously visible. +package lifecycler // import "golang.org/x/exp/shiny/driver/internal/lifecycler" + +import ( + "sync" + + "golang.org/x/mobile/event/lifecycle" +) + +// State is a window's lifecycle state. +type State struct { + mu sync.Mutex + stage lifecycle.Stage + dead bool + focused bool + visible bool +} + +func (s *State) SetDead(b bool) { + s.mu.Lock() + s.dead = b + s.mu.Unlock() +} + +func (s *State) SetFocused(b bool) { + s.mu.Lock() + s.focused = b + s.mu.Unlock() +} + +func (s *State) SetVisible(b bool) { + s.mu.Lock() + s.visible = b + s.mu.Unlock() +} + +func (s *State) SendEvent(r Sender, drawContext interface{}) { + s.mu.Lock() + from, to := s.stage, lifecycle.StageAlive + // The order of these if's is important. For example, once a window becomes + // StageDead, it should never change stage again. + // + // Similarly, focused trumps visible. It's hard to imagine a situation + // where a window is focused and not visible on screen, but in that + // unlikely case, StageFocused seems the most appropriate stage. + if s.dead { + to = lifecycle.StageDead + } else if s.focused { + to = lifecycle.StageFocused + } else if s.visible { + to = lifecycle.StageVisible + } + s.stage = to + s.mu.Unlock() + + if from != to { + r.Send(lifecycle.Event{ + From: from, + To: to, + + // TODO: does shiny use this at all? + DrawContext: drawContext, + }) + } +} + +// Sender is who to send the lifecycle event to. +type Sender interface { + Send(event interface{}) +} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/key.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/key.go new file mode 100644 index 00000000..da75d9a9 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/win32/key.go @@ -0,0 +1,350 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package win32 + +import ( + "fmt" + "syscall" + "unicode/utf16" + + "golang.org/x/mobile/event/key" +) + +// convVirtualKeyCode converts a Win32 virtual key code number +// into the standard keycodes used by the key package. +func convVirtualKeyCode(vKey uint32) key.Code { + switch vKey { + case 0x01: // VK_LBUTTON left mouse button + case 0x02: // VK_RBUTTON right mouse button + case 0x03: // VK_CANCEL control-break processing + case 0x04: // VK_MBUTTON middle mouse button + case 0x05: // VK_XBUTTON1 X1 mouse button + case 0x06: // VK_XBUTTON2 X2 mouse button + case 0x08: // VK_BACK + return key.CodeDeleteBackspace + case 0x09: // VK_TAB + return key.CodeTab + case 0x0C: // VK_CLEAR + case 0x0D: // VK_RETURN + return key.CodeReturnEnter + case 0x10: // VK_SHIFT + return key.CodeLeftShift + case 0x11: // VK_CONTROL + return key.CodeLeftControl + case 0x12: // VK_MENU + return key.CodeLeftAlt + case 0x13: // VK_PAUSE + case 0x14: // VK_CAPITAL + return key.CodeCapsLock + case 0x15: // VK_KANA, VK_HANGUEL, VK_HANGUL + case 0x17: // VK_JUNJA + case 0x18: // VK_FINA, L + case 0x19: // VK_HANJA, VK_KANJI + case 0x1B: // VK_ESCAPE + return key.CodeEscape + case 0x1C: // VK_CONVERT + case 0x1D: // VK_NONCONVERT + case 0x1E: // VK_ACCEPT + case 0x1F: // VK_MODECHANGE + case 0x20: // VK_SPACE + return key.CodeSpacebar + case 0x21: // VK_PRIOR + return key.CodePageUp + case 0x22: // VK_NEXT + return key.CodePageDown + case 0x23: // VK_END + return key.CodeEnd + case 0x24: // VK_HOME + return key.CodeHome + case 0x25: // VK_LEFT + return key.CodeLeftArrow + case 0x26: // VK_UP + return key.CodeUpArrow + case 0x27: // VK_RIGHT + return key.CodeRightArrow + case 0x28: // VK_DOWN + return key.CodeDownArrow + case 0x29: // VK_SELECT + case 0x2A: // VK_PRINT + case 0x2B: // VK_EXECUTE + case 0x2C: // VK_SNAPSHOT + case 0x2D: // VK_INSERT + case 0x2E: // VK_DELETE + return key.CodeDeleteForward + case 0x2F: // VK_HELP + return key.CodeHelp + case 0x30: + return key.Code0 + case 0x31: + return key.Code1 + case 0x32: + return key.Code2 + case 0x33: + return key.Code3 + case 0x34: + return key.Code4 + case 0x35: + return key.Code5 + case 0x36: + return key.Code6 + case 0x37: + return key.Code7 + case 0x38: + return key.Code8 + case 0x39: + return key.Code9 + case 0x41: + return key.CodeA + case 0x42: + return key.CodeB + case 0x43: + return key.CodeC + case 0x44: + return key.CodeD + case 0x45: + return key.CodeE + case 0x46: + return key.CodeF + case 0x47: + return key.CodeG + case 0x48: + return key.CodeH + case 0x49: + return key.CodeI + case 0x4A: + return key.CodeJ + case 0x4B: + return key.CodeK + case 0x4C: + return key.CodeL + case 0x4D: + return key.CodeM + case 0x4E: + return key.CodeN + case 0x4F: + return key.CodeO + case 0x50: + return key.CodeP + case 0x51: + return key.CodeQ + case 0x52: + return key.CodeR + case 0x53: + return key.CodeS + case 0x54: + return key.CodeT + case 0x55: + return key.CodeU + case 0x56: + return key.CodeV + case 0x57: + return key.CodeW + case 0x58: + return key.CodeX + case 0x59: + return key.CodeY + case 0x5A: + return key.CodeZ + case 0x5B: // VK_LWIN + return key.CodeLeftGUI + case 0x5C: // VK_RWIN + return key.CodeRightGUI + case 0x5D: // VK_APPS + case 0x5F: // VK_SLEEP + case 0x60: // VK_NUMPAD0 + return key.CodeKeypad0 + case 0x61: // VK_NUMPAD1 + return key.CodeKeypad1 + case 0x62: // VK_NUMPAD2 + return key.CodeKeypad2 + case 0x63: // VK_NUMPAD3 + return key.CodeKeypad3 + case 0x64: // VK_NUMPAD4 + return key.CodeKeypad4 + case 0x65: // VK_NUMPAD5 + return key.CodeKeypad5 + case 0x66: // VK_NUMPAD6 + return key.CodeKeypad6 + case 0x67: // VK_NUMPAD7 + return key.CodeKeypad7 + case 0x68: // VK_NUMPAD8 + return key.CodeKeypad8 + case 0x69: // VK_NUMPAD9 + return key.CodeKeypad9 + case 0x6A: // VK_MULTIPLY + return key.CodeKeypadAsterisk + case 0x6B: // VK_ADD + return key.CodeKeypadPlusSign + case 0x6C: // VK_SEPARATOR + case 0x6D: // VK_SUBTRACT + return key.CodeKeypadHyphenMinus + case 0x6E: // VK_DECIMAL + return key.CodeFullStop + case 0x6F: // VK_DIVIDE + return key.CodeKeypadSlash + case 0x70: // VK_F1 + return key.CodeF1 + case 0x71: // VK_F2 + return key.CodeF2 + case 0x72: // VK_F3 + return key.CodeF3 + case 0x73: // VK_F4 + return key.CodeF4 + case 0x74: // VK_F5 + return key.CodeF5 + case 0x75: // VK_F6 + return key.CodeF6 + case 0x76: // VK_F7 + return key.CodeF7 + case 0x77: // VK_F8 + return key.CodeF8 + case 0x78: // VK_F9 + return key.CodeF9 + case 0x79: // VK_F10 + return key.CodeF10 + case 0x7A: // VK_F11 + return key.CodeF11 + case 0x7B: // VK_F12 + return key.CodeF12 + case 0x7C: // VK_F13 + return key.CodeF13 + case 0x7D: // VK_F14 + return key.CodeF14 + case 0x7E: // VK_F15 + return key.CodeF15 + case 0x7F: // VK_F16 + return key.CodeF16 + case 0x80: // VK_F17 + return key.CodeF17 + case 0x81: // VK_F18 + return key.CodeF18 + case 0x82: // VK_F19 + return key.CodeF19 + case 0x83: // VK_F20 + return key.CodeF20 + case 0x84: // VK_F21 + return key.CodeF21 + case 0x85: // VK_F22 + return key.CodeF22 + case 0x86: // VK_F23 + return key.CodeF23 + case 0x87: // VK_F24 + return key.CodeF24 + case 0x90: // VK_NUMLOCK + return key.CodeKeypadNumLock + case 0x91: // VK_SCROLL + case 0xA0: // VK_LSHIFT + return key.CodeLeftShift + case 0xA1: // VK_RSHIFT + return key.CodeRightShift + case 0xA2: // VK_LCONTROL + return key.CodeLeftControl + case 0xA3: // VK_RCONTROL + return key.CodeRightControl + case 0xA4: // VK_LMENU + case 0xA5: // VK_RMENU + case 0xA6: // VK_BROWSER_BACK + case 0xA7: // VK_BROWSER_FORWARD + case 0xA8: // VK_BROWSER_REFRESH + case 0xA9: // VK_BROWSER_STOP + case 0xAA: // VK_BROWSER_SEARCH + case 0xAB: // VK_BROWSER_FAVORITES + case 0xAC: // VK_BROWSER_HOME + case 0xAD: // VK_VOLUME_MUTE + return key.CodeMute + case 0xAE: // VK_VOLUME_DOWN + return key.CodeVolumeDown + case 0xAF: // VK_VOLUME_UP + return key.CodeVolumeUp + case 0xB0: // VK_MEDIA_NEXT_TRACK + case 0xB1: // VK_MEDIA_PREV_TRACK + case 0xB2: // VK_MEDIA_STOP + case 0xB3: // VK_MEDIA_PLAY_PAUSE + case 0xB4: // VK_LAUNCH_MAIL + case 0xB5: // VK_LAUNCH_MEDIA_SELECT + case 0xB6: // VK_LAUNCH_APP1 + case 0xB7: // VK_LAUNCH_APP2 + case 0xBA: // VK_OEM_1 ';:' + return key.CodeSemicolon + case 0xBB: // VK_OEM_PLUS '+' + return key.CodeEqualSign + case 0xBC: // VK_OEM_COMMA ',' + return key.CodeComma + case 0xBD: // VK_OEM_MINUS '-' + return key.CodeHyphenMinus + case 0xBE: // VK_OEM_PERIOD '.' + return key.CodeFullStop + case 0xBF: // VK_OEM_2 '/?' + return key.CodeSlash + case 0xC0: // VK_OEM_3 '`~' + return key.CodeGraveAccent + case 0xDB: // VK_OEM_4 '[{' + return key.CodeLeftSquareBracket + case 0xDC: // VK_OEM_5 '\|' + return key.CodeBackslash + case 0xDD: // VK_OEM_6 ']}' + return key.CodeRightSquareBracket + case 0xDE: // VK_OEM_7 'single-quote/double-quote' + return key.CodeApostrophe + case 0xDF: // VK_OEM_8 + return key.CodeUnknown + case 0xE2: // VK_OEM_102 + case 0xE5: // VK_PROCESSKEY + case 0xE7: // VK_PACKET + case 0xF6: // VK_ATTN + case 0xF7: // VK_CRSEL + case 0xF8: // VK_EXSEL + case 0xF9: // VK_EREOF + case 0xFA: // VK_PLAY + case 0xFB: // VK_ZOOM + case 0xFC: // VK_NONAME + case 0xFD: // VK_PA1 + case 0xFE: // VK_OEM_CLEAR + } + return key.CodeUnknown +} + +func readRune(vKey uint32, scanCode uint8) rune { + var ( + keystate [256]byte + buf [4]uint16 + ) + if err := _GetKeyboardState(&keystate[0]); err != nil { + panic(fmt.Sprintf("win32: %v", err)) + } + // TODO: cache GetKeyboardLayout result, update on WM_INPUTLANGCHANGE + layout := _GetKeyboardLayout(0) + ret := _ToUnicodeEx(vKey, uint32(scanCode), &keystate[0], &buf[0], int32(len(buf)), 0, layout) + if ret < 1 { + return -1 + } + return utf16.Decode(buf[:ret])[0] +} + +func sendKeyEvent(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { + e := key.Event{ + Rune: readRune(uint32(wParam), uint8(lParam>>16)), + Code: convVirtualKeyCode(uint32(wParam)), + Modifiers: keyModifiers(), + } + switch uMsg { + case _WM_KEYDOWN, _WM_SYSKEYDOWN: + const prevMask = 1 << 30 + if repeat := lParam&prevMask == prevMask; repeat { + e.Direction = key.DirNone + } else { + e.Direction = key.DirPress + } + case _WM_KEYUP, _WM_SYSKEYUP: + e.Direction = key.DirRelease + default: + panic(fmt.Sprintf("win32: unexpected key message: %d", uMsg)) + } + + KeyEvent(hwnd, e) + return 0 +} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall.go new file mode 100644 index 00000000..43366e9d --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall.go @@ -0,0 +1,7 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output zsyscall_windows.go syscall_windows.go + +package win32 diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall_windows.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall_windows.go new file mode 100644 index 00000000..d71536d6 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/win32/syscall_windows.go @@ -0,0 +1,186 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package win32 + +import ( + "syscall" +) + +type _COLORREF uint32 + +func _RGB(r, g, b byte) _COLORREF { + return _COLORREF(r) | _COLORREF(g)<<8 | _COLORREF(b)<<16 +} + +type _POINT struct { + X int32 + Y int32 +} + +type _RECT struct { + Left int32 + Top int32 + Right int32 + Bottom int32 +} + +type _MSG struct { + HWND syscall.Handle + Message uint32 + Wparam uintptr + Lparam uintptr + Time uint32 + Pt _POINT +} + +type _WNDCLASS struct { + Style uint32 + LpfnWndProc uintptr + CbClsExtra int32 + CbWndExtra int32 + HInstance syscall.Handle + HIcon syscall.Handle + HCursor syscall.Handle + HbrBackground syscall.Handle + LpszMenuName *uint16 + LpszClassName *uint16 +} + +type _WINDOWPOS struct { + HWND syscall.Handle + HWNDInsertAfter syscall.Handle + X int32 + Y int32 + Cx int32 + Cy int32 + Flags uint32 +} + +const ( + _WM_SETFOCUS = 7 + _WM_KILLFOCUS = 8 + _WM_PAINT = 15 + _WM_CLOSE = 16 + _WM_WINDOWPOSCHANGED = 71 + _WM_KEYDOWN = 256 + _WM_KEYUP = 257 + _WM_SYSKEYDOWN = 260 + _WM_SYSKEYUP = 261 + _WM_MOUSEMOVE = 512 + _WM_MOUSEWHEEL = 522 + _WM_LBUTTONDOWN = 513 + _WM_LBUTTONUP = 514 + _WM_RBUTTONDOWN = 516 + _WM_RBUTTONUP = 517 + _WM_MBUTTONDOWN = 519 + _WM_MBUTTONUP = 520 + _WM_USER = 0x0400 +) + +const ( + _WS_OVERLAPPED = 0x00000000 + _WS_CAPTION = 0x00C00000 + _WS_SYSMENU = 0x00080000 + _WS_THICKFRAME = 0x00040000 + _WS_MINIMIZEBOX = 0x00020000 + _WS_MAXIMIZEBOX = 0x00010000 + _WS_OVERLAPPEDWINDOW = _WS_OVERLAPPED | _WS_CAPTION | _WS_SYSMENU | _WS_THICKFRAME | _WS_MINIMIZEBOX | _WS_MAXIMIZEBOX +) + +const ( + _VK_SHIFT = 16 + _VK_CONTROL = 17 + _VK_MENU = 18 + _VK_LWIN = 0x5B + _VK_RWIN = 0x5C +) + +const ( + _MK_LBUTTON = 0x0001 + _MK_MBUTTON = 0x0010 + _MK_RBUTTON = 0x0002 +) + +const ( + _COLOR_BTNFACE = 15 +) + +const ( + _IDI_APPLICATION = 32512 + _IDC_ARROW = 32512 +) + +const ( + _CW_USEDEFAULT = 0x80000000 - 0x100000000 + + _SW_SHOWDEFAULT = 10 + + _HWND_MESSAGE = syscall.Handle(^uintptr(2)) // -3 + + _SWP_NOSIZE = 0x0001 +) + +const ( + _BI_RGB = 0 + _DIB_RGB_COLORS = 0 + + _AC_SRC_OVER = 0x00 + _AC_SRC_ALPHA = 0x01 + + _SRCCOPY = 0x00cc0020 + + _WHEEL_DELTA = 120 +) + +func _GET_X_LPARAM(lp uintptr) int32 { + return int32(_LOWORD(lp)) +} + +func _GET_Y_LPARAM(lp uintptr) int32 { + return int32(_HIWORD(lp)) +} + +func _GET_WHEEL_DELTA_WPARAM(lp uintptr) int16 { + return int16(_HIWORD(lp)) +} + +func _LOWORD(l uintptr) uint16 { + return uint16(uint32(l)) +} + +func _HIWORD(l uintptr) uint16 { + return uint16(uint32(l >> 16)) +} + +// notes to self +// UINT = uint32 +// callbacks = uintptr +// strings = *uint16 + +//sys GetDC(hwnd syscall.Handle) (dc syscall.Handle, err error) = user32.GetDC +//sys ReleaseDC(hwnd syscall.Handle, dc syscall.Handle) (err error) = user32.ReleaseDC +//sys sendMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) = user32.SendMessageW + +//sys _CreateWindowEx(exstyle uint32, className *uint16, windowText *uint16, style uint32, x int32, y int32, width int32, height int32, parent syscall.Handle, menu syscall.Handle, hInstance syscall.Handle, lpParam uintptr) (hwnd syscall.Handle, err error) = user32.CreateWindowExW +//sys _DefWindowProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) = user32.DefWindowProcW +//sys _DestroyWindow(hwnd syscall.Handle) (err error) = user32.DestroyWindow +//sys _DispatchMessage(msg *_MSG) (ret int32) = user32.DispatchMessageW +//sys _GetClientRect(hwnd syscall.Handle, rect *_RECT) (err error) = user32.GetClientRect +//sys _GetWindowRect(hwnd syscall.Handle, rect *_RECT) (err error) = user32.GetWindowRect +//sys _GetKeyboardLayout(threadID uint32) (locale syscall.Handle) = user32.GetKeyboardLayout +//sys _GetKeyboardState(lpKeyState *byte) (err error) = user32.GetKeyboardState +//sys _GetKeyState(virtkey int32) (keystatus int16) = user32.GetKeyState +//sys _GetMessage(msg *_MSG, hwnd syscall.Handle, msgfiltermin uint32, msgfiltermax uint32) (ret int32, err error) [failretval==-1] = user32.GetMessageW +//sys _LoadCursor(hInstance syscall.Handle, cursorName uintptr) (cursor syscall.Handle, err error) = user32.LoadCursorW +//sys _LoadIcon(hInstance syscall.Handle, iconName uintptr) (icon syscall.Handle, err error) = user32.LoadIconW +//sys _MoveWindow(hwnd syscall.Handle, x int32, y int32, w int32, h int32, repaint bool) (err error) = user32.MoveWindow +//sys _PostMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult bool) = user32.PostMessageW +//sys _PostQuitMessage(exitCode int32) = user32.PostQuitMessage +//sys _RegisterClass(wc *_WNDCLASS) (atom uint16, err error) = user32.RegisterClassW +//sys _ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) = user32.ShowWindow +//sys _ScreenToClient(hwnd syscall.Handle, lpPoint *_POINT) (ok bool) = user32.ScreenToClient +//sys _ToUnicodeEx(wVirtKey uint32, wScanCode uint32, lpKeyState *byte, pwszBuff *uint16, cchBuff int32, wFlags uint32, dwhkl syscall.Handle) (ret int32) = user32.ToUnicodeEx +//sys _TranslateMessage(msg *_MSG) (done bool) = user32.TranslateMessage +//sys _UnregisterClass(lpClassName *uint16, hInstance syscall.Handle) (done bool) = user32.UnregisterClassW diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/win32.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/win32.go new file mode 100644 index 00000000..c020ce69 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/win32/win32.go @@ -0,0 +1,519 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +// Package win32 implements a partial shiny screen driver using the Win32 API. +// It provides window, lifecycle, key, and mouse management, but no drawing. +// That is left to windriver (using GDI) or gldriver (using DirectX via ANGLE). +package win32 // import "golang.org/x/exp/shiny/driver/internal/win32" + +import ( + "fmt" + "runtime" + "sync" + "syscall" + "unsafe" + + "golang.org/x/exp/shiny/screen" + "golang.org/x/mobile/event/key" + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/mouse" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/geom" +) + +// screenHWND is the handle to the "Screen window". +// The Screen window encapsulates all screen.Screen operations +// in an actual Windows window so they all run on the main thread. +// Since any messages sent to a window will be executed on the +// main thread, we can safely use the messages below. +var screenHWND syscall.Handle + +const ( + msgCreateWindow = _WM_USER + iota + msgMainCallback + msgShow + msgQuit + msgLast +) + +// userWM is used to generate private (WM_USER and above) window message IDs +// for use by screenWindowWndProc and windowWndProc. +type userWM struct { + sync.Mutex + id uint32 +} + +func (m *userWM) next() uint32 { + m.Lock() + if m.id == 0 { + m.id = msgLast + } + r := m.id + m.id++ + m.Unlock() + return r +} + +var currentUserWM userWM + +func newWindow(opts *screen.NewWindowOptions) (syscall.Handle, error) { + // TODO(brainman): convert windowClass to *uint16 once (in initWindowClass) + wcname, err := syscall.UTF16PtrFromString(windowClass) + if err != nil { + return 0, err + } + title, err := syscall.UTF16PtrFromString(opts.GetTitle()) + if err != nil { + return 0, err + } + hwnd, err := _CreateWindowEx(0, + wcname, title, + _WS_OVERLAPPEDWINDOW, + _CW_USEDEFAULT, _CW_USEDEFAULT, + _CW_USEDEFAULT, _CW_USEDEFAULT, + 0, 0, hThisInstance, 0) + if err != nil { + return 0, err + } + // TODO(andlabs): use proper nCmdShow + // TODO(andlabs): call UpdateWindow() + + return hwnd, nil +} + +// ResizeClientRect makes hwnd client rectangle opts.Width by opts.Height in size. +func ResizeClientRect(hwnd syscall.Handle, opts *screen.NewWindowOptions) error { + if opts == nil || opts.Width <= 0 || opts.Height <= 0 { + return nil + } + var cr, wr _RECT + err := _GetClientRect(hwnd, &cr) + if err != nil { + return err + } + err = _GetWindowRect(hwnd, &wr) + if err != nil { + return err + } + w := (wr.Right - wr.Left) - (cr.Right - int32(opts.Width)) + h := (wr.Bottom - wr.Top) - (cr.Bottom - int32(opts.Height)) + return _MoveWindow(hwnd, wr.Left, wr.Top, w, h, false) +} + +// Show shows a newly created window. +// It sends the appropriate lifecycle events, makes the window appear +// on the screen, and sends an initial size event. +// +// This is a separate step from NewWindow to give the driver a chance +// to setup its internal state for a window before events start being +// delivered. +func Show(hwnd syscall.Handle) { + SendMessage(hwnd, msgShow, 0, 0) +} + +func Release(hwnd syscall.Handle) { + SendMessage(hwnd, _WM_CLOSE, 0, 0) +} + +func sendFocus(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { + switch uMsg { + case _WM_SETFOCUS: + LifecycleEvent(hwnd, lifecycle.StageFocused) + case _WM_KILLFOCUS: + LifecycleEvent(hwnd, lifecycle.StageVisible) + default: + panic(fmt.Sprintf("unexpected focus message: %d", uMsg)) + } + return _DefWindowProc(hwnd, uMsg, wParam, lParam) +} + +func sendShow(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { + LifecycleEvent(hwnd, lifecycle.StageVisible) + _ShowWindow(hwnd, _SW_SHOWDEFAULT) + sendSize(hwnd) + return 0 +} + +func sendSizeEvent(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { + wp := (*_WINDOWPOS)(unsafe.Pointer(lParam)) + if wp.Flags&_SWP_NOSIZE != 0 { + return 0 + } + sendSize(hwnd) + return 0 +} + +func sendSize(hwnd syscall.Handle) { + var r _RECT + if err := _GetClientRect(hwnd, &r); err != nil { + panic(err) // TODO(andlabs) + } + + width := int(r.Right - r.Left) + height := int(r.Bottom - r.Top) + + // TODO(andlabs): don't assume that PixelsPerPt == 1 + SizeEvent(hwnd, size.Event{ + WidthPx: width, + HeightPx: height, + WidthPt: geom.Pt(width), + HeightPt: geom.Pt(height), + PixelsPerPt: 1, + }) +} + +func sendClose(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { + // TODO(ktye): DefWindowProc calls DestroyWindow by default. + // To intercept destruction of the window, return 0 and call + // DestroyWindow when appropriate. + LifecycleEvent(hwnd, lifecycle.StageDead) + return _DefWindowProc(hwnd, uMsg, wParam, lParam) +} + +func sendMouseEvent(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { + e := mouse.Event{ + X: float32(_GET_X_LPARAM(lParam)), + Y: float32(_GET_Y_LPARAM(lParam)), + Modifiers: keyModifiers(), + } + + switch uMsg { + case _WM_MOUSEMOVE: + e.Direction = mouse.DirNone + case _WM_LBUTTONDOWN, _WM_MBUTTONDOWN, _WM_RBUTTONDOWN: + e.Direction = mouse.DirPress + case _WM_LBUTTONUP, _WM_MBUTTONUP, _WM_RBUTTONUP: + e.Direction = mouse.DirRelease + case _WM_MOUSEWHEEL: + // TODO: On a trackpad, a scroll can be a drawn-out affair with a + // distinct beginning and end. Should the intermediate events be + // DirNone? + e.Direction = mouse.DirStep + + // Convert from screen to window coordinates. + p := _POINT{ + int32(e.X), + int32(e.Y), + } + _ScreenToClient(hwnd, &p) + e.X = float32(p.X) + e.Y = float32(p.Y) + default: + panic("sendMouseEvent() called on non-mouse message") + } + + switch uMsg { + case _WM_MOUSEMOVE: + // No-op. + case _WM_LBUTTONDOWN, _WM_LBUTTONUP: + e.Button = mouse.ButtonLeft + case _WM_MBUTTONDOWN, _WM_MBUTTONUP: + e.Button = mouse.ButtonMiddle + case _WM_RBUTTONDOWN, _WM_RBUTTONUP: + e.Button = mouse.ButtonRight + case _WM_MOUSEWHEEL: + // TODO: handle horizontal scrolling + delta := _GET_WHEEL_DELTA_WPARAM(wParam) / _WHEEL_DELTA + switch { + case delta > 0: + e.Button = mouse.ButtonWheelUp + case delta < 0: + e.Button = mouse.ButtonWheelDown + delta = -delta + default: + return + } + for delta > 0 { + MouseEvent(hwnd, e) + delta-- + } + return + } + + MouseEvent(hwnd, e) + + return 0 +} + +// Precondition: this is called in immediate response to the message that triggered the event (so not after w.Send). +func keyModifiers() (m key.Modifiers) { + down := func(x int32) bool { + // GetKeyState gets the key state at the time of the message, so this is what we want. + return _GetKeyState(x)&0x80 != 0 + } + + if down(_VK_CONTROL) { + m |= key.ModControl + } + if down(_VK_MENU) { + m |= key.ModAlt + } + if down(_VK_SHIFT) { + m |= key.ModShift + } + if down(_VK_LWIN) || down(_VK_RWIN) { + m |= key.ModMeta + } + return m +} + +var ( + MouseEvent func(hwnd syscall.Handle, e mouse.Event) + PaintEvent func(hwnd syscall.Handle, e paint.Event) + SizeEvent func(hwnd syscall.Handle, e size.Event) + KeyEvent func(hwnd syscall.Handle, e key.Event) + LifecycleEvent func(hwnd syscall.Handle, e lifecycle.Stage) + + // TODO: use the golang.org/x/exp/shiny/driver/internal/lifecycler package + // instead of or together with the LifecycleEvent callback? +) + +func sendPaint(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr) { + PaintEvent(hwnd, paint.Event{}) + return _DefWindowProc(hwnd, uMsg, wParam, lParam) +} + +var screenMsgs = map[uint32]func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr){} + +func AddScreenMsg(fn func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr)) uint32 { + uMsg := currentUserWM.next() + screenMsgs[uMsg] = func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) uintptr { + fn(hwnd, uMsg, wParam, lParam) + return 0 + } + return uMsg +} + +func screenWindowWndProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { + switch uMsg { + case msgCreateWindow: + p := (*newWindowParams)(unsafe.Pointer(lParam)) + p.w, p.err = newWindow(p.opts) + case msgMainCallback: + go func() { + mainCallback() + SendScreenMessage(msgQuit, 0, 0) + }() + case msgQuit: + _PostQuitMessage(0) + } + fn := screenMsgs[uMsg] + if fn != nil { + return fn(hwnd, uMsg, wParam, lParam) + } + return _DefWindowProc(hwnd, uMsg, wParam, lParam) +} + +//go:uintptrescapes + +func SendScreenMessage(uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { + return SendMessage(screenHWND, uMsg, wParam, lParam) +} + +var windowMsgs = map[uint32]func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) (lResult uintptr){ + _WM_SETFOCUS: sendFocus, + _WM_KILLFOCUS: sendFocus, + _WM_PAINT: sendPaint, + msgShow: sendShow, + _WM_WINDOWPOSCHANGED: sendSizeEvent, + _WM_CLOSE: sendClose, + + _WM_LBUTTONDOWN: sendMouseEvent, + _WM_LBUTTONUP: sendMouseEvent, + _WM_MBUTTONDOWN: sendMouseEvent, + _WM_MBUTTONUP: sendMouseEvent, + _WM_RBUTTONDOWN: sendMouseEvent, + _WM_RBUTTONUP: sendMouseEvent, + _WM_MOUSEMOVE: sendMouseEvent, + _WM_MOUSEWHEEL: sendMouseEvent, + + _WM_KEYDOWN: sendKeyEvent, + _WM_KEYUP: sendKeyEvent, + _WM_SYSKEYDOWN: sendKeyEvent, + _WM_SYSKEYUP: sendKeyEvent, +} + +func AddWindowMsg(fn func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr)) uint32 { + uMsg := currentUserWM.next() + windowMsgs[uMsg] = func(hwnd syscall.Handle, uMsg uint32, wParam, lParam uintptr) uintptr { + fn(hwnd, uMsg, wParam, lParam) + return 0 + } + return uMsg +} + +func windowWndProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { + fn := windowMsgs[uMsg] + if fn != nil { + return fn(hwnd, uMsg, wParam, lParam) + } + return _DefWindowProc(hwnd, uMsg, wParam, lParam) +} + +type newWindowParams struct { + opts *screen.NewWindowOptions + w syscall.Handle + err error +} + +func NewWindow(opts *screen.NewWindowOptions) (syscall.Handle, error) { + var p newWindowParams + p.opts = opts + SendScreenMessage(msgCreateWindow, 0, uintptr(unsafe.Pointer(&p))) + return p.w, p.err +} + +const windowClass = "shiny_Window" +const screenWindowClass = "shiny_ScreenWindow" + +func initWindowClass() (err error) { + wcname, err := syscall.UTF16PtrFromString(windowClass) + if err != nil { + return err + } + _, err = _RegisterClass(&_WNDCLASS{ + LpszClassName: wcname, + LpfnWndProc: syscall.NewCallback(windowWndProc), + HIcon: hDefaultIcon, + HCursor: hDefaultCursor, + HInstance: hThisInstance, + // TODO(andlabs): change this to something else? NULL? the hollow brush? + HbrBackground: syscall.Handle(_COLOR_BTNFACE + 1), + }) + return err +} + +func closeWindowClass() (err error) { + wcname, err := syscall.UTF16PtrFromString(windowClass) + if err != nil { + return err + } + _UnregisterClass(wcname, hThisInstance) + + return nil +} + +func initScreenWindow() (err error) { + swc, err := syscall.UTF16PtrFromString(screenWindowClass) + if err != nil { + return err + } + emptyString, err := syscall.UTF16PtrFromString("") + if err != nil { + return err + } + wc := _WNDCLASS{ + LpszClassName: swc, + LpfnWndProc: syscall.NewCallback(screenWindowWndProc), + HIcon: hDefaultIcon, + HCursor: hDefaultCursor, + HInstance: hThisInstance, + HbrBackground: syscall.Handle(_COLOR_BTNFACE + 1), + } + _, err = _RegisterClass(&wc) + if err != nil { + return err + } + screenHWND, err = _CreateWindowEx(0, + swc, emptyString, + _WS_OVERLAPPEDWINDOW, + _CW_USEDEFAULT, _CW_USEDEFAULT, + _CW_USEDEFAULT, _CW_USEDEFAULT, + _HWND_MESSAGE, 0, hThisInstance, 0) + if err != nil { + return err + } + return nil +} + +func closeScreenWindow() (err error) { + // first destroy window + _DestroyWindow(screenHWND) + + // then unregister class + swc, err := syscall.UTF16PtrFromString(screenWindowClass) + if err != nil { + return err + } + _UnregisterClass(swc, hThisInstance) + + return nil +} + +var ( + hDefaultIcon syscall.Handle + hDefaultCursor syscall.Handle + hThisInstance syscall.Handle +) + +func initCommon() (err error) { + hDefaultIcon, err = _LoadIcon(0, _IDI_APPLICATION) + if err != nil { + return err + } + hDefaultCursor, err = _LoadCursor(0, _IDC_ARROW) + if err != nil { + return err + } + // TODO(andlabs) hThisInstance + return nil +} + +//go:uintptrescapes + +func SendMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { + return sendMessage(hwnd, uMsg, wParam, lParam) +} + +var mainCallback func() + +func Main(f func()) (retErr error) { + // It does not matter which OS thread we are on. + // All that matters is that we confine all UI operations + // to the thread that created the respective window. + runtime.LockOSThread() + + if err := initCommon(); err != nil { + return err + } + + if err := initScreenWindow(); err != nil { + return err + } + defer func() { + // TODO(andlabs): log an error if this fails? + closeScreenWindow() + }() + + if err := initWindowClass(); err != nil { + return err + } + defer func() { + // TODO(andlabs): log an error if this fails? + closeWindowClass() + }() + + // Prime the pump. + mainCallback = f + _PostMessage(screenHWND, msgMainCallback, 0, 0) + + // Main message pump. + var m _MSG + for { + done, err := _GetMessage(&m, 0, 0, 0) + if err != nil { + return fmt.Errorf("win32 GetMessage failed: %v", err) + } + if done == 0 { // WM_QUIT + break + } + _TranslateMessage(&m) + _DispatchMessage(&m) + } + + return nil +} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/win32/zsyscall_windows.go b/vendor/golang.org/x/exp/shiny/driver/internal/win32/zsyscall_windows.go new file mode 100644 index 00000000..26999f65 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/win32/zsyscall_windows.go @@ -0,0 +1,293 @@ +// MACHINE GENERATED BY 'go generate' COMMAND; DO NOT EDIT + +package win32 + +import ( + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +var _ unsafe.Pointer + +// Do the interface allocations only once for common +// Errno values. +const ( + errnoERROR_IO_PENDING = 997 +) + +var ( + errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING) +) + +// errnoErr returns common boxed Errno values, to prevent +// allocations at runtime. +func errnoErr(e syscall.Errno) error { + switch e { + case 0: + return nil + case errnoERROR_IO_PENDING: + return errERROR_IO_PENDING + } + // TODO: add more here, after collecting data on the common + // error values see on Windows. (perhaps when running + // all.bat?) + return e +} + +var ( + moduser32 = windows.NewLazySystemDLL("user32.dll") + + procGetDC = moduser32.NewProc("GetDC") + procReleaseDC = moduser32.NewProc("ReleaseDC") + procSendMessageW = moduser32.NewProc("SendMessageW") + procCreateWindowExW = moduser32.NewProc("CreateWindowExW") + procDefWindowProcW = moduser32.NewProc("DefWindowProcW") + procDestroyWindow = moduser32.NewProc("DestroyWindow") + procDispatchMessageW = moduser32.NewProc("DispatchMessageW") + procGetClientRect = moduser32.NewProc("GetClientRect") + procGetWindowRect = moduser32.NewProc("GetWindowRect") + procGetKeyboardLayout = moduser32.NewProc("GetKeyboardLayout") + procGetKeyboardState = moduser32.NewProc("GetKeyboardState") + procGetKeyState = moduser32.NewProc("GetKeyState") + procGetMessageW = moduser32.NewProc("GetMessageW") + procLoadCursorW = moduser32.NewProc("LoadCursorW") + procLoadIconW = moduser32.NewProc("LoadIconW") + procMoveWindow = moduser32.NewProc("MoveWindow") + procPostMessageW = moduser32.NewProc("PostMessageW") + procPostQuitMessage = moduser32.NewProc("PostQuitMessage") + procRegisterClassW = moduser32.NewProc("RegisterClassW") + procShowWindow = moduser32.NewProc("ShowWindow") + procScreenToClient = moduser32.NewProc("ScreenToClient") + procToUnicodeEx = moduser32.NewProc("ToUnicodeEx") + procTranslateMessage = moduser32.NewProc("TranslateMessage") + procUnregisterClassW = moduser32.NewProc("UnregisterClassW") +) + +func GetDC(hwnd syscall.Handle) (dc syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall(procGetDC.Addr(), 1, uintptr(hwnd), 0, 0) + dc = syscall.Handle(r0) + if dc == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func ReleaseDC(hwnd syscall.Handle, dc syscall.Handle) (err error) { + r1, _, e1 := syscall.Syscall(procReleaseDC.Addr(), 2, uintptr(hwnd), uintptr(dc), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func sendMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { + r0, _, _ := syscall.Syscall6(procSendMessageW.Addr(), 4, uintptr(hwnd), uintptr(uMsg), uintptr(wParam), uintptr(lParam), 0, 0) + lResult = uintptr(r0) + return +} + +func _CreateWindowEx(exstyle uint32, className *uint16, windowText *uint16, style uint32, x int32, y int32, width int32, height int32, parent syscall.Handle, menu syscall.Handle, hInstance syscall.Handle, lpParam uintptr) (hwnd syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall12(procCreateWindowExW.Addr(), 12, uintptr(exstyle), uintptr(unsafe.Pointer(className)), uintptr(unsafe.Pointer(windowText)), uintptr(style), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(parent), uintptr(menu), uintptr(hInstance), uintptr(lpParam)) + hwnd = syscall.Handle(r0) + if hwnd == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _DefWindowProc(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult uintptr) { + r0, _, _ := syscall.Syscall6(procDefWindowProcW.Addr(), 4, uintptr(hwnd), uintptr(uMsg), uintptr(wParam), uintptr(lParam), 0, 0) + lResult = uintptr(r0) + return +} + +func _DestroyWindow(hwnd syscall.Handle) (err error) { + r1, _, e1 := syscall.Syscall(procDestroyWindow.Addr(), 1, uintptr(hwnd), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _DispatchMessage(msg *_MSG) (ret int32) { + r0, _, _ := syscall.Syscall(procDispatchMessageW.Addr(), 1, uintptr(unsafe.Pointer(msg)), 0, 0) + ret = int32(r0) + return +} + +func _GetClientRect(hwnd syscall.Handle, rect *_RECT) (err error) { + r1, _, e1 := syscall.Syscall(procGetClientRect.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(rect)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetWindowRect(hwnd syscall.Handle, rect *_RECT) (err error) { + r1, _, e1 := syscall.Syscall(procGetWindowRect.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(rect)), 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetKeyboardLayout(threadID uint32) (locale syscall.Handle) { + r0, _, _ := syscall.Syscall(procGetKeyboardLayout.Addr(), 1, uintptr(threadID), 0, 0) + locale = syscall.Handle(r0) + return +} + +func _GetKeyboardState(lpKeyState *byte) (err error) { + r1, _, e1 := syscall.Syscall(procGetKeyboardState.Addr(), 1, uintptr(unsafe.Pointer(lpKeyState)), 0, 0) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _GetKeyState(virtkey int32) (keystatus int16) { + r0, _, _ := syscall.Syscall(procGetKeyState.Addr(), 1, uintptr(virtkey), 0, 0) + keystatus = int16(r0) + return +} + +func _GetMessage(msg *_MSG, hwnd syscall.Handle, msgfiltermin uint32, msgfiltermax uint32) (ret int32, err error) { + r0, _, e1 := syscall.Syscall6(procGetMessageW.Addr(), 4, uintptr(unsafe.Pointer(msg)), uintptr(hwnd), uintptr(msgfiltermin), uintptr(msgfiltermax), 0, 0) + ret = int32(r0) + if ret == -1 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _LoadCursor(hInstance syscall.Handle, cursorName uintptr) (cursor syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall(procLoadCursorW.Addr(), 2, uintptr(hInstance), uintptr(cursorName), 0) + cursor = syscall.Handle(r0) + if cursor == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _LoadIcon(hInstance syscall.Handle, iconName uintptr) (icon syscall.Handle, err error) { + r0, _, e1 := syscall.Syscall(procLoadIconW.Addr(), 2, uintptr(hInstance), uintptr(iconName), 0) + icon = syscall.Handle(r0) + if icon == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _MoveWindow(hwnd syscall.Handle, x int32, y int32, w int32, h int32, repaint bool) (err error) { + var _p0 uint32 + if repaint { + _p0 = 1 + } else { + _p0 = 0 + } + r1, _, e1 := syscall.Syscall6(procMoveWindow.Addr(), 6, uintptr(hwnd), uintptr(x), uintptr(y), uintptr(w), uintptr(h), uintptr(_p0)) + if r1 == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _PostMessage(hwnd syscall.Handle, uMsg uint32, wParam uintptr, lParam uintptr) (lResult bool) { + r0, _, _ := syscall.Syscall6(procPostMessageW.Addr(), 4, uintptr(hwnd), uintptr(uMsg), uintptr(wParam), uintptr(lParam), 0, 0) + lResult = r0 != 0 + return +} + +func _PostQuitMessage(exitCode int32) { + syscall.Syscall(procPostQuitMessage.Addr(), 1, uintptr(exitCode), 0, 0) + return +} + +func _RegisterClass(wc *_WNDCLASS) (atom uint16, err error) { + r0, _, e1 := syscall.Syscall(procRegisterClassW.Addr(), 1, uintptr(unsafe.Pointer(wc)), 0, 0) + atom = uint16(r0) + if atom == 0 { + if e1 != 0 { + err = errnoErr(e1) + } else { + err = syscall.EINVAL + } + } + return +} + +func _ShowWindow(hwnd syscall.Handle, cmdshow int32) (wasvisible bool) { + r0, _, _ := syscall.Syscall(procShowWindow.Addr(), 2, uintptr(hwnd), uintptr(cmdshow), 0) + wasvisible = r0 != 0 + return +} + +func _ScreenToClient(hwnd syscall.Handle, lpPoint *_POINT) (ok bool) { + r0, _, _ := syscall.Syscall(procScreenToClient.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(lpPoint)), 0) + ok = r0 != 0 + return +} + +func _ToUnicodeEx(wVirtKey uint32, wScanCode uint32, lpKeyState *byte, pwszBuff *uint16, cchBuff int32, wFlags uint32, dwhkl syscall.Handle) (ret int32) { + r0, _, _ := syscall.Syscall9(procToUnicodeEx.Addr(), 7, uintptr(wVirtKey), uintptr(wScanCode), uintptr(unsafe.Pointer(lpKeyState)), uintptr(unsafe.Pointer(pwszBuff)), uintptr(cchBuff), uintptr(wFlags), uintptr(dwhkl), 0, 0) + ret = int32(r0) + return +} + +func _TranslateMessage(msg *_MSG) (done bool) { + r0, _, _ := syscall.Syscall(procTranslateMessage.Addr(), 1, uintptr(unsafe.Pointer(msg)), 0, 0) + done = r0 != 0 + return +} + +func _UnregisterClass(lpClassName *uint16, hInstance syscall.Handle) (done bool) { + r0, _, _ := syscall.Syscall(procUnregisterClassW.Addr(), 2, uintptr(unsafe.Pointer(lpClassName)), uintptr(hInstance), 0) + done = r0 != 0 + return +} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/x11key/table.go b/vendor/golang.org/x/exp/shiny/driver/internal/x11key/table.go new file mode 100644 index 00000000..63e83443 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/x11key/table.go @@ -0,0 +1,1577 @@ +// generated by go generate; DO NOT EDIT. + +package x11key + +// keysymCodePoints maps xproto.Keysym values to their corresponding unicode code point. +var keysymCodePoints = map[rune]rune{ + 0x0020: 0x0020, // XK_space: SPACE + 0x0021: 0x0021, // XK_exclam: EXCLAMATION MARK + 0x0022: 0x0022, // XK_quotedbl: QUOTATION MARK + 0x0023: 0x0023, // XK_numbersign: NUMBER SIGN + 0x0024: 0x0024, // XK_dollar: DOLLAR SIGN + 0x0025: 0x0025, // XK_percent: PERCENT SIGN + 0x0026: 0x0026, // XK_ampersand: AMPERSAND + 0x0027: 0x0027, // XK_apostrophe: APOSTROPHE + 0x0028: 0x0028, // XK_parenleft: LEFT PARENTHESIS + 0x0029: 0x0029, // XK_parenright: RIGHT PARENTHESIS + 0x002a: 0x002A, // XK_asterisk: ASTERISK + 0x002b: 0x002B, // XK_plus: PLUS SIGN + 0x002c: 0x002C, // XK_comma: COMMA + 0x002d: 0x002D, // XK_minus: HYPHEN-MINUS + 0x002e: 0x002E, // XK_period: FULL STOP + 0x002f: 0x002F, // XK_slash: SOLIDUS + 0x0030: 0x0030, // XK_0: DIGIT ZERO + 0x0031: 0x0031, // XK_1: DIGIT ONE + 0x0032: 0x0032, // XK_2: DIGIT TWO + 0x0033: 0x0033, // XK_3: DIGIT THREE + 0x0034: 0x0034, // XK_4: DIGIT FOUR + 0x0035: 0x0035, // XK_5: DIGIT FIVE + 0x0036: 0x0036, // XK_6: DIGIT SIX + 0x0037: 0x0037, // XK_7: DIGIT SEVEN + 0x0038: 0x0038, // XK_8: DIGIT EIGHT + 0x0039: 0x0039, // XK_9: DIGIT NINE + 0x003a: 0x003A, // XK_colon: COLON + 0x003b: 0x003B, // XK_semicolon: SEMICOLON + 0x003c: 0x003C, // XK_less: LESS-THAN SIGN + 0x003d: 0x003D, // XK_equal: EQUALS SIGN + 0x003e: 0x003E, // XK_greater: GREATER-THAN SIGN + 0x003f: 0x003F, // XK_question: QUESTION MARK + 0x0040: 0x0040, // XK_at: COMMERCIAL AT + 0x0041: 0x0041, // XK_A: LATIN CAPITAL LETTER A + 0x0042: 0x0042, // XK_B: LATIN CAPITAL LETTER B + 0x0043: 0x0043, // XK_C: LATIN CAPITAL LETTER C + 0x0044: 0x0044, // XK_D: LATIN CAPITAL LETTER D + 0x0045: 0x0045, // XK_E: LATIN CAPITAL LETTER E + 0x0046: 0x0046, // XK_F: LATIN CAPITAL LETTER F + 0x0047: 0x0047, // XK_G: LATIN CAPITAL LETTER G + 0x0048: 0x0048, // XK_H: LATIN CAPITAL LETTER H + 0x0049: 0x0049, // XK_I: LATIN CAPITAL LETTER I + 0x004a: 0x004A, // XK_J: LATIN CAPITAL LETTER J + 0x004b: 0x004B, // XK_K: LATIN CAPITAL LETTER K + 0x004c: 0x004C, // XK_L: LATIN CAPITAL LETTER L + 0x004d: 0x004D, // XK_M: LATIN CAPITAL LETTER M + 0x004e: 0x004E, // XK_N: LATIN CAPITAL LETTER N + 0x004f: 0x004F, // XK_O: LATIN CAPITAL LETTER O + 0x0050: 0x0050, // XK_P: LATIN CAPITAL LETTER P + 0x0051: 0x0051, // XK_Q: LATIN CAPITAL LETTER Q + 0x0052: 0x0052, // XK_R: LATIN CAPITAL LETTER R + 0x0053: 0x0053, // XK_S: LATIN CAPITAL LETTER S + 0x0054: 0x0054, // XK_T: LATIN CAPITAL LETTER T + 0x0055: 0x0055, // XK_U: LATIN CAPITAL LETTER U + 0x0056: 0x0056, // XK_V: LATIN CAPITAL LETTER V + 0x0057: 0x0057, // XK_W: LATIN CAPITAL LETTER W + 0x0058: 0x0058, // XK_X: LATIN CAPITAL LETTER X + 0x0059: 0x0059, // XK_Y: LATIN CAPITAL LETTER Y + 0x005a: 0x005A, // XK_Z: LATIN CAPITAL LETTER Z + 0x005b: 0x005B, // XK_bracketleft: LEFT SQUARE BRACKET + 0x005c: 0x005C, // XK_backslash: REVERSE SOLIDUS + 0x005d: 0x005D, // XK_bracketright: RIGHT SQUARE BRACKET + 0x005e: 0x005E, // XK_asciicircum: CIRCUMFLEX ACCENT + 0x005f: 0x005F, // XK_underscore: LOW LINE + 0x0060: 0x0060, // XK_grave: GRAVE ACCENT + 0x0061: 0x0061, // XK_a: LATIN SMALL LETTER A + 0x0062: 0x0062, // XK_b: LATIN SMALL LETTER B + 0x0063: 0x0063, // XK_c: LATIN SMALL LETTER C + 0x0064: 0x0064, // XK_d: LATIN SMALL LETTER D + 0x0065: 0x0065, // XK_e: LATIN SMALL LETTER E + 0x0066: 0x0066, // XK_f: LATIN SMALL LETTER F + 0x0067: 0x0067, // XK_g: LATIN SMALL LETTER G + 0x0068: 0x0068, // XK_h: LATIN SMALL LETTER H + 0x0069: 0x0069, // XK_i: LATIN SMALL LETTER I + 0x006a: 0x006A, // XK_j: LATIN SMALL LETTER J + 0x006b: 0x006B, // XK_k: LATIN SMALL LETTER K + 0x006c: 0x006C, // XK_l: LATIN SMALL LETTER L + 0x006d: 0x006D, // XK_m: LATIN SMALL LETTER M + 0x006e: 0x006E, // XK_n: LATIN SMALL LETTER N + 0x006f: 0x006F, // XK_o: LATIN SMALL LETTER O + 0x0070: 0x0070, // XK_p: LATIN SMALL LETTER P + 0x0071: 0x0071, // XK_q: LATIN SMALL LETTER Q + 0x0072: 0x0072, // XK_r: LATIN SMALL LETTER R + 0x0073: 0x0073, // XK_s: LATIN SMALL LETTER S + 0x0074: 0x0074, // XK_t: LATIN SMALL LETTER T + 0x0075: 0x0075, // XK_u: LATIN SMALL LETTER U + 0x0076: 0x0076, // XK_v: LATIN SMALL LETTER V + 0x0077: 0x0077, // XK_w: LATIN SMALL LETTER W + 0x0078: 0x0078, // XK_x: LATIN SMALL LETTER X + 0x0079: 0x0079, // XK_y: LATIN SMALL LETTER Y + 0x007a: 0x007A, // XK_z: LATIN SMALL LETTER Z + 0x007b: 0x007B, // XK_braceleft: LEFT CURLY BRACKET + 0x007c: 0x007C, // XK_bar: VERTICAL LINE + 0x007d: 0x007D, // XK_braceright: RIGHT CURLY BRACKET + 0x007e: 0x007E, // XK_asciitilde: TILDE + 0x00a0: 0x00A0, // XK_nobreakspace: NO-BREAK SPACE + 0x00a1: 0x00A1, // XK_exclamdown: INVERTED EXCLAMATION MARK + 0x00a2: 0x00A2, // XK_cent: CENT SIGN + 0x00a3: 0x00A3, // XK_sterling: POUND SIGN + 0x00a4: 0x00A4, // XK_currency: CURRENCY SIGN + 0x00a5: 0x00A5, // XK_yen: YEN SIGN + 0x00a6: 0x00A6, // XK_brokenbar: BROKEN BAR + 0x00a7: 0x00A7, // XK_section: SECTION SIGN + 0x00a8: 0x00A8, // XK_diaeresis: DIAERESIS + 0x00a9: 0x00A9, // XK_copyright: COPYRIGHT SIGN + 0x00aa: 0x00AA, // XK_ordfeminine: FEMININE ORDINAL INDICATOR + 0x00ab: 0x00AB, // XK_guillemotleft: LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00ac: 0x00AC, // XK_notsign: NOT SIGN + 0x00ad: 0x00AD, // XK_hyphen: SOFT HYPHEN + 0x00ae: 0x00AE, // XK_registered: REGISTERED SIGN + 0x00af: 0x00AF, // XK_macron: MACRON + 0x00b0: 0x00B0, // XK_degree: DEGREE SIGN + 0x00b1: 0x00B1, // XK_plusminus: PLUS-MINUS SIGN + 0x00b2: 0x00B2, // XK_twosuperior: SUPERSCRIPT TWO + 0x00b3: 0x00B3, // XK_threesuperior: SUPERSCRIPT THREE + 0x00b4: 0x00B4, // XK_acute: ACUTE ACCENT + 0x00b5: 0x00B5, // XK_mu: MICRO SIGN + 0x00b6: 0x00B6, // XK_paragraph: PILCROW SIGN + 0x00b7: 0x00B7, // XK_periodcentered: MIDDLE DOT + 0x00b8: 0x00B8, // XK_cedilla: CEDILLA + 0x00b9: 0x00B9, // XK_onesuperior: SUPERSCRIPT ONE + 0x00ba: 0x00BA, // XK_masculine: MASCULINE ORDINAL INDICATOR + 0x00bb: 0x00BB, // XK_guillemotright: RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bc: 0x00BC, // XK_onequarter: VULGAR FRACTION ONE QUARTER + 0x00bd: 0x00BD, // XK_onehalf: VULGAR FRACTION ONE HALF + 0x00be: 0x00BE, // XK_threequarters: VULGAR FRACTION THREE QUARTERS + 0x00bf: 0x00BF, // XK_questiondown: INVERTED QUESTION MARK + 0x00c0: 0x00C0, // XK_Agrave: LATIN CAPITAL LETTER A WITH GRAVE + 0x00c1: 0x00C1, // XK_Aacute: LATIN CAPITAL LETTER A WITH ACUTE + 0x00c2: 0x00C2, // XK_Acircumflex: LATIN CAPITAL LETTER A WITH CIRCUMFLEX + 0x00c3: 0x00C3, // XK_Atilde: LATIN CAPITAL LETTER A WITH TILDE + 0x00c4: 0x00C4, // XK_Adiaeresis: LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5: 0x00C5, // XK_Aring: LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c6: 0x00C6, // XK_AE: LATIN CAPITAL LETTER AE + 0x00c7: 0x00C7, // XK_Ccedilla: LATIN CAPITAL LETTER C WITH CEDILLA + 0x00c8: 0x00C8, // XK_Egrave: LATIN CAPITAL LETTER E WITH GRAVE + 0x00c9: 0x00C9, // XK_Eacute: LATIN CAPITAL LETTER E WITH ACUTE + 0x00ca: 0x00CA, // XK_Ecircumflex: LATIN CAPITAL LETTER E WITH CIRCUMFLEX + 0x00cb: 0x00CB, // XK_Ediaeresis: LATIN CAPITAL LETTER E WITH DIAERESIS + 0x00cc: 0x00CC, // XK_Igrave: LATIN CAPITAL LETTER I WITH GRAVE + 0x00cd: 0x00CD, // XK_Iacute: LATIN CAPITAL LETTER I WITH ACUTE + 0x00ce: 0x00CE, // XK_Icircumflex: LATIN CAPITAL LETTER I WITH CIRCUMFLEX + 0x00cf: 0x00CF, // XK_Idiaeresis: LATIN CAPITAL LETTER I WITH DIAERESIS + 0x00d0: 0x00D0, // XK_ETH: LATIN CAPITAL LETTER ETH + 0x00d1: 0x00D1, // XK_Ntilde: LATIN CAPITAL LETTER N WITH TILDE + 0x00d2: 0x00D2, // XK_Ograve: LATIN CAPITAL LETTER O WITH GRAVE + 0x00d3: 0x00D3, // XK_Oacute: LATIN CAPITAL LETTER O WITH ACUTE + 0x00d4: 0x00D4, // XK_Ocircumflex: LATIN CAPITAL LETTER O WITH CIRCUMFLEX + 0x00d5: 0x00D5, // XK_Otilde: LATIN CAPITAL LETTER O WITH TILDE + 0x00d6: 0x00D6, // XK_Odiaeresis: LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00d7: 0x00D7, // XK_multiply: MULTIPLICATION SIGN + 0x00d8: 0x00D8, // XK_Oslash: LATIN CAPITAL LETTER O WITH STROKE + 0x00d9: 0x00D9, // XK_Ugrave: LATIN CAPITAL LETTER U WITH GRAVE + 0x00da: 0x00DA, // XK_Uacute: LATIN CAPITAL LETTER U WITH ACUTE + 0x00db: 0x00DB, // XK_Ucircumflex: LATIN CAPITAL LETTER U WITH CIRCUMFLEX + 0x00dc: 0x00DC, // XK_Udiaeresis: LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00dd: 0x00DD, // XK_Yacute: LATIN CAPITAL LETTER Y WITH ACUTE + 0x00de: 0x00DE, // XK_THORN: LATIN CAPITAL LETTER THORN + 0x00df: 0x00DF, // XK_ssharp: LATIN SMALL LETTER SHARP S + 0x00e0: 0x00E0, // XK_agrave: LATIN SMALL LETTER A WITH GRAVE + 0x00e1: 0x00E1, // XK_aacute: LATIN SMALL LETTER A WITH ACUTE + 0x00e2: 0x00E2, // XK_acircumflex: LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e3: 0x00E3, // XK_atilde: LATIN SMALL LETTER A WITH TILDE + 0x00e4: 0x00E4, // XK_adiaeresis: LATIN SMALL LETTER A WITH DIAERESIS + 0x00e5: 0x00E5, // XK_aring: LATIN SMALL LETTER A WITH RING ABOVE + 0x00e6: 0x00E6, // XK_ae: LATIN SMALL LETTER AE + 0x00e7: 0x00E7, // XK_ccedilla: LATIN SMALL LETTER C WITH CEDILLA + 0x00e8: 0x00E8, // XK_egrave: LATIN SMALL LETTER E WITH GRAVE + 0x00e9: 0x00E9, // XK_eacute: LATIN SMALL LETTER E WITH ACUTE + 0x00ea: 0x00EA, // XK_ecircumflex: LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb: 0x00EB, // XK_ediaeresis: LATIN SMALL LETTER E WITH DIAERESIS + 0x00ec: 0x00EC, // XK_igrave: LATIN SMALL LETTER I WITH GRAVE + 0x00ed: 0x00ED, // XK_iacute: LATIN SMALL LETTER I WITH ACUTE + 0x00ee: 0x00EE, // XK_icircumflex: LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ef: 0x00EF, // XK_idiaeresis: LATIN SMALL LETTER I WITH DIAERESIS + 0x00f0: 0x00F0, // XK_eth: LATIN SMALL LETTER ETH + 0x00f1: 0x00F1, // XK_ntilde: LATIN SMALL LETTER N WITH TILDE + 0x00f2: 0x00F2, // XK_ograve: LATIN SMALL LETTER O WITH GRAVE + 0x00f3: 0x00F3, // XK_oacute: LATIN SMALL LETTER O WITH ACUTE + 0x00f4: 0x00F4, // XK_ocircumflex: LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f5: 0x00F5, // XK_otilde: LATIN SMALL LETTER O WITH TILDE + 0x00f6: 0x00F6, // XK_odiaeresis: LATIN SMALL LETTER O WITH DIAERESIS + 0x00f7: 0x00F7, // XK_division: DIVISION SIGN + 0x00f8: 0x00F8, // XK_oslash: LATIN SMALL LETTER O WITH STROKE + 0x00f9: 0x00F9, // XK_ugrave: LATIN SMALL LETTER U WITH GRAVE + 0x00fa: 0x00FA, // XK_uacute: LATIN SMALL LETTER U WITH ACUTE + 0x00fb: 0x00FB, // XK_ucircumflex: LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00fc: 0x00FC, // XK_udiaeresis: LATIN SMALL LETTER U WITH DIAERESIS + 0x00fd: 0x00FD, // XK_yacute: LATIN SMALL LETTER Y WITH ACUTE + 0x00fe: 0x00FE, // XK_thorn: LATIN SMALL LETTER THORN + 0x00ff: 0x00FF, // XK_ydiaeresis: LATIN SMALL LETTER Y WITH DIAERESIS + 0x01a1: 0x0104, // XK_Aogonek: LATIN CAPITAL LETTER A WITH OGONEK + 0x01a2: 0x02D8, // XK_breve: BREVE + 0x01a3: 0x0141, // XK_Lstroke: LATIN CAPITAL LETTER L WITH STROKE + 0x01a5: 0x013D, // XK_Lcaron: LATIN CAPITAL LETTER L WITH CARON + 0x01a6: 0x015A, // XK_Sacute: LATIN CAPITAL LETTER S WITH ACUTE + 0x01a9: 0x0160, // XK_Scaron: LATIN CAPITAL LETTER S WITH CARON + 0x01aa: 0x015E, // XK_Scedilla: LATIN CAPITAL LETTER S WITH CEDILLA + 0x01ab: 0x0164, // XK_Tcaron: LATIN CAPITAL LETTER T WITH CARON + 0x01ac: 0x0179, // XK_Zacute: LATIN CAPITAL LETTER Z WITH ACUTE + 0x01ae: 0x017D, // XK_Zcaron: LATIN CAPITAL LETTER Z WITH CARON + 0x01af: 0x017B, // XK_Zabovedot: LATIN CAPITAL LETTER Z WITH DOT ABOVE + 0x01b1: 0x0105, // XK_aogonek: LATIN SMALL LETTER A WITH OGONEK + 0x01b2: 0x02DB, // XK_ogonek: OGONEK + 0x01b3: 0x0142, // XK_lstroke: LATIN SMALL LETTER L WITH STROKE + 0x01b5: 0x013E, // XK_lcaron: LATIN SMALL LETTER L WITH CARON + 0x01b6: 0x015B, // XK_sacute: LATIN SMALL LETTER S WITH ACUTE + 0x01b7: 0x02C7, // XK_caron: CARON + 0x01b9: 0x0161, // XK_scaron: LATIN SMALL LETTER S WITH CARON + 0x01ba: 0x015F, // XK_scedilla: LATIN SMALL LETTER S WITH CEDILLA + 0x01bb: 0x0165, // XK_tcaron: LATIN SMALL LETTER T WITH CARON + 0x01bc: 0x017A, // XK_zacute: LATIN SMALL LETTER Z WITH ACUTE + 0x01bd: 0x02DD, // XK_doubleacute: DOUBLE ACUTE ACCENT + 0x01be: 0x017E, // XK_zcaron: LATIN SMALL LETTER Z WITH CARON + 0x01bf: 0x017C, // XK_zabovedot: LATIN SMALL LETTER Z WITH DOT ABOVE + 0x01c0: 0x0154, // XK_Racute: LATIN CAPITAL LETTER R WITH ACUTE + 0x01c3: 0x0102, // XK_Abreve: LATIN CAPITAL LETTER A WITH BREVE + 0x01c5: 0x0139, // XK_Lacute: LATIN CAPITAL LETTER L WITH ACUTE + 0x01c6: 0x0106, // XK_Cacute: LATIN CAPITAL LETTER C WITH ACUTE + 0x01c8: 0x010C, // XK_Ccaron: LATIN CAPITAL LETTER C WITH CARON + 0x01ca: 0x0118, // XK_Eogonek: LATIN CAPITAL LETTER E WITH OGONEK + 0x01cc: 0x011A, // XK_Ecaron: LATIN CAPITAL LETTER E WITH CARON + 0x01cf: 0x010E, // XK_Dcaron: LATIN CAPITAL LETTER D WITH CARON + 0x01d0: 0x0110, // XK_Dstroke: LATIN CAPITAL LETTER D WITH STROKE + 0x01d1: 0x0143, // XK_Nacute: LATIN CAPITAL LETTER N WITH ACUTE + 0x01d2: 0x0147, // XK_Ncaron: LATIN CAPITAL LETTER N WITH CARON + 0x01d5: 0x0150, // XK_Odoubleacute: LATIN CAPITAL LETTER O WITH DOUBLE ACUTE + 0x01d8: 0x0158, // XK_Rcaron: LATIN CAPITAL LETTER R WITH CARON + 0x01d9: 0x016E, // XK_Uring: LATIN CAPITAL LETTER U WITH RING ABOVE + 0x01db: 0x0170, // XK_Udoubleacute: LATIN CAPITAL LETTER U WITH DOUBLE ACUTE + 0x01de: 0x0162, // XK_Tcedilla: LATIN CAPITAL LETTER T WITH CEDILLA + 0x01e0: 0x0155, // XK_racute: LATIN SMALL LETTER R WITH ACUTE + 0x01e3: 0x0103, // XK_abreve: LATIN SMALL LETTER A WITH BREVE + 0x01e5: 0x013A, // XK_lacute: LATIN SMALL LETTER L WITH ACUTE + 0x01e6: 0x0107, // XK_cacute: LATIN SMALL LETTER C WITH ACUTE + 0x01e8: 0x010D, // XK_ccaron: LATIN SMALL LETTER C WITH CARON + 0x01ea: 0x0119, // XK_eogonek: LATIN SMALL LETTER E WITH OGONEK + 0x01ec: 0x011B, // XK_ecaron: LATIN SMALL LETTER E WITH CARON + 0x01ef: 0x010F, // XK_dcaron: LATIN SMALL LETTER D WITH CARON + 0x01f0: 0x0111, // XK_dstroke: LATIN SMALL LETTER D WITH STROKE + 0x01f1: 0x0144, // XK_nacute: LATIN SMALL LETTER N WITH ACUTE + 0x01f2: 0x0148, // XK_ncaron: LATIN SMALL LETTER N WITH CARON + 0x01f5: 0x0151, // XK_odoubleacute: LATIN SMALL LETTER O WITH DOUBLE ACUTE + 0x01f8: 0x0159, // XK_rcaron: LATIN SMALL LETTER R WITH CARON + 0x01f9: 0x016F, // XK_uring: LATIN SMALL LETTER U WITH RING ABOVE + 0x01fb: 0x0171, // XK_udoubleacute: LATIN SMALL LETTER U WITH DOUBLE ACUTE + 0x01fe: 0x0163, // XK_tcedilla: LATIN SMALL LETTER T WITH CEDILLA + 0x01ff: 0x02D9, // XK_abovedot: DOT ABOVE + 0x02a1: 0x0126, // XK_Hstroke: LATIN CAPITAL LETTER H WITH STROKE + 0x02a6: 0x0124, // XK_Hcircumflex: LATIN CAPITAL LETTER H WITH CIRCUMFLEX + 0x02a9: 0x0130, // XK_Iabovedot: LATIN CAPITAL LETTER I WITH DOT ABOVE + 0x02ab: 0x011E, // XK_Gbreve: LATIN CAPITAL LETTER G WITH BREVE + 0x02ac: 0x0134, // XK_Jcircumflex: LATIN CAPITAL LETTER J WITH CIRCUMFLEX + 0x02b1: 0x0127, // XK_hstroke: LATIN SMALL LETTER H WITH STROKE + 0x02b6: 0x0125, // XK_hcircumflex: LATIN SMALL LETTER H WITH CIRCUMFLEX + 0x02b9: 0x0131, // XK_idotless: LATIN SMALL LETTER DOTLESS I + 0x02bb: 0x011F, // XK_gbreve: LATIN SMALL LETTER G WITH BREVE + 0x02bc: 0x0135, // XK_jcircumflex: LATIN SMALL LETTER J WITH CIRCUMFLEX + 0x02c5: 0x010A, // XK_Cabovedot: LATIN CAPITAL LETTER C WITH DOT ABOVE + 0x02c6: 0x0108, // XK_Ccircumflex: LATIN CAPITAL LETTER C WITH CIRCUMFLEX + 0x02d5: 0x0120, // XK_Gabovedot: LATIN CAPITAL LETTER G WITH DOT ABOVE + 0x02d8: 0x011C, // XK_Gcircumflex: LATIN CAPITAL LETTER G WITH CIRCUMFLEX + 0x02dd: 0x016C, // XK_Ubreve: LATIN CAPITAL LETTER U WITH BREVE + 0x02de: 0x015C, // XK_Scircumflex: LATIN CAPITAL LETTER S WITH CIRCUMFLEX + 0x02e5: 0x010B, // XK_cabovedot: LATIN SMALL LETTER C WITH DOT ABOVE + 0x02e6: 0x0109, // XK_ccircumflex: LATIN SMALL LETTER C WITH CIRCUMFLEX + 0x02f5: 0x0121, // XK_gabovedot: LATIN SMALL LETTER G WITH DOT ABOVE + 0x02f8: 0x011D, // XK_gcircumflex: LATIN SMALL LETTER G WITH CIRCUMFLEX + 0x02fd: 0x016D, // XK_ubreve: LATIN SMALL LETTER U WITH BREVE + 0x02fe: 0x015D, // XK_scircumflex: LATIN SMALL LETTER S WITH CIRCUMFLEX + 0x03a2: 0x0138, // XK_kra: LATIN SMALL LETTER KRA + 0x03a3: 0x0156, // XK_Rcedilla: LATIN CAPITAL LETTER R WITH CEDILLA + 0x03a5: 0x0128, // XK_Itilde: LATIN CAPITAL LETTER I WITH TILDE + 0x03a6: 0x013B, // XK_Lcedilla: LATIN CAPITAL LETTER L WITH CEDILLA + 0x03aa: 0x0112, // XK_Emacron: LATIN CAPITAL LETTER E WITH MACRON + 0x03ab: 0x0122, // XK_Gcedilla: LATIN CAPITAL LETTER G WITH CEDILLA + 0x03ac: 0x0166, // XK_Tslash: LATIN CAPITAL LETTER T WITH STROKE + 0x03b3: 0x0157, // XK_rcedilla: LATIN SMALL LETTER R WITH CEDILLA + 0x03b5: 0x0129, // XK_itilde: LATIN SMALL LETTER I WITH TILDE + 0x03b6: 0x013C, // XK_lcedilla: LATIN SMALL LETTER L WITH CEDILLA + 0x03ba: 0x0113, // XK_emacron: LATIN SMALL LETTER E WITH MACRON + 0x03bb: 0x0123, // XK_gcedilla: LATIN SMALL LETTER G WITH CEDILLA + 0x03bc: 0x0167, // XK_tslash: LATIN SMALL LETTER T WITH STROKE + 0x03bd: 0x014A, // XK_ENG: LATIN CAPITAL LETTER ENG + 0x03bf: 0x014B, // XK_eng: LATIN SMALL LETTER ENG + 0x03c0: 0x0100, // XK_Amacron: LATIN CAPITAL LETTER A WITH MACRON + 0x03c7: 0x012E, // XK_Iogonek: LATIN CAPITAL LETTER I WITH OGONEK + 0x03cc: 0x0116, // XK_Eabovedot: LATIN CAPITAL LETTER E WITH DOT ABOVE + 0x03cf: 0x012A, // XK_Imacron: LATIN CAPITAL LETTER I WITH MACRON + 0x03d1: 0x0145, // XK_Ncedilla: LATIN CAPITAL LETTER N WITH CEDILLA + 0x03d2: 0x014C, // XK_Omacron: LATIN CAPITAL LETTER O WITH MACRON + 0x03d3: 0x0136, // XK_Kcedilla: LATIN CAPITAL LETTER K WITH CEDILLA + 0x03d9: 0x0172, // XK_Uogonek: LATIN CAPITAL LETTER U WITH OGONEK + 0x03dd: 0x0168, // XK_Utilde: LATIN CAPITAL LETTER U WITH TILDE + 0x03de: 0x016A, // XK_Umacron: LATIN CAPITAL LETTER U WITH MACRON + 0x03e0: 0x0101, // XK_amacron: LATIN SMALL LETTER A WITH MACRON + 0x03e7: 0x012F, // XK_iogonek: LATIN SMALL LETTER I WITH OGONEK + 0x03ec: 0x0117, // XK_eabovedot: LATIN SMALL LETTER E WITH DOT ABOVE + 0x03ef: 0x012B, // XK_imacron: LATIN SMALL LETTER I WITH MACRON + 0x03f1: 0x0146, // XK_ncedilla: LATIN SMALL LETTER N WITH CEDILLA + 0x03f2: 0x014D, // XK_omacron: LATIN SMALL LETTER O WITH MACRON + 0x03f3: 0x0137, // XK_kcedilla: LATIN SMALL LETTER K WITH CEDILLA + 0x03f9: 0x0173, // XK_uogonek: LATIN SMALL LETTER U WITH OGONEK + 0x03fd: 0x0169, // XK_utilde: LATIN SMALL LETTER U WITH TILDE + 0x03fe: 0x016B, // XK_umacron: LATIN SMALL LETTER U WITH MACRON + 0x1000174: 0x0174, // XK_Wcircumflex: LATIN CAPITAL LETTER W WITH CIRCUMFLEX + 0x1000175: 0x0175, // XK_wcircumflex: LATIN SMALL LETTER W WITH CIRCUMFLEX + 0x1000176: 0x0176, // XK_Ycircumflex: LATIN CAPITAL LETTER Y WITH CIRCUMFLEX + 0x1000177: 0x0177, // XK_ycircumflex: LATIN SMALL LETTER Y WITH CIRCUMFLEX + 0x1001e02: 0x1E02, // XK_Babovedot: LATIN CAPITAL LETTER B WITH DOT ABOVE + 0x1001e03: 0x1E03, // XK_babovedot: LATIN SMALL LETTER B WITH DOT ABOVE + 0x1001e0a: 0x1E0A, // XK_Dabovedot: LATIN CAPITAL LETTER D WITH DOT ABOVE + 0x1001e0b: 0x1E0B, // XK_dabovedot: LATIN SMALL LETTER D WITH DOT ABOVE + 0x1001e1e: 0x1E1E, // XK_Fabovedot: LATIN CAPITAL LETTER F WITH DOT ABOVE + 0x1001e1f: 0x1E1F, // XK_fabovedot: LATIN SMALL LETTER F WITH DOT ABOVE + 0x1001e40: 0x1E40, // XK_Mabovedot: LATIN CAPITAL LETTER M WITH DOT ABOVE + 0x1001e41: 0x1E41, // XK_mabovedot: LATIN SMALL LETTER M WITH DOT ABOVE + 0x1001e56: 0x1E56, // XK_Pabovedot: LATIN CAPITAL LETTER P WITH DOT ABOVE + 0x1001e57: 0x1E57, // XK_pabovedot: LATIN SMALL LETTER P WITH DOT ABOVE + 0x1001e60: 0x1E60, // XK_Sabovedot: LATIN CAPITAL LETTER S WITH DOT ABOVE + 0x1001e61: 0x1E61, // XK_sabovedot: LATIN SMALL LETTER S WITH DOT ABOVE + 0x1001e6a: 0x1E6A, // XK_Tabovedot: LATIN CAPITAL LETTER T WITH DOT ABOVE + 0x1001e6b: 0x1E6B, // XK_tabovedot: LATIN SMALL LETTER T WITH DOT ABOVE + 0x1001e80: 0x1E80, // XK_Wgrave: LATIN CAPITAL LETTER W WITH GRAVE + 0x1001e81: 0x1E81, // XK_wgrave: LATIN SMALL LETTER W WITH GRAVE + 0x1001e82: 0x1E82, // XK_Wacute: LATIN CAPITAL LETTER W WITH ACUTE + 0x1001e83: 0x1E83, // XK_wacute: LATIN SMALL LETTER W WITH ACUTE + 0x1001e84: 0x1E84, // XK_Wdiaeresis: LATIN CAPITAL LETTER W WITH DIAERESIS + 0x1001e85: 0x1E85, // XK_wdiaeresis: LATIN SMALL LETTER W WITH DIAERESIS + 0x1001ef2: 0x1EF2, // XK_Ygrave: LATIN CAPITAL LETTER Y WITH GRAVE + 0x1001ef3: 0x1EF3, // XK_ygrave: LATIN SMALL LETTER Y WITH GRAVE + 0x13bc: 0x0152, // XK_OE: LATIN CAPITAL LIGATURE OE + 0x13bd: 0x0153, // XK_oe: LATIN SMALL LIGATURE OE + 0x13be: 0x0178, // XK_Ydiaeresis: LATIN CAPITAL LETTER Y WITH DIAERESIS + 0x047e: 0x203E, // XK_overline: OVERLINE + 0x04a1: 0x3002, // XK_kana_fullstop: IDEOGRAPHIC FULL STOP + 0x04a2: 0x300C, // XK_kana_openingbracket: LEFT CORNER BRACKET + 0x04a3: 0x300D, // XK_kana_closingbracket: RIGHT CORNER BRACKET + 0x04a4: 0x3001, // XK_kana_comma: IDEOGRAPHIC COMMA + 0x04a5: 0x30FB, // XK_kana_conjunctive: KATAKANA MIDDLE DOT + 0x04a6: 0x30F2, // XK_kana_WO: KATAKANA LETTER WO + 0x04a7: 0x30A1, // XK_kana_a: KATAKANA LETTER SMALL A + 0x04a8: 0x30A3, // XK_kana_i: KATAKANA LETTER SMALL I + 0x04a9: 0x30A5, // XK_kana_u: KATAKANA LETTER SMALL U + 0x04aa: 0x30A7, // XK_kana_e: KATAKANA LETTER SMALL E + 0x04ab: 0x30A9, // XK_kana_o: KATAKANA LETTER SMALL O + 0x04ac: 0x30E3, // XK_kana_ya: KATAKANA LETTER SMALL YA + 0x04ad: 0x30E5, // XK_kana_yu: KATAKANA LETTER SMALL YU + 0x04ae: 0x30E7, // XK_kana_yo: KATAKANA LETTER SMALL YO + 0x04af: 0x30C3, // XK_kana_tsu: KATAKANA LETTER SMALL TU + 0x04b0: 0x30FC, // XK_prolongedsound: KATAKANA-HIRAGANA PROLONGED SOUND MARK + 0x04b1: 0x30A2, // XK_kana_A: KATAKANA LETTER A + 0x04b2: 0x30A4, // XK_kana_I: KATAKANA LETTER I + 0x04b3: 0x30A6, // XK_kana_U: KATAKANA LETTER U + 0x04b4: 0x30A8, // XK_kana_E: KATAKANA LETTER E + 0x04b5: 0x30AA, // XK_kana_O: KATAKANA LETTER O + 0x04b6: 0x30AB, // XK_kana_KA: KATAKANA LETTER KA + 0x04b7: 0x30AD, // XK_kana_KI: KATAKANA LETTER KI + 0x04b8: 0x30AF, // XK_kana_KU: KATAKANA LETTER KU + 0x04b9: 0x30B1, // XK_kana_KE: KATAKANA LETTER KE + 0x04ba: 0x30B3, // XK_kana_KO: KATAKANA LETTER KO + 0x04bb: 0x30B5, // XK_kana_SA: KATAKANA LETTER SA + 0x04bc: 0x30B7, // XK_kana_SHI: KATAKANA LETTER SI + 0x04bd: 0x30B9, // XK_kana_SU: KATAKANA LETTER SU + 0x04be: 0x30BB, // XK_kana_SE: KATAKANA LETTER SE + 0x04bf: 0x30BD, // XK_kana_SO: KATAKANA LETTER SO + 0x04c0: 0x30BF, // XK_kana_TA: KATAKANA LETTER TA + 0x04c1: 0x30C1, // XK_kana_CHI: KATAKANA LETTER TI + 0x04c2: 0x30C4, // XK_kana_TSU: KATAKANA LETTER TU + 0x04c3: 0x30C6, // XK_kana_TE: KATAKANA LETTER TE + 0x04c4: 0x30C8, // XK_kana_TO: KATAKANA LETTER TO + 0x04c5: 0x30CA, // XK_kana_NA: KATAKANA LETTER NA + 0x04c6: 0x30CB, // XK_kana_NI: KATAKANA LETTER NI + 0x04c7: 0x30CC, // XK_kana_NU: KATAKANA LETTER NU + 0x04c8: 0x30CD, // XK_kana_NE: KATAKANA LETTER NE + 0x04c9: 0x30CE, // XK_kana_NO: KATAKANA LETTER NO + 0x04ca: 0x30CF, // XK_kana_HA: KATAKANA LETTER HA + 0x04cb: 0x30D2, // XK_kana_HI: KATAKANA LETTER HI + 0x04cc: 0x30D5, // XK_kana_FU: KATAKANA LETTER HU + 0x04cd: 0x30D8, // XK_kana_HE: KATAKANA LETTER HE + 0x04ce: 0x30DB, // XK_kana_HO: KATAKANA LETTER HO + 0x04cf: 0x30DE, // XK_kana_MA: KATAKANA LETTER MA + 0x04d0: 0x30DF, // XK_kana_MI: KATAKANA LETTER MI + 0x04d1: 0x30E0, // XK_kana_MU: KATAKANA LETTER MU + 0x04d2: 0x30E1, // XK_kana_ME: KATAKANA LETTER ME + 0x04d3: 0x30E2, // XK_kana_MO: KATAKANA LETTER MO + 0x04d4: 0x30E4, // XK_kana_YA: KATAKANA LETTER YA + 0x04d5: 0x30E6, // XK_kana_YU: KATAKANA LETTER YU + 0x04d6: 0x30E8, // XK_kana_YO: KATAKANA LETTER YO + 0x04d7: 0x30E9, // XK_kana_RA: KATAKANA LETTER RA + 0x04d8: 0x30EA, // XK_kana_RI: KATAKANA LETTER RI + 0x04d9: 0x30EB, // XK_kana_RU: KATAKANA LETTER RU + 0x04da: 0x30EC, // XK_kana_RE: KATAKANA LETTER RE + 0x04db: 0x30ED, // XK_kana_RO: KATAKANA LETTER RO + 0x04dc: 0x30EF, // XK_kana_WA: KATAKANA LETTER WA + 0x04dd: 0x30F3, // XK_kana_N: KATAKANA LETTER N + 0x04de: 0x309B, // XK_voicedsound: KATAKANA-HIRAGANA VOICED SOUND MARK + 0x04df: 0x309C, // XK_semivoicedsound: KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK + 0x10006f0: 0x06F0, // XK_Farsi_0: EXTENDED ARABIC-INDIC DIGIT ZERO + 0x10006f1: 0x06F1, // XK_Farsi_1: EXTENDED ARABIC-INDIC DIGIT ONE + 0x10006f2: 0x06F2, // XK_Farsi_2: EXTENDED ARABIC-INDIC DIGIT TWO + 0x10006f3: 0x06F3, // XK_Farsi_3: EXTENDED ARABIC-INDIC DIGIT THREE + 0x10006f4: 0x06F4, // XK_Farsi_4: EXTENDED ARABIC-INDIC DIGIT FOUR + 0x10006f5: 0x06F5, // XK_Farsi_5: EXTENDED ARABIC-INDIC DIGIT FIVE + 0x10006f6: 0x06F6, // XK_Farsi_6: EXTENDED ARABIC-INDIC DIGIT SIX + 0x10006f7: 0x06F7, // XK_Farsi_7: EXTENDED ARABIC-INDIC DIGIT SEVEN + 0x10006f8: 0x06F8, // XK_Farsi_8: EXTENDED ARABIC-INDIC DIGIT EIGHT + 0x10006f9: 0x06F9, // XK_Farsi_9: EXTENDED ARABIC-INDIC DIGIT NINE + 0x100066a: 0x066A, // XK_Arabic_percent: ARABIC PERCENT SIGN + 0x1000670: 0x0670, // XK_Arabic_superscript_alef: ARABIC LETTER SUPERSCRIPT ALEF + 0x1000679: 0x0679, // XK_Arabic_tteh: ARABIC LETTER TTEH + 0x100067e: 0x067E, // XK_Arabic_peh: ARABIC LETTER PEH + 0x1000686: 0x0686, // XK_Arabic_tcheh: ARABIC LETTER TCHEH + 0x1000688: 0x0688, // XK_Arabic_ddal: ARABIC LETTER DDAL + 0x1000691: 0x0691, // XK_Arabic_rreh: ARABIC LETTER RREH + 0x05ac: 0x060C, // XK_Arabic_comma: ARABIC COMMA + 0x10006d4: 0x06D4, // XK_Arabic_fullstop: ARABIC FULL STOP + 0x1000660: 0x0660, // XK_Arabic_0: ARABIC-INDIC DIGIT ZERO + 0x1000661: 0x0661, // XK_Arabic_1: ARABIC-INDIC DIGIT ONE + 0x1000662: 0x0662, // XK_Arabic_2: ARABIC-INDIC DIGIT TWO + 0x1000663: 0x0663, // XK_Arabic_3: ARABIC-INDIC DIGIT THREE + 0x1000664: 0x0664, // XK_Arabic_4: ARABIC-INDIC DIGIT FOUR + 0x1000665: 0x0665, // XK_Arabic_5: ARABIC-INDIC DIGIT FIVE + 0x1000666: 0x0666, // XK_Arabic_6: ARABIC-INDIC DIGIT SIX + 0x1000667: 0x0667, // XK_Arabic_7: ARABIC-INDIC DIGIT SEVEN + 0x1000668: 0x0668, // XK_Arabic_8: ARABIC-INDIC DIGIT EIGHT + 0x1000669: 0x0669, // XK_Arabic_9: ARABIC-INDIC DIGIT NINE + 0x05bb: 0x061B, // XK_Arabic_semicolon: ARABIC SEMICOLON + 0x05bf: 0x061F, // XK_Arabic_question_mark: ARABIC QUESTION MARK + 0x05c1: 0x0621, // XK_Arabic_hamza: ARABIC LETTER HAMZA + 0x05c2: 0x0622, // XK_Arabic_maddaonalef: ARABIC LETTER ALEF WITH MADDA ABOVE + 0x05c3: 0x0623, // XK_Arabic_hamzaonalef: ARABIC LETTER ALEF WITH HAMZA ABOVE + 0x05c4: 0x0624, // XK_Arabic_hamzaonwaw: ARABIC LETTER WAW WITH HAMZA ABOVE + 0x05c5: 0x0625, // XK_Arabic_hamzaunderalef: ARABIC LETTER ALEF WITH HAMZA BELOW + 0x05c6: 0x0626, // XK_Arabic_hamzaonyeh: ARABIC LETTER YEH WITH HAMZA ABOVE + 0x05c7: 0x0627, // XK_Arabic_alef: ARABIC LETTER ALEF + 0x05c8: 0x0628, // XK_Arabic_beh: ARABIC LETTER BEH + 0x05c9: 0x0629, // XK_Arabic_tehmarbuta: ARABIC LETTER TEH MARBUTA + 0x05ca: 0x062A, // XK_Arabic_teh: ARABIC LETTER TEH + 0x05cb: 0x062B, // XK_Arabic_theh: ARABIC LETTER THEH + 0x05cc: 0x062C, // XK_Arabic_jeem: ARABIC LETTER JEEM + 0x05cd: 0x062D, // XK_Arabic_hah: ARABIC LETTER HAH + 0x05ce: 0x062E, // XK_Arabic_khah: ARABIC LETTER KHAH + 0x05cf: 0x062F, // XK_Arabic_dal: ARABIC LETTER DAL + 0x05d0: 0x0630, // XK_Arabic_thal: ARABIC LETTER THAL + 0x05d1: 0x0631, // XK_Arabic_ra: ARABIC LETTER REH + 0x05d2: 0x0632, // XK_Arabic_zain: ARABIC LETTER ZAIN + 0x05d3: 0x0633, // XK_Arabic_seen: ARABIC LETTER SEEN + 0x05d4: 0x0634, // XK_Arabic_sheen: ARABIC LETTER SHEEN + 0x05d5: 0x0635, // XK_Arabic_sad: ARABIC LETTER SAD + 0x05d6: 0x0636, // XK_Arabic_dad: ARABIC LETTER DAD + 0x05d7: 0x0637, // XK_Arabic_tah: ARABIC LETTER TAH + 0x05d8: 0x0638, // XK_Arabic_zah: ARABIC LETTER ZAH + 0x05d9: 0x0639, // XK_Arabic_ain: ARABIC LETTER AIN + 0x05da: 0x063A, // XK_Arabic_ghain: ARABIC LETTER GHAIN + 0x05e0: 0x0640, // XK_Arabic_tatweel: ARABIC TATWEEL + 0x05e1: 0x0641, // XK_Arabic_feh: ARABIC LETTER FEH + 0x05e2: 0x0642, // XK_Arabic_qaf: ARABIC LETTER QAF + 0x05e3: 0x0643, // XK_Arabic_kaf: ARABIC LETTER KAF + 0x05e4: 0x0644, // XK_Arabic_lam: ARABIC LETTER LAM + 0x05e5: 0x0645, // XK_Arabic_meem: ARABIC LETTER MEEM + 0x05e6: 0x0646, // XK_Arabic_noon: ARABIC LETTER NOON + 0x05e7: 0x0647, // XK_Arabic_ha: ARABIC LETTER HEH + 0x05e8: 0x0648, // XK_Arabic_waw: ARABIC LETTER WAW + 0x05e9: 0x0649, // XK_Arabic_alefmaksura: ARABIC LETTER ALEF MAKSURA + 0x05ea: 0x064A, // XK_Arabic_yeh: ARABIC LETTER YEH + 0x05eb: 0x064B, // XK_Arabic_fathatan: ARABIC FATHATAN + 0x05ec: 0x064C, // XK_Arabic_dammatan: ARABIC DAMMATAN + 0x05ed: 0x064D, // XK_Arabic_kasratan: ARABIC KASRATAN + 0x05ee: 0x064E, // XK_Arabic_fatha: ARABIC FATHA + 0x05ef: 0x064F, // XK_Arabic_damma: ARABIC DAMMA + 0x05f0: 0x0650, // XK_Arabic_kasra: ARABIC KASRA + 0x05f1: 0x0651, // XK_Arabic_shadda: ARABIC SHADDA + 0x05f2: 0x0652, // XK_Arabic_sukun: ARABIC SUKUN + 0x1000653: 0x0653, // XK_Arabic_madda_above: ARABIC MADDAH ABOVE + 0x1000654: 0x0654, // XK_Arabic_hamza_above: ARABIC HAMZA ABOVE + 0x1000655: 0x0655, // XK_Arabic_hamza_below: ARABIC HAMZA BELOW + 0x1000698: 0x0698, // XK_Arabic_jeh: ARABIC LETTER JEH + 0x10006a4: 0x06A4, // XK_Arabic_veh: ARABIC LETTER VEH + 0x10006a9: 0x06A9, // XK_Arabic_keheh: ARABIC LETTER KEHEH + 0x10006af: 0x06AF, // XK_Arabic_gaf: ARABIC LETTER GAF + 0x10006ba: 0x06BA, // XK_Arabic_noon_ghunna: ARABIC LETTER NOON GHUNNA + 0x10006be: 0x06BE, // XK_Arabic_heh_doachashmee: ARABIC LETTER HEH DOACHASHMEE + 0x10006cc: 0x06CC, // XK_Farsi_yeh: ARABIC LETTER FARSI YEH + 0x10006d2: 0x06D2, // XK_Arabic_yeh_baree: ARABIC LETTER YEH BARREE + 0x10006c1: 0x06C1, // XK_Arabic_heh_goal: ARABIC LETTER HEH GOAL + 0x1000492: 0x0492, // XK_Cyrillic_GHE_bar: CYRILLIC CAPITAL LETTER GHE WITH STROKE + 0x1000493: 0x0493, // XK_Cyrillic_ghe_bar: CYRILLIC SMALL LETTER GHE WITH STROKE + 0x1000496: 0x0496, // XK_Cyrillic_ZHE_descender: CYRILLIC CAPITAL LETTER ZHE WITH DESCENDER + 0x1000497: 0x0497, // XK_Cyrillic_zhe_descender: CYRILLIC SMALL LETTER ZHE WITH DESCENDER + 0x100049a: 0x049A, // XK_Cyrillic_KA_descender: CYRILLIC CAPITAL LETTER KA WITH DESCENDER + 0x100049b: 0x049B, // XK_Cyrillic_ka_descender: CYRILLIC SMALL LETTER KA WITH DESCENDER + 0x100049c: 0x049C, // XK_Cyrillic_KA_vertstroke: CYRILLIC CAPITAL LETTER KA WITH VERTICAL STROKE + 0x100049d: 0x049D, // XK_Cyrillic_ka_vertstroke: CYRILLIC SMALL LETTER KA WITH VERTICAL STROKE + 0x10004a2: 0x04A2, // XK_Cyrillic_EN_descender: CYRILLIC CAPITAL LETTER EN WITH DESCENDER + 0x10004a3: 0x04A3, // XK_Cyrillic_en_descender: CYRILLIC SMALL LETTER EN WITH DESCENDER + 0x10004ae: 0x04AE, // XK_Cyrillic_U_straight: CYRILLIC CAPITAL LETTER STRAIGHT U + 0x10004af: 0x04AF, // XK_Cyrillic_u_straight: CYRILLIC SMALL LETTER STRAIGHT U + 0x10004b0: 0x04B0, // XK_Cyrillic_U_straight_bar: CYRILLIC CAPITAL LETTER STRAIGHT U WITH STROKE + 0x10004b1: 0x04B1, // XK_Cyrillic_u_straight_bar: CYRILLIC SMALL LETTER STRAIGHT U WITH STROKE + 0x10004b2: 0x04B2, // XK_Cyrillic_HA_descender: CYRILLIC CAPITAL LETTER HA WITH DESCENDER + 0x10004b3: 0x04B3, // XK_Cyrillic_ha_descender: CYRILLIC SMALL LETTER HA WITH DESCENDER + 0x10004b6: 0x04B6, // XK_Cyrillic_CHE_descender: CYRILLIC CAPITAL LETTER CHE WITH DESCENDER + 0x10004b7: 0x04B7, // XK_Cyrillic_che_descender: CYRILLIC SMALL LETTER CHE WITH DESCENDER + 0x10004b8: 0x04B8, // XK_Cyrillic_CHE_vertstroke: CYRILLIC CAPITAL LETTER CHE WITH VERTICAL STROKE + 0x10004b9: 0x04B9, // XK_Cyrillic_che_vertstroke: CYRILLIC SMALL LETTER CHE WITH VERTICAL STROKE + 0x10004ba: 0x04BA, // XK_Cyrillic_SHHA: CYRILLIC CAPITAL LETTER SHHA + 0x10004bb: 0x04BB, // XK_Cyrillic_shha: CYRILLIC SMALL LETTER SHHA + 0x10004d8: 0x04D8, // XK_Cyrillic_SCHWA: CYRILLIC CAPITAL LETTER SCHWA + 0x10004d9: 0x04D9, // XK_Cyrillic_schwa: CYRILLIC SMALL LETTER SCHWA + 0x10004e2: 0x04E2, // XK_Cyrillic_I_macron: CYRILLIC CAPITAL LETTER I WITH MACRON + 0x10004e3: 0x04E3, // XK_Cyrillic_i_macron: CYRILLIC SMALL LETTER I WITH MACRON + 0x10004e8: 0x04E8, // XK_Cyrillic_O_bar: CYRILLIC CAPITAL LETTER BARRED O + 0x10004e9: 0x04E9, // XK_Cyrillic_o_bar: CYRILLIC SMALL LETTER BARRED O + 0x10004ee: 0x04EE, // XK_Cyrillic_U_macron: CYRILLIC CAPITAL LETTER U WITH MACRON + 0x10004ef: 0x04EF, // XK_Cyrillic_u_macron: CYRILLIC SMALL LETTER U WITH MACRON + 0x06a1: 0x0452, // XK_Serbian_dje: CYRILLIC SMALL LETTER DJE + 0x06a2: 0x0453, // XK_Macedonia_gje: CYRILLIC SMALL LETTER GJE + 0x06a3: 0x0451, // XK_Cyrillic_io: CYRILLIC SMALL LETTER IO + 0x06a4: 0x0454, // XK_Ukrainian_ie: CYRILLIC SMALL LETTER UKRAINIAN IE + 0x06a5: 0x0455, // XK_Macedonia_dse: CYRILLIC SMALL LETTER DZE + 0x06a6: 0x0456, // XK_Ukrainian_i: CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I + 0x06a7: 0x0457, // XK_Ukrainian_yi: CYRILLIC SMALL LETTER YI + 0x06a8: 0x0458, // XK_Cyrillic_je: CYRILLIC SMALL LETTER JE + 0x06a9: 0x0459, // XK_Cyrillic_lje: CYRILLIC SMALL LETTER LJE + 0x06aa: 0x045A, // XK_Cyrillic_nje: CYRILLIC SMALL LETTER NJE + 0x06ab: 0x045B, // XK_Serbian_tshe: CYRILLIC SMALL LETTER TSHE + 0x06ac: 0x045C, // XK_Macedonia_kje: CYRILLIC SMALL LETTER KJE + 0x06ad: 0x0491, // XK_Ukrainian_ghe_with_upturn: CYRILLIC SMALL LETTER GHE WITH UPTURN + 0x06ae: 0x045E, // XK_Byelorussian_shortu: CYRILLIC SMALL LETTER SHORT U + 0x06af: 0x045F, // XK_Cyrillic_dzhe: CYRILLIC SMALL LETTER DZHE + 0x06b0: 0x2116, // XK_numerosign: NUMERO SIGN + 0x06b1: 0x0402, // XK_Serbian_DJE: CYRILLIC CAPITAL LETTER DJE + 0x06b2: 0x0403, // XK_Macedonia_GJE: CYRILLIC CAPITAL LETTER GJE + 0x06b3: 0x0401, // XK_Cyrillic_IO: CYRILLIC CAPITAL LETTER IO + 0x06b4: 0x0404, // XK_Ukrainian_IE: CYRILLIC CAPITAL LETTER UKRAINIAN IE + 0x06b5: 0x0405, // XK_Macedonia_DSE: CYRILLIC CAPITAL LETTER DZE + 0x06b6: 0x0406, // XK_Ukrainian_I: CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I + 0x06b7: 0x0407, // XK_Ukrainian_YI: CYRILLIC CAPITAL LETTER YI + 0x06b8: 0x0408, // XK_Cyrillic_JE: CYRILLIC CAPITAL LETTER JE + 0x06b9: 0x0409, // XK_Cyrillic_LJE: CYRILLIC CAPITAL LETTER LJE + 0x06ba: 0x040A, // XK_Cyrillic_NJE: CYRILLIC CAPITAL LETTER NJE + 0x06bb: 0x040B, // XK_Serbian_TSHE: CYRILLIC CAPITAL LETTER TSHE + 0x06bc: 0x040C, // XK_Macedonia_KJE: CYRILLIC CAPITAL LETTER KJE + 0x06bd: 0x0490, // XK_Ukrainian_GHE_WITH_UPTURN: CYRILLIC CAPITAL LETTER GHE WITH UPTURN + 0x06be: 0x040E, // XK_Byelorussian_SHORTU: CYRILLIC CAPITAL LETTER SHORT U + 0x06bf: 0x040F, // XK_Cyrillic_DZHE: CYRILLIC CAPITAL LETTER DZHE + 0x06c0: 0x044E, // XK_Cyrillic_yu: CYRILLIC SMALL LETTER YU + 0x06c1: 0x0430, // XK_Cyrillic_a: CYRILLIC SMALL LETTER A + 0x06c2: 0x0431, // XK_Cyrillic_be: CYRILLIC SMALL LETTER BE + 0x06c3: 0x0446, // XK_Cyrillic_tse: CYRILLIC SMALL LETTER TSE + 0x06c4: 0x0434, // XK_Cyrillic_de: CYRILLIC SMALL LETTER DE + 0x06c5: 0x0435, // XK_Cyrillic_ie: CYRILLIC SMALL LETTER IE + 0x06c6: 0x0444, // XK_Cyrillic_ef: CYRILLIC SMALL LETTER EF + 0x06c7: 0x0433, // XK_Cyrillic_ghe: CYRILLIC SMALL LETTER GHE + 0x06c8: 0x0445, // XK_Cyrillic_ha: CYRILLIC SMALL LETTER HA + 0x06c9: 0x0438, // XK_Cyrillic_i: CYRILLIC SMALL LETTER I + 0x06ca: 0x0439, // XK_Cyrillic_shorti: CYRILLIC SMALL LETTER SHORT I + 0x06cb: 0x043A, // XK_Cyrillic_ka: CYRILLIC SMALL LETTER KA + 0x06cc: 0x043B, // XK_Cyrillic_el: CYRILLIC SMALL LETTER EL + 0x06cd: 0x043C, // XK_Cyrillic_em: CYRILLIC SMALL LETTER EM + 0x06ce: 0x043D, // XK_Cyrillic_en: CYRILLIC SMALL LETTER EN + 0x06cf: 0x043E, // XK_Cyrillic_o: CYRILLIC SMALL LETTER O + 0x06d0: 0x043F, // XK_Cyrillic_pe: CYRILLIC SMALL LETTER PE + 0x06d1: 0x044F, // XK_Cyrillic_ya: CYRILLIC SMALL LETTER YA + 0x06d2: 0x0440, // XK_Cyrillic_er: CYRILLIC SMALL LETTER ER + 0x06d3: 0x0441, // XK_Cyrillic_es: CYRILLIC SMALL LETTER ES + 0x06d4: 0x0442, // XK_Cyrillic_te: CYRILLIC SMALL LETTER TE + 0x06d5: 0x0443, // XK_Cyrillic_u: CYRILLIC SMALL LETTER U + 0x06d6: 0x0436, // XK_Cyrillic_zhe: CYRILLIC SMALL LETTER ZHE + 0x06d7: 0x0432, // XK_Cyrillic_ve: CYRILLIC SMALL LETTER VE + 0x06d8: 0x044C, // XK_Cyrillic_softsign: CYRILLIC SMALL LETTER SOFT SIGN + 0x06d9: 0x044B, // XK_Cyrillic_yeru: CYRILLIC SMALL LETTER YERU + 0x06da: 0x0437, // XK_Cyrillic_ze: CYRILLIC SMALL LETTER ZE + 0x06db: 0x0448, // XK_Cyrillic_sha: CYRILLIC SMALL LETTER SHA + 0x06dc: 0x044D, // XK_Cyrillic_e: CYRILLIC SMALL LETTER E + 0x06dd: 0x0449, // XK_Cyrillic_shcha: CYRILLIC SMALL LETTER SHCHA + 0x06de: 0x0447, // XK_Cyrillic_che: CYRILLIC SMALL LETTER CHE + 0x06df: 0x044A, // XK_Cyrillic_hardsign: CYRILLIC SMALL LETTER HARD SIGN + 0x06e0: 0x042E, // XK_Cyrillic_YU: CYRILLIC CAPITAL LETTER YU + 0x06e1: 0x0410, // XK_Cyrillic_A: CYRILLIC CAPITAL LETTER A + 0x06e2: 0x0411, // XK_Cyrillic_BE: CYRILLIC CAPITAL LETTER BE + 0x06e3: 0x0426, // XK_Cyrillic_TSE: CYRILLIC CAPITAL LETTER TSE + 0x06e4: 0x0414, // XK_Cyrillic_DE: CYRILLIC CAPITAL LETTER DE + 0x06e5: 0x0415, // XK_Cyrillic_IE: CYRILLIC CAPITAL LETTER IE + 0x06e6: 0x0424, // XK_Cyrillic_EF: CYRILLIC CAPITAL LETTER EF + 0x06e7: 0x0413, // XK_Cyrillic_GHE: CYRILLIC CAPITAL LETTER GHE + 0x06e8: 0x0425, // XK_Cyrillic_HA: CYRILLIC CAPITAL LETTER HA + 0x06e9: 0x0418, // XK_Cyrillic_I: CYRILLIC CAPITAL LETTER I + 0x06ea: 0x0419, // XK_Cyrillic_SHORTI: CYRILLIC CAPITAL LETTER SHORT I + 0x06eb: 0x041A, // XK_Cyrillic_KA: CYRILLIC CAPITAL LETTER KA + 0x06ec: 0x041B, // XK_Cyrillic_EL: CYRILLIC CAPITAL LETTER EL + 0x06ed: 0x041C, // XK_Cyrillic_EM: CYRILLIC CAPITAL LETTER EM + 0x06ee: 0x041D, // XK_Cyrillic_EN: CYRILLIC CAPITAL LETTER EN + 0x06ef: 0x041E, // XK_Cyrillic_O: CYRILLIC CAPITAL LETTER O + 0x06f0: 0x041F, // XK_Cyrillic_PE: CYRILLIC CAPITAL LETTER PE + 0x06f1: 0x042F, // XK_Cyrillic_YA: CYRILLIC CAPITAL LETTER YA + 0x06f2: 0x0420, // XK_Cyrillic_ER: CYRILLIC CAPITAL LETTER ER + 0x06f3: 0x0421, // XK_Cyrillic_ES: CYRILLIC CAPITAL LETTER ES + 0x06f4: 0x0422, // XK_Cyrillic_TE: CYRILLIC CAPITAL LETTER TE + 0x06f5: 0x0423, // XK_Cyrillic_U: CYRILLIC CAPITAL LETTER U + 0x06f6: 0x0416, // XK_Cyrillic_ZHE: CYRILLIC CAPITAL LETTER ZHE + 0x06f7: 0x0412, // XK_Cyrillic_VE: CYRILLIC CAPITAL LETTER VE + 0x06f8: 0x042C, // XK_Cyrillic_SOFTSIGN: CYRILLIC CAPITAL LETTER SOFT SIGN + 0x06f9: 0x042B, // XK_Cyrillic_YERU: CYRILLIC CAPITAL LETTER YERU + 0x06fa: 0x0417, // XK_Cyrillic_ZE: CYRILLIC CAPITAL LETTER ZE + 0x06fb: 0x0428, // XK_Cyrillic_SHA: CYRILLIC CAPITAL LETTER SHA + 0x06fc: 0x042D, // XK_Cyrillic_E: CYRILLIC CAPITAL LETTER E + 0x06fd: 0x0429, // XK_Cyrillic_SHCHA: CYRILLIC CAPITAL LETTER SHCHA + 0x06fe: 0x0427, // XK_Cyrillic_CHE: CYRILLIC CAPITAL LETTER CHE + 0x06ff: 0x042A, // XK_Cyrillic_HARDSIGN: CYRILLIC CAPITAL LETTER HARD SIGN + 0x07a1: 0x0386, // XK_Greek_ALPHAaccent: GREEK CAPITAL LETTER ALPHA WITH TONOS + 0x07a2: 0x0388, // XK_Greek_EPSILONaccent: GREEK CAPITAL LETTER EPSILON WITH TONOS + 0x07a3: 0x0389, // XK_Greek_ETAaccent: GREEK CAPITAL LETTER ETA WITH TONOS + 0x07a4: 0x038A, // XK_Greek_IOTAaccent: GREEK CAPITAL LETTER IOTA WITH TONOS + 0x07a5: 0x03AA, // XK_Greek_IOTAdieresis: GREEK CAPITAL LETTER IOTA WITH DIALYTIKA + 0x07a7: 0x038C, // XK_Greek_OMICRONaccent: GREEK CAPITAL LETTER OMICRON WITH TONOS + 0x07a8: 0x038E, // XK_Greek_UPSILONaccent: GREEK CAPITAL LETTER UPSILON WITH TONOS + 0x07a9: 0x03AB, // XK_Greek_UPSILONdieresis: GREEK CAPITAL LETTER UPSILON WITH DIALYTIKA + 0x07ab: 0x038F, // XK_Greek_OMEGAaccent: GREEK CAPITAL LETTER OMEGA WITH TONOS + 0x07ae: 0x0385, // XK_Greek_accentdieresis: GREEK DIALYTIKA TONOS + 0x07af: 0x2015, // XK_Greek_horizbar: HORIZONTAL BAR + 0x07b1: 0x03AC, // XK_Greek_alphaaccent: GREEK SMALL LETTER ALPHA WITH TONOS + 0x07b2: 0x03AD, // XK_Greek_epsilonaccent: GREEK SMALL LETTER EPSILON WITH TONOS + 0x07b3: 0x03AE, // XK_Greek_etaaccent: GREEK SMALL LETTER ETA WITH TONOS + 0x07b4: 0x03AF, // XK_Greek_iotaaccent: GREEK SMALL LETTER IOTA WITH TONOS + 0x07b5: 0x03CA, // XK_Greek_iotadieresis: GREEK SMALL LETTER IOTA WITH DIALYTIKA + 0x07b6: 0x0390, // XK_Greek_iotaaccentdieresis: GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS + 0x07b7: 0x03CC, // XK_Greek_omicronaccent: GREEK SMALL LETTER OMICRON WITH TONOS + 0x07b8: 0x03CD, // XK_Greek_upsilonaccent: GREEK SMALL LETTER UPSILON WITH TONOS + 0x07b9: 0x03CB, // XK_Greek_upsilondieresis: GREEK SMALL LETTER UPSILON WITH DIALYTIKA + 0x07ba: 0x03B0, // XK_Greek_upsilonaccentdieresis: GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS + 0x07bb: 0x03CE, // XK_Greek_omegaaccent: GREEK SMALL LETTER OMEGA WITH TONOS + 0x07c1: 0x0391, // XK_Greek_ALPHA: GREEK CAPITAL LETTER ALPHA + 0x07c2: 0x0392, // XK_Greek_BETA: GREEK CAPITAL LETTER BETA + 0x07c3: 0x0393, // XK_Greek_GAMMA: GREEK CAPITAL LETTER GAMMA + 0x07c4: 0x0394, // XK_Greek_DELTA: GREEK CAPITAL LETTER DELTA + 0x07c5: 0x0395, // XK_Greek_EPSILON: GREEK CAPITAL LETTER EPSILON + 0x07c6: 0x0396, // XK_Greek_ZETA: GREEK CAPITAL LETTER ZETA + 0x07c7: 0x0397, // XK_Greek_ETA: GREEK CAPITAL LETTER ETA + 0x07c8: 0x0398, // XK_Greek_THETA: GREEK CAPITAL LETTER THETA + 0x07c9: 0x0399, // XK_Greek_IOTA: GREEK CAPITAL LETTER IOTA + 0x07ca: 0x039A, // XK_Greek_KAPPA: GREEK CAPITAL LETTER KAPPA + 0x07cb: 0x039B, // XK_Greek_LAMDA: GREEK CAPITAL LETTER LAMDA + 0x07cc: 0x039C, // XK_Greek_MU: GREEK CAPITAL LETTER MU + 0x07cd: 0x039D, // XK_Greek_NU: GREEK CAPITAL LETTER NU + 0x07ce: 0x039E, // XK_Greek_XI: GREEK CAPITAL LETTER XI + 0x07cf: 0x039F, // XK_Greek_OMICRON: GREEK CAPITAL LETTER OMICRON + 0x07d0: 0x03A0, // XK_Greek_PI: GREEK CAPITAL LETTER PI + 0x07d1: 0x03A1, // XK_Greek_RHO: GREEK CAPITAL LETTER RHO + 0x07d2: 0x03A3, // XK_Greek_SIGMA: GREEK CAPITAL LETTER SIGMA + 0x07d4: 0x03A4, // XK_Greek_TAU: GREEK CAPITAL LETTER TAU + 0x07d5: 0x03A5, // XK_Greek_UPSILON: GREEK CAPITAL LETTER UPSILON + 0x07d6: 0x03A6, // XK_Greek_PHI: GREEK CAPITAL LETTER PHI + 0x07d7: 0x03A7, // XK_Greek_CHI: GREEK CAPITAL LETTER CHI + 0x07d8: 0x03A8, // XK_Greek_PSI: GREEK CAPITAL LETTER PSI + 0x07d9: 0x03A9, // XK_Greek_OMEGA: GREEK CAPITAL LETTER OMEGA + 0x07e1: 0x03B1, // XK_Greek_alpha: GREEK SMALL LETTER ALPHA + 0x07e2: 0x03B2, // XK_Greek_beta: GREEK SMALL LETTER BETA + 0x07e3: 0x03B3, // XK_Greek_gamma: GREEK SMALL LETTER GAMMA + 0x07e4: 0x03B4, // XK_Greek_delta: GREEK SMALL LETTER DELTA + 0x07e5: 0x03B5, // XK_Greek_epsilon: GREEK SMALL LETTER EPSILON + 0x07e6: 0x03B6, // XK_Greek_zeta: GREEK SMALL LETTER ZETA + 0x07e7: 0x03B7, // XK_Greek_eta: GREEK SMALL LETTER ETA + 0x07e8: 0x03B8, // XK_Greek_theta: GREEK SMALL LETTER THETA + 0x07e9: 0x03B9, // XK_Greek_iota: GREEK SMALL LETTER IOTA + 0x07ea: 0x03BA, // XK_Greek_kappa: GREEK SMALL LETTER KAPPA + 0x07eb: 0x03BB, // XK_Greek_lamda: GREEK SMALL LETTER LAMDA + 0x07ec: 0x03BC, // XK_Greek_mu: GREEK SMALL LETTER MU + 0x07ed: 0x03BD, // XK_Greek_nu: GREEK SMALL LETTER NU + 0x07ee: 0x03BE, // XK_Greek_xi: GREEK SMALL LETTER XI + 0x07ef: 0x03BF, // XK_Greek_omicron: GREEK SMALL LETTER OMICRON + 0x07f0: 0x03C0, // XK_Greek_pi: GREEK SMALL LETTER PI + 0x07f1: 0x03C1, // XK_Greek_rho: GREEK SMALL LETTER RHO + 0x07f2: 0x03C3, // XK_Greek_sigma: GREEK SMALL LETTER SIGMA + 0x07f3: 0x03C2, // XK_Greek_finalsmallsigma: GREEK SMALL LETTER FINAL SIGMA + 0x07f4: 0x03C4, // XK_Greek_tau: GREEK SMALL LETTER TAU + 0x07f5: 0x03C5, // XK_Greek_upsilon: GREEK SMALL LETTER UPSILON + 0x07f6: 0x03C6, // XK_Greek_phi: GREEK SMALL LETTER PHI + 0x07f7: 0x03C7, // XK_Greek_chi: GREEK SMALL LETTER CHI + 0x07f8: 0x03C8, // XK_Greek_psi: GREEK SMALL LETTER PSI + 0x07f9: 0x03C9, // XK_Greek_omega: GREEK SMALL LETTER OMEGA + 0x08a1: 0x23B7, // XK_leftradical: RADICAL SYMBOL BOTTOM + 0x08a2: 0x250C, // XK_topleftradical: BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x08a3: 0x2500, // XK_horizconnector: BOX DRAWINGS LIGHT HORIZONTAL + 0x08a4: 0x2320, // XK_topintegral: TOP HALF INTEGRAL + 0x08a5: 0x2321, // XK_botintegral: BOTTOM HALF INTEGRAL + 0x08a6: 0x2502, // XK_vertconnector: BOX DRAWINGS LIGHT VERTICAL + 0x08a7: 0x23A1, // XK_topleftsqbracket: LEFT SQUARE BRACKET UPPER CORNER + 0x08a8: 0x23A3, // XK_botleftsqbracket: LEFT SQUARE BRACKET LOWER CORNER + 0x08a9: 0x23A4, // XK_toprightsqbracket: RIGHT SQUARE BRACKET UPPER CORNER + 0x08aa: 0x23A6, // XK_botrightsqbracket: RIGHT SQUARE BRACKET LOWER CORNER + 0x08ab: 0x239B, // XK_topleftparens: LEFT PARENTHESIS UPPER HOOK + 0x08ac: 0x239D, // XK_botleftparens: LEFT PARENTHESIS LOWER HOOK + 0x08ad: 0x239E, // XK_toprightparens: RIGHT PARENTHESIS UPPER HOOK + 0x08ae: 0x23A0, // XK_botrightparens: RIGHT PARENTHESIS LOWER HOOK + 0x08af: 0x23A8, // XK_leftmiddlecurlybrace: LEFT CURLY BRACKET MIDDLE PIECE + 0x08b0: 0x23AC, // XK_rightmiddlecurlybrace: RIGHT CURLY BRACKET MIDDLE PIECE + 0x08bc: 0x2264, // XK_lessthanequal: LESS-THAN OR EQUAL TO + 0x08bd: 0x2260, // XK_notequal: NOT EQUAL TO + 0x08be: 0x2265, // XK_greaterthanequal: GREATER-THAN OR EQUAL TO + 0x08bf: 0x222B, // XK_integral: INTEGRAL + 0x08c0: 0x2234, // XK_therefore: THEREFORE + 0x08c1: 0x221D, // XK_variation: PROPORTIONAL TO + 0x08c2: 0x221E, // XK_infinity: INFINITY + 0x08c5: 0x2207, // XK_nabla: NABLA + 0x08c8: 0x223C, // XK_approximate: TILDE OPERATOR + 0x08c9: 0x2243, // XK_similarequal: ASYMPTOTICALLY EQUAL TO + 0x08cd: 0x21D4, // XK_ifonlyif: LEFT RIGHT DOUBLE ARROW + 0x08ce: 0x21D2, // XK_implies: RIGHTWARDS DOUBLE ARROW + 0x08cf: 0x2261, // XK_identical: IDENTICAL TO + 0x08d6: 0x221A, // XK_radical: SQUARE ROOT + 0x08da: 0x2282, // XK_includedin: SUBSET OF + 0x08db: 0x2283, // XK_includes: SUPERSET OF + 0x08dc: 0x2229, // XK_intersection: INTERSECTION + 0x08dd: 0x222A, // XK_union: UNION + 0x08de: 0x2227, // XK_logicaland: LOGICAL AND + 0x08df: 0x2228, // XK_logicalor: LOGICAL OR + 0x08ef: 0x2202, // XK_partialderivative: PARTIAL DIFFERENTIAL + 0x08f6: 0x0192, // XK_function: LATIN SMALL LETTER F WITH HOOK + 0x08fb: 0x2190, // XK_leftarrow: LEFTWARDS ARROW + 0x08fc: 0x2191, // XK_uparrow: UPWARDS ARROW + 0x08fd: 0x2192, // XK_rightarrow: RIGHTWARDS ARROW + 0x08fe: 0x2193, // XK_downarrow: DOWNWARDS ARROW + 0x09e0: 0x25C6, // XK_soliddiamond: BLACK DIAMOND + 0x09e1: 0x2592, // XK_checkerboard: MEDIUM SHADE + 0x09e2: 0x2409, // XK_ht: SYMBOL FOR HORIZONTAL TABULATION + 0x09e3: 0x240C, // XK_ff: SYMBOL FOR FORM FEED + 0x09e4: 0x240D, // XK_cr: SYMBOL FOR CARRIAGE RETURN + 0x09e5: 0x240A, // XK_lf: SYMBOL FOR LINE FEED + 0x09e8: 0x2424, // XK_nl: SYMBOL FOR NEWLINE + 0x09e9: 0x240B, // XK_vt: SYMBOL FOR VERTICAL TABULATION + 0x09ea: 0x2518, // XK_lowrightcorner: BOX DRAWINGS LIGHT UP AND LEFT + 0x09eb: 0x2510, // XK_uprightcorner: BOX DRAWINGS LIGHT DOWN AND LEFT + 0x09ec: 0x250C, // XK_upleftcorner: BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x09ed: 0x2514, // XK_lowleftcorner: BOX DRAWINGS LIGHT UP AND RIGHT + 0x09ee: 0x253C, // XK_crossinglines: BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x09ef: 0x23BA, // XK_horizlinescan1: HORIZONTAL SCAN LINE-1 + 0x09f0: 0x23BB, // XK_horizlinescan3: HORIZONTAL SCAN LINE-3 + 0x09f1: 0x2500, // XK_horizlinescan5: BOX DRAWINGS LIGHT HORIZONTAL + 0x09f2: 0x23BC, // XK_horizlinescan7: HORIZONTAL SCAN LINE-7 + 0x09f3: 0x23BD, // XK_horizlinescan9: HORIZONTAL SCAN LINE-9 + 0x09f4: 0x251C, // XK_leftt: BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x09f5: 0x2524, // XK_rightt: BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x09f6: 0x2534, // XK_bott: BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x09f7: 0x252C, // XK_topt: BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x09f8: 0x2502, // XK_vertbar: BOX DRAWINGS LIGHT VERTICAL + 0x0aa1: 0x2003, // XK_emspace: EM SPACE + 0x0aa2: 0x2002, // XK_enspace: EN SPACE + 0x0aa3: 0x2004, // XK_em3space: THREE-PER-EM SPACE + 0x0aa4: 0x2005, // XK_em4space: FOUR-PER-EM SPACE + 0x0aa5: 0x2007, // XK_digitspace: FIGURE SPACE + 0x0aa6: 0x2008, // XK_punctspace: PUNCTUATION SPACE + 0x0aa7: 0x2009, // XK_thinspace: THIN SPACE + 0x0aa8: 0x200A, // XK_hairspace: HAIR SPACE + 0x0aa9: 0x2014, // XK_emdash: EM DASH + 0x0aaa: 0x2013, // XK_endash: EN DASH + 0x0aac: 0x2423, // XK_signifblank: OPEN BOX + 0x0aae: 0x2026, // XK_ellipsis: HORIZONTAL ELLIPSIS + 0x0aaf: 0x2025, // XK_doubbaselinedot: TWO DOT LEADER + 0x0ab0: 0x2153, // XK_onethird: VULGAR FRACTION ONE THIRD + 0x0ab1: 0x2154, // XK_twothirds: VULGAR FRACTION TWO THIRDS + 0x0ab2: 0x2155, // XK_onefifth: VULGAR FRACTION ONE FIFTH + 0x0ab3: 0x2156, // XK_twofifths: VULGAR FRACTION TWO FIFTHS + 0x0ab4: 0x2157, // XK_threefifths: VULGAR FRACTION THREE FIFTHS + 0x0ab5: 0x2158, // XK_fourfifths: VULGAR FRACTION FOUR FIFTHS + 0x0ab6: 0x2159, // XK_onesixth: VULGAR FRACTION ONE SIXTH + 0x0ab7: 0x215A, // XK_fivesixths: VULGAR FRACTION FIVE SIXTHS + 0x0ab8: 0x2105, // XK_careof: CARE OF + 0x0abb: 0x2012, // XK_figdash: FIGURE DASH + 0x0abc: 0x27E8, // XK_leftanglebracket: MATHEMATICAL LEFT ANGLE BRACKET + 0x0abd: 0x002E, // XK_decimalpoint: FULL STOP + 0x0abe: 0x27E9, // XK_rightanglebracket: MATHEMATICAL RIGHT ANGLE BRACKET + 0x0ac3: 0x215B, // XK_oneeighth: VULGAR FRACTION ONE EIGHTH + 0x0ac4: 0x215C, // XK_threeeighths: VULGAR FRACTION THREE EIGHTHS + 0x0ac5: 0x215D, // XK_fiveeighths: VULGAR FRACTION FIVE EIGHTHS + 0x0ac6: 0x215E, // XK_seveneighths: VULGAR FRACTION SEVEN EIGHTHS + 0x0ac9: 0x2122, // XK_trademark: TRADE MARK SIGN + 0x0aca: 0x2613, // XK_signaturemark: SALTIRE + 0x0acc: 0x25C1, // XK_leftopentriangle: WHITE LEFT-POINTING TRIANGLE + 0x0acd: 0x25B7, // XK_rightopentriangle: WHITE RIGHT-POINTING TRIANGLE + 0x0ace: 0x25CB, // XK_emopencircle: WHITE CIRCLE + 0x0acf: 0x25AF, // XK_emopenrectangle: WHITE VERTICAL RECTANGLE + 0x0ad0: 0x2018, // XK_leftsinglequotemark: LEFT SINGLE QUOTATION MARK + 0x0ad1: 0x2019, // XK_rightsinglequotemark: RIGHT SINGLE QUOTATION MARK + 0x0ad2: 0x201C, // XK_leftdoublequotemark: LEFT DOUBLE QUOTATION MARK + 0x0ad3: 0x201D, // XK_rightdoublequotemark: RIGHT DOUBLE QUOTATION MARK + 0x0ad4: 0x211E, // XK_prescription: PRESCRIPTION TAKE + 0x0ad5: 0x2030, // XK_permille: PER MILLE SIGN + 0x0ad6: 0x2032, // XK_minutes: PRIME + 0x0ad7: 0x2033, // XK_seconds: DOUBLE PRIME + 0x0ad9: 0x271D, // XK_latincross: LATIN CROSS + 0x0adb: 0x25AC, // XK_filledrectbullet: BLACK RECTANGLE + 0x0adc: 0x25C0, // XK_filledlefttribullet: BLACK LEFT-POINTING TRIANGLE + 0x0add: 0x25B6, // XK_filledrighttribullet: BLACK RIGHT-POINTING TRIANGLE + 0x0ade: 0x25CF, // XK_emfilledcircle: BLACK CIRCLE + 0x0adf: 0x25AE, // XK_emfilledrect: BLACK VERTICAL RECTANGLE + 0x0ae0: 0x25E6, // XK_enopencircbullet: WHITE BULLET + 0x0ae1: 0x25AB, // XK_enopensquarebullet: WHITE SMALL SQUARE + 0x0ae2: 0x25AD, // XK_openrectbullet: WHITE RECTANGLE + 0x0ae3: 0x25B3, // XK_opentribulletup: WHITE UP-POINTING TRIANGLE + 0x0ae4: 0x25BD, // XK_opentribulletdown: WHITE DOWN-POINTING TRIANGLE + 0x0ae5: 0x2606, // XK_openstar: WHITE STAR + 0x0ae6: 0x2022, // XK_enfilledcircbullet: BULLET + 0x0ae7: 0x25AA, // XK_enfilledsqbullet: BLACK SMALL SQUARE + 0x0ae8: 0x25B2, // XK_filledtribulletup: BLACK UP-POINTING TRIANGLE + 0x0ae9: 0x25BC, // XK_filledtribulletdown: BLACK DOWN-POINTING TRIANGLE + 0x0aea: 0x261C, // XK_leftpointer: WHITE LEFT POINTING INDEX + 0x0aeb: 0x261E, // XK_rightpointer: WHITE RIGHT POINTING INDEX + 0x0aec: 0x2663, // XK_club: BLACK CLUB SUIT + 0x0aed: 0x2666, // XK_diamond: BLACK DIAMOND SUIT + 0x0aee: 0x2665, // XK_heart: BLACK HEART SUIT + 0x0af0: 0x2720, // XK_maltesecross: MALTESE CROSS + 0x0af1: 0x2020, // XK_dagger: DAGGER + 0x0af2: 0x2021, // XK_doubledagger: DOUBLE DAGGER + 0x0af3: 0x2713, // XK_checkmark: CHECK MARK + 0x0af4: 0x2717, // XK_ballotcross: BALLOT X + 0x0af5: 0x266F, // XK_musicalsharp: MUSIC SHARP SIGN + 0x0af6: 0x266D, // XK_musicalflat: MUSIC FLAT SIGN + 0x0af7: 0x2642, // XK_malesymbol: MALE SIGN + 0x0af8: 0x2640, // XK_femalesymbol: FEMALE SIGN + 0x0af9: 0x260E, // XK_telephone: BLACK TELEPHONE + 0x0afa: 0x2315, // XK_telephonerecorder: TELEPHONE RECORDER + 0x0afb: 0x2117, // XK_phonographcopyright: SOUND RECORDING COPYRIGHT + 0x0afc: 0x2038, // XK_caret: CARET + 0x0afd: 0x201A, // XK_singlelowquotemark: SINGLE LOW-9 QUOTATION MARK + 0x0afe: 0x201E, // XK_doublelowquotemark: DOUBLE LOW-9 QUOTATION MARK + 0x0ba3: 0x003C, // XK_leftcaret: LESS-THAN SIGN + 0x0ba6: 0x003E, // XK_rightcaret: GREATER-THAN SIGN + 0x0ba8: 0x2228, // XK_downcaret: LOGICAL OR + 0x0ba9: 0x2227, // XK_upcaret: LOGICAL AND + 0x0bc0: 0x00AF, // XK_overbar: MACRON + 0x0bc2: 0x22A4, // XK_downtack: DOWN TACK + 0x0bc3: 0x2229, // XK_upshoe: INTERSECTION + 0x0bc4: 0x230A, // XK_downstile: LEFT FLOOR + 0x0bc6: 0x005F, // XK_underbar: LOW LINE + 0x0bca: 0x2218, // XK_jot: RING OPERATOR + 0x0bcc: 0x2395, // XK_quad: APL FUNCTIONAL SYMBOL QUAD + 0x0bce: 0x22A5, // XK_uptack: UP TACK + 0x0bcf: 0x25CB, // XK_circle: WHITE CIRCLE + 0x0bd3: 0x2308, // XK_upstile: LEFT CEILING + 0x0bd6: 0x222A, // XK_downshoe: UNION + 0x0bd8: 0x2283, // XK_rightshoe: SUPERSET OF + 0x0bda: 0x2282, // XK_leftshoe: SUBSET OF + 0x0bdc: 0x22A3, // XK_lefttack: LEFT TACK + 0x0bfc: 0x22A2, // XK_righttack: RIGHT TACK + 0x0cdf: 0x2017, // XK_hebrew_doublelowline: DOUBLE LOW LINE + 0x0ce0: 0x05D0, // XK_hebrew_aleph: HEBREW LETTER ALEF + 0x0ce1: 0x05D1, // XK_hebrew_bet: HEBREW LETTER BET + 0x0ce2: 0x05D2, // XK_hebrew_gimel: HEBREW LETTER GIMEL + 0x0ce3: 0x05D3, // XK_hebrew_dalet: HEBREW LETTER DALET + 0x0ce4: 0x05D4, // XK_hebrew_he: HEBREW LETTER HE + 0x0ce5: 0x05D5, // XK_hebrew_waw: HEBREW LETTER VAV + 0x0ce6: 0x05D6, // XK_hebrew_zain: HEBREW LETTER ZAYIN + 0x0ce7: 0x05D7, // XK_hebrew_chet: HEBREW LETTER HET + 0x0ce8: 0x05D8, // XK_hebrew_tet: HEBREW LETTER TET + 0x0ce9: 0x05D9, // XK_hebrew_yod: HEBREW LETTER YOD + 0x0cea: 0x05DA, // XK_hebrew_finalkaph: HEBREW LETTER FINAL KAF + 0x0ceb: 0x05DB, // XK_hebrew_kaph: HEBREW LETTER KAF + 0x0cec: 0x05DC, // XK_hebrew_lamed: HEBREW LETTER LAMED + 0x0ced: 0x05DD, // XK_hebrew_finalmem: HEBREW LETTER FINAL MEM + 0x0cee: 0x05DE, // XK_hebrew_mem: HEBREW LETTER MEM + 0x0cef: 0x05DF, // XK_hebrew_finalnun: HEBREW LETTER FINAL NUN + 0x0cf0: 0x05E0, // XK_hebrew_nun: HEBREW LETTER NUN + 0x0cf1: 0x05E1, // XK_hebrew_samech: HEBREW LETTER SAMEKH + 0x0cf2: 0x05E2, // XK_hebrew_ayin: HEBREW LETTER AYIN + 0x0cf3: 0x05E3, // XK_hebrew_finalpe: HEBREW LETTER FINAL PE + 0x0cf4: 0x05E4, // XK_hebrew_pe: HEBREW LETTER PE + 0x0cf5: 0x05E5, // XK_hebrew_finalzade: HEBREW LETTER FINAL TSADI + 0x0cf6: 0x05E6, // XK_hebrew_zade: HEBREW LETTER TSADI + 0x0cf7: 0x05E7, // XK_hebrew_qoph: HEBREW LETTER QOF + 0x0cf8: 0x05E8, // XK_hebrew_resh: HEBREW LETTER RESH + 0x0cf9: 0x05E9, // XK_hebrew_shin: HEBREW LETTER SHIN + 0x0cfa: 0x05EA, // XK_hebrew_taw: HEBREW LETTER TAV + 0x0da1: 0x0E01, // XK_Thai_kokai: THAI CHARACTER KO KAI + 0x0da2: 0x0E02, // XK_Thai_khokhai: THAI CHARACTER KHO KHAI + 0x0da3: 0x0E03, // XK_Thai_khokhuat: THAI CHARACTER KHO KHUAT + 0x0da4: 0x0E04, // XK_Thai_khokhwai: THAI CHARACTER KHO KHWAI + 0x0da5: 0x0E05, // XK_Thai_khokhon: THAI CHARACTER KHO KHON + 0x0da6: 0x0E06, // XK_Thai_khorakhang: THAI CHARACTER KHO RAKHANG + 0x0da7: 0x0E07, // XK_Thai_ngongu: THAI CHARACTER NGO NGU + 0x0da8: 0x0E08, // XK_Thai_chochan: THAI CHARACTER CHO CHAN + 0x0da9: 0x0E09, // XK_Thai_choching: THAI CHARACTER CHO CHING + 0x0daa: 0x0E0A, // XK_Thai_chochang: THAI CHARACTER CHO CHANG + 0x0dab: 0x0E0B, // XK_Thai_soso: THAI CHARACTER SO SO + 0x0dac: 0x0E0C, // XK_Thai_chochoe: THAI CHARACTER CHO CHOE + 0x0dad: 0x0E0D, // XK_Thai_yoying: THAI CHARACTER YO YING + 0x0dae: 0x0E0E, // XK_Thai_dochada: THAI CHARACTER DO CHADA + 0x0daf: 0x0E0F, // XK_Thai_topatak: THAI CHARACTER TO PATAK + 0x0db0: 0x0E10, // XK_Thai_thothan: THAI CHARACTER THO THAN + 0x0db1: 0x0E11, // XK_Thai_thonangmontho: THAI CHARACTER THO NANGMONTHO + 0x0db2: 0x0E12, // XK_Thai_thophuthao: THAI CHARACTER THO PHUTHAO + 0x0db3: 0x0E13, // XK_Thai_nonen: THAI CHARACTER NO NEN + 0x0db4: 0x0E14, // XK_Thai_dodek: THAI CHARACTER DO DEK + 0x0db5: 0x0E15, // XK_Thai_totao: THAI CHARACTER TO TAO + 0x0db6: 0x0E16, // XK_Thai_thothung: THAI CHARACTER THO THUNG + 0x0db7: 0x0E17, // XK_Thai_thothahan: THAI CHARACTER THO THAHAN + 0x0db8: 0x0E18, // XK_Thai_thothong: THAI CHARACTER THO THONG + 0x0db9: 0x0E19, // XK_Thai_nonu: THAI CHARACTER NO NU + 0x0dba: 0x0E1A, // XK_Thai_bobaimai: THAI CHARACTER BO BAIMAI + 0x0dbb: 0x0E1B, // XK_Thai_popla: THAI CHARACTER PO PLA + 0x0dbc: 0x0E1C, // XK_Thai_phophung: THAI CHARACTER PHO PHUNG + 0x0dbd: 0x0E1D, // XK_Thai_fofa: THAI CHARACTER FO FA + 0x0dbe: 0x0E1E, // XK_Thai_phophan: THAI CHARACTER PHO PHAN + 0x0dbf: 0x0E1F, // XK_Thai_fofan: THAI CHARACTER FO FAN + 0x0dc0: 0x0E20, // XK_Thai_phosamphao: THAI CHARACTER PHO SAMPHAO + 0x0dc1: 0x0E21, // XK_Thai_moma: THAI CHARACTER MO MA + 0x0dc2: 0x0E22, // XK_Thai_yoyak: THAI CHARACTER YO YAK + 0x0dc3: 0x0E23, // XK_Thai_rorua: THAI CHARACTER RO RUA + 0x0dc4: 0x0E24, // XK_Thai_ru: THAI CHARACTER RU + 0x0dc5: 0x0E25, // XK_Thai_loling: THAI CHARACTER LO LING + 0x0dc6: 0x0E26, // XK_Thai_lu: THAI CHARACTER LU + 0x0dc7: 0x0E27, // XK_Thai_wowaen: THAI CHARACTER WO WAEN + 0x0dc8: 0x0E28, // XK_Thai_sosala: THAI CHARACTER SO SALA + 0x0dc9: 0x0E29, // XK_Thai_sorusi: THAI CHARACTER SO RUSI + 0x0dca: 0x0E2A, // XK_Thai_sosua: THAI CHARACTER SO SUA + 0x0dcb: 0x0E2B, // XK_Thai_hohip: THAI CHARACTER HO HIP + 0x0dcc: 0x0E2C, // XK_Thai_lochula: THAI CHARACTER LO CHULA + 0x0dcd: 0x0E2D, // XK_Thai_oang: THAI CHARACTER O ANG + 0x0dce: 0x0E2E, // XK_Thai_honokhuk: THAI CHARACTER HO NOKHUK + 0x0dcf: 0x0E2F, // XK_Thai_paiyannoi: THAI CHARACTER PAIYANNOI + 0x0dd0: 0x0E30, // XK_Thai_saraa: THAI CHARACTER SARA A + 0x0dd1: 0x0E31, // XK_Thai_maihanakat: THAI CHARACTER MAI HAN-AKAT + 0x0dd2: 0x0E32, // XK_Thai_saraaa: THAI CHARACTER SARA AA + 0x0dd3: 0x0E33, // XK_Thai_saraam: THAI CHARACTER SARA AM + 0x0dd4: 0x0E34, // XK_Thai_sarai: THAI CHARACTER SARA I + 0x0dd5: 0x0E35, // XK_Thai_saraii: THAI CHARACTER SARA II + 0x0dd6: 0x0E36, // XK_Thai_saraue: THAI CHARACTER SARA UE + 0x0dd7: 0x0E37, // XK_Thai_sarauee: THAI CHARACTER SARA UEE + 0x0dd8: 0x0E38, // XK_Thai_sarau: THAI CHARACTER SARA U + 0x0dd9: 0x0E39, // XK_Thai_sarauu: THAI CHARACTER SARA UU + 0x0dda: 0x0E3A, // XK_Thai_phinthu: THAI CHARACTER PHINTHU + 0x0ddf: 0x0E3F, // XK_Thai_baht: THAI CURRENCY SYMBOL BAHT + 0x0de0: 0x0E40, // XK_Thai_sarae: THAI CHARACTER SARA E + 0x0de1: 0x0E41, // XK_Thai_saraae: THAI CHARACTER SARA AE + 0x0de2: 0x0E42, // XK_Thai_sarao: THAI CHARACTER SARA O + 0x0de3: 0x0E43, // XK_Thai_saraaimaimuan: THAI CHARACTER SARA AI MAIMUAN + 0x0de4: 0x0E44, // XK_Thai_saraaimaimalai: THAI CHARACTER SARA AI MAIMALAI + 0x0de5: 0x0E45, // XK_Thai_lakkhangyao: THAI CHARACTER LAKKHANGYAO + 0x0de6: 0x0E46, // XK_Thai_maiyamok: THAI CHARACTER MAIYAMOK + 0x0de7: 0x0E47, // XK_Thai_maitaikhu: THAI CHARACTER MAITAIKHU + 0x0de8: 0x0E48, // XK_Thai_maiek: THAI CHARACTER MAI EK + 0x0de9: 0x0E49, // XK_Thai_maitho: THAI CHARACTER MAI THO + 0x0dea: 0x0E4A, // XK_Thai_maitri: THAI CHARACTER MAI TRI + 0x0deb: 0x0E4B, // XK_Thai_maichattawa: THAI CHARACTER MAI CHATTAWA + 0x0dec: 0x0E4C, // XK_Thai_thanthakhat: THAI CHARACTER THANTHAKHAT + 0x0ded: 0x0E4D, // XK_Thai_nikhahit: THAI CHARACTER NIKHAHIT + 0x0df0: 0x0E50, // XK_Thai_leksun: THAI DIGIT ZERO + 0x0df1: 0x0E51, // XK_Thai_leknung: THAI DIGIT ONE + 0x0df2: 0x0E52, // XK_Thai_leksong: THAI DIGIT TWO + 0x0df3: 0x0E53, // XK_Thai_leksam: THAI DIGIT THREE + 0x0df4: 0x0E54, // XK_Thai_leksi: THAI DIGIT FOUR + 0x0df5: 0x0E55, // XK_Thai_lekha: THAI DIGIT FIVE + 0x0df6: 0x0E56, // XK_Thai_lekhok: THAI DIGIT SIX + 0x0df7: 0x0E57, // XK_Thai_lekchet: THAI DIGIT SEVEN + 0x0df8: 0x0E58, // XK_Thai_lekpaet: THAI DIGIT EIGHT + 0x0df9: 0x0E59, // XK_Thai_lekkao: THAI DIGIT NINE + 0x0eff: 0x20A9, // XK_Korean_Won: WON SIGN + 0x1000587: 0x0587, // XK_Armenian_ligature_ew: ARMENIAN SMALL LIGATURE ECH YIWN + 0x1000589: 0x0589, // XK_Armenian_full_stop: ARMENIAN FULL STOP + 0x100055d: 0x055D, // XK_Armenian_separation_mark: ARMENIAN COMMA + 0x100058a: 0x058A, // XK_Armenian_hyphen: ARMENIAN HYPHEN + 0x100055c: 0x055C, // XK_Armenian_exclam: ARMENIAN EXCLAMATION MARK + 0x100055b: 0x055B, // XK_Armenian_accent: ARMENIAN EMPHASIS MARK + 0x100055e: 0x055E, // XK_Armenian_question: ARMENIAN QUESTION MARK + 0x1000531: 0x0531, // XK_Armenian_AYB: ARMENIAN CAPITAL LETTER AYB + 0x1000561: 0x0561, // XK_Armenian_ayb: ARMENIAN SMALL LETTER AYB + 0x1000532: 0x0532, // XK_Armenian_BEN: ARMENIAN CAPITAL LETTER BEN + 0x1000562: 0x0562, // XK_Armenian_ben: ARMENIAN SMALL LETTER BEN + 0x1000533: 0x0533, // XK_Armenian_GIM: ARMENIAN CAPITAL LETTER GIM + 0x1000563: 0x0563, // XK_Armenian_gim: ARMENIAN SMALL LETTER GIM + 0x1000534: 0x0534, // XK_Armenian_DA: ARMENIAN CAPITAL LETTER DA + 0x1000564: 0x0564, // XK_Armenian_da: ARMENIAN SMALL LETTER DA + 0x1000535: 0x0535, // XK_Armenian_YECH: ARMENIAN CAPITAL LETTER ECH + 0x1000565: 0x0565, // XK_Armenian_yech: ARMENIAN SMALL LETTER ECH + 0x1000536: 0x0536, // XK_Armenian_ZA: ARMENIAN CAPITAL LETTER ZA + 0x1000566: 0x0566, // XK_Armenian_za: ARMENIAN SMALL LETTER ZA + 0x1000537: 0x0537, // XK_Armenian_E: ARMENIAN CAPITAL LETTER EH + 0x1000567: 0x0567, // XK_Armenian_e: ARMENIAN SMALL LETTER EH + 0x1000538: 0x0538, // XK_Armenian_AT: ARMENIAN CAPITAL LETTER ET + 0x1000568: 0x0568, // XK_Armenian_at: ARMENIAN SMALL LETTER ET + 0x1000539: 0x0539, // XK_Armenian_TO: ARMENIAN CAPITAL LETTER TO + 0x1000569: 0x0569, // XK_Armenian_to: ARMENIAN SMALL LETTER TO + 0x100053a: 0x053A, // XK_Armenian_ZHE: ARMENIAN CAPITAL LETTER ZHE + 0x100056a: 0x056A, // XK_Armenian_zhe: ARMENIAN SMALL LETTER ZHE + 0x100053b: 0x053B, // XK_Armenian_INI: ARMENIAN CAPITAL LETTER INI + 0x100056b: 0x056B, // XK_Armenian_ini: ARMENIAN SMALL LETTER INI + 0x100053c: 0x053C, // XK_Armenian_LYUN: ARMENIAN CAPITAL LETTER LIWN + 0x100056c: 0x056C, // XK_Armenian_lyun: ARMENIAN SMALL LETTER LIWN + 0x100053d: 0x053D, // XK_Armenian_KHE: ARMENIAN CAPITAL LETTER XEH + 0x100056d: 0x056D, // XK_Armenian_khe: ARMENIAN SMALL LETTER XEH + 0x100053e: 0x053E, // XK_Armenian_TSA: ARMENIAN CAPITAL LETTER CA + 0x100056e: 0x056E, // XK_Armenian_tsa: ARMENIAN SMALL LETTER CA + 0x100053f: 0x053F, // XK_Armenian_KEN: ARMENIAN CAPITAL LETTER KEN + 0x100056f: 0x056F, // XK_Armenian_ken: ARMENIAN SMALL LETTER KEN + 0x1000540: 0x0540, // XK_Armenian_HO: ARMENIAN CAPITAL LETTER HO + 0x1000570: 0x0570, // XK_Armenian_ho: ARMENIAN SMALL LETTER HO + 0x1000541: 0x0541, // XK_Armenian_DZA: ARMENIAN CAPITAL LETTER JA + 0x1000571: 0x0571, // XK_Armenian_dza: ARMENIAN SMALL LETTER JA + 0x1000542: 0x0542, // XK_Armenian_GHAT: ARMENIAN CAPITAL LETTER GHAD + 0x1000572: 0x0572, // XK_Armenian_ghat: ARMENIAN SMALL LETTER GHAD + 0x1000543: 0x0543, // XK_Armenian_TCHE: ARMENIAN CAPITAL LETTER CHEH + 0x1000573: 0x0573, // XK_Armenian_tche: ARMENIAN SMALL LETTER CHEH + 0x1000544: 0x0544, // XK_Armenian_MEN: ARMENIAN CAPITAL LETTER MEN + 0x1000574: 0x0574, // XK_Armenian_men: ARMENIAN SMALL LETTER MEN + 0x1000545: 0x0545, // XK_Armenian_HI: ARMENIAN CAPITAL LETTER YI + 0x1000575: 0x0575, // XK_Armenian_hi: ARMENIAN SMALL LETTER YI + 0x1000546: 0x0546, // XK_Armenian_NU: ARMENIAN CAPITAL LETTER NOW + 0x1000576: 0x0576, // XK_Armenian_nu: ARMENIAN SMALL LETTER NOW + 0x1000547: 0x0547, // XK_Armenian_SHA: ARMENIAN CAPITAL LETTER SHA + 0x1000577: 0x0577, // XK_Armenian_sha: ARMENIAN SMALL LETTER SHA + 0x1000548: 0x0548, // XK_Armenian_VO: ARMENIAN CAPITAL LETTER VO + 0x1000578: 0x0578, // XK_Armenian_vo: ARMENIAN SMALL LETTER VO + 0x1000549: 0x0549, // XK_Armenian_CHA: ARMENIAN CAPITAL LETTER CHA + 0x1000579: 0x0579, // XK_Armenian_cha: ARMENIAN SMALL LETTER CHA + 0x100054a: 0x054A, // XK_Armenian_PE: ARMENIAN CAPITAL LETTER PEH + 0x100057a: 0x057A, // XK_Armenian_pe: ARMENIAN SMALL LETTER PEH + 0x100054b: 0x054B, // XK_Armenian_JE: ARMENIAN CAPITAL LETTER JHEH + 0x100057b: 0x057B, // XK_Armenian_je: ARMENIAN SMALL LETTER JHEH + 0x100054c: 0x054C, // XK_Armenian_RA: ARMENIAN CAPITAL LETTER RA + 0x100057c: 0x057C, // XK_Armenian_ra: ARMENIAN SMALL LETTER RA + 0x100054d: 0x054D, // XK_Armenian_SE: ARMENIAN CAPITAL LETTER SEH + 0x100057d: 0x057D, // XK_Armenian_se: ARMENIAN SMALL LETTER SEH + 0x100054e: 0x054E, // XK_Armenian_VEV: ARMENIAN CAPITAL LETTER VEW + 0x100057e: 0x057E, // XK_Armenian_vev: ARMENIAN SMALL LETTER VEW + 0x100054f: 0x054F, // XK_Armenian_TYUN: ARMENIAN CAPITAL LETTER TIWN + 0x100057f: 0x057F, // XK_Armenian_tyun: ARMENIAN SMALL LETTER TIWN + 0x1000550: 0x0550, // XK_Armenian_RE: ARMENIAN CAPITAL LETTER REH + 0x1000580: 0x0580, // XK_Armenian_re: ARMENIAN SMALL LETTER REH + 0x1000551: 0x0551, // XK_Armenian_TSO: ARMENIAN CAPITAL LETTER CO + 0x1000581: 0x0581, // XK_Armenian_tso: ARMENIAN SMALL LETTER CO + 0x1000552: 0x0552, // XK_Armenian_VYUN: ARMENIAN CAPITAL LETTER YIWN + 0x1000582: 0x0582, // XK_Armenian_vyun: ARMENIAN SMALL LETTER YIWN + 0x1000553: 0x0553, // XK_Armenian_PYUR: ARMENIAN CAPITAL LETTER PIWR + 0x1000583: 0x0583, // XK_Armenian_pyur: ARMENIAN SMALL LETTER PIWR + 0x1000554: 0x0554, // XK_Armenian_KE: ARMENIAN CAPITAL LETTER KEH + 0x1000584: 0x0584, // XK_Armenian_ke: ARMENIAN SMALL LETTER KEH + 0x1000555: 0x0555, // XK_Armenian_O: ARMENIAN CAPITAL LETTER OH + 0x1000585: 0x0585, // XK_Armenian_o: ARMENIAN SMALL LETTER OH + 0x1000556: 0x0556, // XK_Armenian_FE: ARMENIAN CAPITAL LETTER FEH + 0x1000586: 0x0586, // XK_Armenian_fe: ARMENIAN SMALL LETTER FEH + 0x100055a: 0x055A, // XK_Armenian_apostrophe: ARMENIAN APOSTROPHE + 0x10010d0: 0x10D0, // XK_Georgian_an: GEORGIAN LETTER AN + 0x10010d1: 0x10D1, // XK_Georgian_ban: GEORGIAN LETTER BAN + 0x10010d2: 0x10D2, // XK_Georgian_gan: GEORGIAN LETTER GAN + 0x10010d3: 0x10D3, // XK_Georgian_don: GEORGIAN LETTER DON + 0x10010d4: 0x10D4, // XK_Georgian_en: GEORGIAN LETTER EN + 0x10010d5: 0x10D5, // XK_Georgian_vin: GEORGIAN LETTER VIN + 0x10010d6: 0x10D6, // XK_Georgian_zen: GEORGIAN LETTER ZEN + 0x10010d7: 0x10D7, // XK_Georgian_tan: GEORGIAN LETTER TAN + 0x10010d8: 0x10D8, // XK_Georgian_in: GEORGIAN LETTER IN + 0x10010d9: 0x10D9, // XK_Georgian_kan: GEORGIAN LETTER KAN + 0x10010da: 0x10DA, // XK_Georgian_las: GEORGIAN LETTER LAS + 0x10010db: 0x10DB, // XK_Georgian_man: GEORGIAN LETTER MAN + 0x10010dc: 0x10DC, // XK_Georgian_nar: GEORGIAN LETTER NAR + 0x10010dd: 0x10DD, // XK_Georgian_on: GEORGIAN LETTER ON + 0x10010de: 0x10DE, // XK_Georgian_par: GEORGIAN LETTER PAR + 0x10010df: 0x10DF, // XK_Georgian_zhar: GEORGIAN LETTER ZHAR + 0x10010e0: 0x10E0, // XK_Georgian_rae: GEORGIAN LETTER RAE + 0x10010e1: 0x10E1, // XK_Georgian_san: GEORGIAN LETTER SAN + 0x10010e2: 0x10E2, // XK_Georgian_tar: GEORGIAN LETTER TAR + 0x10010e3: 0x10E3, // XK_Georgian_un: GEORGIAN LETTER UN + 0x10010e4: 0x10E4, // XK_Georgian_phar: GEORGIAN LETTER PHAR + 0x10010e5: 0x10E5, // XK_Georgian_khar: GEORGIAN LETTER KHAR + 0x10010e6: 0x10E6, // XK_Georgian_ghan: GEORGIAN LETTER GHAN + 0x10010e7: 0x10E7, // XK_Georgian_qar: GEORGIAN LETTER QAR + 0x10010e8: 0x10E8, // XK_Georgian_shin: GEORGIAN LETTER SHIN + 0x10010e9: 0x10E9, // XK_Georgian_chin: GEORGIAN LETTER CHIN + 0x10010ea: 0x10EA, // XK_Georgian_can: GEORGIAN LETTER CAN + 0x10010eb: 0x10EB, // XK_Georgian_jil: GEORGIAN LETTER JIL + 0x10010ec: 0x10EC, // XK_Georgian_cil: GEORGIAN LETTER CIL + 0x10010ed: 0x10ED, // XK_Georgian_char: GEORGIAN LETTER CHAR + 0x10010ee: 0x10EE, // XK_Georgian_xan: GEORGIAN LETTER XAN + 0x10010ef: 0x10EF, // XK_Georgian_jhan: GEORGIAN LETTER JHAN + 0x10010f0: 0x10F0, // XK_Georgian_hae: GEORGIAN LETTER HAE + 0x10010f1: 0x10F1, // XK_Georgian_he: GEORGIAN LETTER HE + 0x10010f2: 0x10F2, // XK_Georgian_hie: GEORGIAN LETTER HIE + 0x10010f3: 0x10F3, // XK_Georgian_we: GEORGIAN LETTER WE + 0x10010f4: 0x10F4, // XK_Georgian_har: GEORGIAN LETTER HAR + 0x10010f5: 0x10F5, // XK_Georgian_hoe: GEORGIAN LETTER HOE + 0x10010f6: 0x10F6, // XK_Georgian_fi: GEORGIAN LETTER FI + 0x1001e8a: 0x1E8A, // XK_Xabovedot: LATIN CAPITAL LETTER X WITH DOT ABOVE + 0x100012c: 0x012C, // XK_Ibreve: LATIN CAPITAL LETTER I WITH BREVE + 0x10001b5: 0x01B5, // XK_Zstroke: LATIN CAPITAL LETTER Z WITH STROKE + 0x10001e6: 0x01E6, // XK_Gcaron: LATIN CAPITAL LETTER G WITH CARON + 0x10001d1: 0x01D2, // XK_Ocaron: LATIN CAPITAL LETTER O WITH CARON + 0x100019f: 0x019F, // XK_Obarred: LATIN CAPITAL LETTER O WITH MIDDLE TILDE + 0x1001e8b: 0x1E8B, // XK_xabovedot: LATIN SMALL LETTER X WITH DOT ABOVE + 0x100012d: 0x012D, // XK_ibreve: LATIN SMALL LETTER I WITH BREVE + 0x10001b6: 0x01B6, // XK_zstroke: LATIN SMALL LETTER Z WITH STROKE + 0x10001e7: 0x01E7, // XK_gcaron: LATIN SMALL LETTER G WITH CARON + 0x10001d2: 0x01D2, // XK_ocaron: LATIN SMALL LETTER O WITH CARON + 0x1000275: 0x0275, // XK_obarred: LATIN SMALL LETTER BARRED O + 0x100018f: 0x018F, // XK_SCHWA: LATIN CAPITAL LETTER SCHWA + 0x1000259: 0x0259, // XK_schwa: LATIN SMALL LETTER SCHWA + 0x10001b7: 0x01B7, // XK_EZH: LATIN CAPITAL LETTER EZH + 0x1000292: 0x0292, // XK_ezh: LATIN SMALL LETTER EZH + 0x1001e36: 0x1E36, // XK_Lbelowdot: LATIN CAPITAL LETTER L WITH DOT BELOW + 0x1001e37: 0x1E37, // XK_lbelowdot: LATIN SMALL LETTER L WITH DOT BELOW + 0x1001ea0: 0x1EA0, // XK_Abelowdot: LATIN CAPITAL LETTER A WITH DOT BELOW + 0x1001ea1: 0x1EA1, // XK_abelowdot: LATIN SMALL LETTER A WITH DOT BELOW + 0x1001ea2: 0x1EA2, // XK_Ahook: LATIN CAPITAL LETTER A WITH HOOK ABOVE + 0x1001ea3: 0x1EA3, // XK_ahook: LATIN SMALL LETTER A WITH HOOK ABOVE + 0x1001ea4: 0x1EA4, // XK_Acircumflexacute: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND ACUTE + 0x1001ea5: 0x1EA5, // XK_acircumflexacute: LATIN SMALL LETTER A WITH CIRCUMFLEX AND ACUTE + 0x1001ea6: 0x1EA6, // XK_Acircumflexgrave: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND GRAVE + 0x1001ea7: 0x1EA7, // XK_acircumflexgrave: LATIN SMALL LETTER A WITH CIRCUMFLEX AND GRAVE + 0x1001ea8: 0x1EA8, // XK_Acircumflexhook: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE + 0x1001ea9: 0x1EA9, // XK_acircumflexhook: LATIN SMALL LETTER A WITH CIRCUMFLEX AND HOOK ABOVE + 0x1001eaa: 0x1EAA, // XK_Acircumflextilde: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND TILDE + 0x1001eab: 0x1EAB, // XK_acircumflextilde: LATIN SMALL LETTER A WITH CIRCUMFLEX AND TILDE + 0x1001eac: 0x1EAC, // XK_Acircumflexbelowdot: LATIN CAPITAL LETTER A WITH CIRCUMFLEX AND DOT BELOW + 0x1001ead: 0x1EAD, // XK_acircumflexbelowdot: LATIN SMALL LETTER A WITH CIRCUMFLEX AND DOT BELOW + 0x1001eae: 0x1EAE, // XK_Abreveacute: LATIN CAPITAL LETTER A WITH BREVE AND ACUTE + 0x1001eaf: 0x1EAF, // XK_abreveacute: LATIN SMALL LETTER A WITH BREVE AND ACUTE + 0x1001eb0: 0x1EB0, // XK_Abrevegrave: LATIN CAPITAL LETTER A WITH BREVE AND GRAVE + 0x1001eb1: 0x1EB1, // XK_abrevegrave: LATIN SMALL LETTER A WITH BREVE AND GRAVE + 0x1001eb2: 0x1EB2, // XK_Abrevehook: LATIN CAPITAL LETTER A WITH BREVE AND HOOK ABOVE + 0x1001eb3: 0x1EB3, // XK_abrevehook: LATIN SMALL LETTER A WITH BREVE AND HOOK ABOVE + 0x1001eb4: 0x1EB4, // XK_Abrevetilde: LATIN CAPITAL LETTER A WITH BREVE AND TILDE + 0x1001eb5: 0x1EB5, // XK_abrevetilde: LATIN SMALL LETTER A WITH BREVE AND TILDE + 0x1001eb6: 0x1EB6, // XK_Abrevebelowdot: LATIN CAPITAL LETTER A WITH BREVE AND DOT BELOW + 0x1001eb7: 0x1EB7, // XK_abrevebelowdot: LATIN SMALL LETTER A WITH BREVE AND DOT BELOW + 0x1001eb8: 0x1EB8, // XK_Ebelowdot: LATIN CAPITAL LETTER E WITH DOT BELOW + 0x1001eb9: 0x1EB9, // XK_ebelowdot: LATIN SMALL LETTER E WITH DOT BELOW + 0x1001eba: 0x1EBA, // XK_Ehook: LATIN CAPITAL LETTER E WITH HOOK ABOVE + 0x1001ebb: 0x1EBB, // XK_ehook: LATIN SMALL LETTER E WITH HOOK ABOVE + 0x1001ebc: 0x1EBC, // XK_Etilde: LATIN CAPITAL LETTER E WITH TILDE + 0x1001ebd: 0x1EBD, // XK_etilde: LATIN SMALL LETTER E WITH TILDE + 0x1001ebe: 0x1EBE, // XK_Ecircumflexacute: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND ACUTE + 0x1001ebf: 0x1EBF, // XK_ecircumflexacute: LATIN SMALL LETTER E WITH CIRCUMFLEX AND ACUTE + 0x1001ec0: 0x1EC0, // XK_Ecircumflexgrave: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND GRAVE + 0x1001ec1: 0x1EC1, // XK_ecircumflexgrave: LATIN SMALL LETTER E WITH CIRCUMFLEX AND GRAVE + 0x1001ec2: 0x1EC2, // XK_Ecircumflexhook: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE + 0x1001ec3: 0x1EC3, // XK_ecircumflexhook: LATIN SMALL LETTER E WITH CIRCUMFLEX AND HOOK ABOVE + 0x1001ec4: 0x1EC4, // XK_Ecircumflextilde: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND TILDE + 0x1001ec5: 0x1EC5, // XK_ecircumflextilde: LATIN SMALL LETTER E WITH CIRCUMFLEX AND TILDE + 0x1001ec6: 0x1EC6, // XK_Ecircumflexbelowdot: LATIN CAPITAL LETTER E WITH CIRCUMFLEX AND DOT BELOW + 0x1001ec7: 0x1EC7, // XK_ecircumflexbelowdot: LATIN SMALL LETTER E WITH CIRCUMFLEX AND DOT BELOW + 0x1001ec8: 0x1EC8, // XK_Ihook: LATIN CAPITAL LETTER I WITH HOOK ABOVE + 0x1001ec9: 0x1EC9, // XK_ihook: LATIN SMALL LETTER I WITH HOOK ABOVE + 0x1001eca: 0x1ECA, // XK_Ibelowdot: LATIN CAPITAL LETTER I WITH DOT BELOW + 0x1001ecb: 0x1ECB, // XK_ibelowdot: LATIN SMALL LETTER I WITH DOT BELOW + 0x1001ecc: 0x1ECC, // XK_Obelowdot: LATIN CAPITAL LETTER O WITH DOT BELOW + 0x1001ecd: 0x1ECD, // XK_obelowdot: LATIN SMALL LETTER O WITH DOT BELOW + 0x1001ece: 0x1ECE, // XK_Ohook: LATIN CAPITAL LETTER O WITH HOOK ABOVE + 0x1001ecf: 0x1ECF, // XK_ohook: LATIN SMALL LETTER O WITH HOOK ABOVE + 0x1001ed0: 0x1ED0, // XK_Ocircumflexacute: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND ACUTE + 0x1001ed1: 0x1ED1, // XK_ocircumflexacute: LATIN SMALL LETTER O WITH CIRCUMFLEX AND ACUTE + 0x1001ed2: 0x1ED2, // XK_Ocircumflexgrave: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND GRAVE + 0x1001ed3: 0x1ED3, // XK_ocircumflexgrave: LATIN SMALL LETTER O WITH CIRCUMFLEX AND GRAVE + 0x1001ed4: 0x1ED4, // XK_Ocircumflexhook: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE + 0x1001ed5: 0x1ED5, // XK_ocircumflexhook: LATIN SMALL LETTER O WITH CIRCUMFLEX AND HOOK ABOVE + 0x1001ed6: 0x1ED6, // XK_Ocircumflextilde: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND TILDE + 0x1001ed7: 0x1ED7, // XK_ocircumflextilde: LATIN SMALL LETTER O WITH CIRCUMFLEX AND TILDE + 0x1001ed8: 0x1ED8, // XK_Ocircumflexbelowdot: LATIN CAPITAL LETTER O WITH CIRCUMFLEX AND DOT BELOW + 0x1001ed9: 0x1ED9, // XK_ocircumflexbelowdot: LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW + 0x1001eda: 0x1EDA, // XK_Ohornacute: LATIN CAPITAL LETTER O WITH HORN AND ACUTE + 0x1001edb: 0x1EDB, // XK_ohornacute: LATIN SMALL LETTER O WITH HORN AND ACUTE + 0x1001edc: 0x1EDC, // XK_Ohorngrave: LATIN CAPITAL LETTER O WITH HORN AND GRAVE + 0x1001edd: 0x1EDD, // XK_ohorngrave: LATIN SMALL LETTER O WITH HORN AND GRAVE + 0x1001ede: 0x1EDE, // XK_Ohornhook: LATIN CAPITAL LETTER O WITH HORN AND HOOK ABOVE + 0x1001edf: 0x1EDF, // XK_ohornhook: LATIN SMALL LETTER O WITH HORN AND HOOK ABOVE + 0x1001ee0: 0x1EE0, // XK_Ohorntilde: LATIN CAPITAL LETTER O WITH HORN AND TILDE + 0x1001ee1: 0x1EE1, // XK_ohorntilde: LATIN SMALL LETTER O WITH HORN AND TILDE + 0x1001ee2: 0x1EE2, // XK_Ohornbelowdot: LATIN CAPITAL LETTER O WITH HORN AND DOT BELOW + 0x1001ee3: 0x1EE3, // XK_ohornbelowdot: LATIN SMALL LETTER O WITH HORN AND DOT BELOW + 0x1001ee4: 0x1EE4, // XK_Ubelowdot: LATIN CAPITAL LETTER U WITH DOT BELOW + 0x1001ee5: 0x1EE5, // XK_ubelowdot: LATIN SMALL LETTER U WITH DOT BELOW + 0x1001ee6: 0x1EE6, // XK_Uhook: LATIN CAPITAL LETTER U WITH HOOK ABOVE + 0x1001ee7: 0x1EE7, // XK_uhook: LATIN SMALL LETTER U WITH HOOK ABOVE + 0x1001ee8: 0x1EE8, // XK_Uhornacute: LATIN CAPITAL LETTER U WITH HORN AND ACUTE + 0x1001ee9: 0x1EE9, // XK_uhornacute: LATIN SMALL LETTER U WITH HORN AND ACUTE + 0x1001eea: 0x1EEA, // XK_Uhorngrave: LATIN CAPITAL LETTER U WITH HORN AND GRAVE + 0x1001eeb: 0x1EEB, // XK_uhorngrave: LATIN SMALL LETTER U WITH HORN AND GRAVE + 0x1001eec: 0x1EEC, // XK_Uhornhook: LATIN CAPITAL LETTER U WITH HORN AND HOOK ABOVE + 0x1001eed: 0x1EED, // XK_uhornhook: LATIN SMALL LETTER U WITH HORN AND HOOK ABOVE + 0x1001eee: 0x1EEE, // XK_Uhorntilde: LATIN CAPITAL LETTER U WITH HORN AND TILDE + 0x1001eef: 0x1EEF, // XK_uhorntilde: LATIN SMALL LETTER U WITH HORN AND TILDE + 0x1001ef0: 0x1EF0, // XK_Uhornbelowdot: LATIN CAPITAL LETTER U WITH HORN AND DOT BELOW + 0x1001ef1: 0x1EF1, // XK_uhornbelowdot: LATIN SMALL LETTER U WITH HORN AND DOT BELOW + 0x1001ef4: 0x1EF4, // XK_Ybelowdot: LATIN CAPITAL LETTER Y WITH DOT BELOW + 0x1001ef5: 0x1EF5, // XK_ybelowdot: LATIN SMALL LETTER Y WITH DOT BELOW + 0x1001ef6: 0x1EF6, // XK_Yhook: LATIN CAPITAL LETTER Y WITH HOOK ABOVE + 0x1001ef7: 0x1EF7, // XK_yhook: LATIN SMALL LETTER Y WITH HOOK ABOVE + 0x1001ef8: 0x1EF8, // XK_Ytilde: LATIN CAPITAL LETTER Y WITH TILDE + 0x1001ef9: 0x1EF9, // XK_ytilde: LATIN SMALL LETTER Y WITH TILDE + 0x10001a0: 0x01A0, // XK_Ohorn: LATIN CAPITAL LETTER O WITH HORN + 0x10001a1: 0x01A1, // XK_ohorn: LATIN SMALL LETTER O WITH HORN + 0x10001af: 0x01AF, // XK_Uhorn: LATIN CAPITAL LETTER U WITH HORN + 0x10001b0: 0x01B0, // XK_uhorn: LATIN SMALL LETTER U WITH HORN + 0x10020a0: 0x20A0, // XK_EcuSign: EURO-CURRENCY SIGN + 0x10020a1: 0x20A1, // XK_ColonSign: COLON SIGN + 0x10020a2: 0x20A2, // XK_CruzeiroSign: CRUZEIRO SIGN + 0x10020a3: 0x20A3, // XK_FFrancSign: FRENCH FRANC SIGN + 0x10020a4: 0x20A4, // XK_LiraSign: LIRA SIGN + 0x10020a5: 0x20A5, // XK_MillSign: MILL SIGN + 0x10020a6: 0x20A6, // XK_NairaSign: NAIRA SIGN + 0x10020a7: 0x20A7, // XK_PesetaSign: PESETA SIGN + 0x10020a8: 0x20A8, // XK_RupeeSign: RUPEE SIGN + 0x10020a9: 0x20A9, // XK_WonSign: WON SIGN + 0x10020aa: 0x20AA, // XK_NewSheqelSign: NEW SHEQEL SIGN + 0x10020ab: 0x20AB, // XK_DongSign: DONG SIGN + 0x20ac: 0x20AC, // XK_EuroSign: EURO SIGN + 0x1002070: 0x2070, // XK_zerosuperior: SUPERSCRIPT ZERO + 0x1002074: 0x2074, // XK_foursuperior: SUPERSCRIPT FOUR + 0x1002075: 0x2075, // XK_fivesuperior: SUPERSCRIPT FIVE + 0x1002076: 0x2076, // XK_sixsuperior: SUPERSCRIPT SIX + 0x1002077: 0x2077, // XK_sevensuperior: SUPERSCRIPT SEVEN + 0x1002078: 0x2078, // XK_eightsuperior: SUPERSCRIPT EIGHT + 0x1002079: 0x2079, // XK_ninesuperior: SUPERSCRIPT NINE + 0x1002080: 0x2080, // XK_zerosubscript: SUBSCRIPT ZERO + 0x1002081: 0x2081, // XK_onesubscript: SUBSCRIPT ONE + 0x1002082: 0x2082, // XK_twosubscript: SUBSCRIPT TWO + 0x1002083: 0x2083, // XK_threesubscript: SUBSCRIPT THREE + 0x1002084: 0x2084, // XK_foursubscript: SUBSCRIPT FOUR + 0x1002085: 0x2085, // XK_fivesubscript: SUBSCRIPT FIVE + 0x1002086: 0x2086, // XK_sixsubscript: SUBSCRIPT SIX + 0x1002087: 0x2087, // XK_sevensubscript: SUBSCRIPT SEVEN + 0x1002088: 0x2088, // XK_eightsubscript: SUBSCRIPT EIGHT + 0x1002089: 0x2089, // XK_ninesubscript: SUBSCRIPT NINE + 0x1002202: 0x2202, // XK_partdifferential: PARTIAL DIFFERENTIAL + 0x1002205: 0x2205, // XK_emptyset: NULL SET + 0x1002208: 0x2208, // XK_elementof: ELEMENT OF + 0x1002209: 0x2209, // XK_notelementof: NOT AN ELEMENT OF + 0x100220B: 0x220B, // XK_containsas: CONTAINS AS MEMBER + 0x100221A: 0x221A, // XK_squareroot: SQUARE ROOT + 0x100221B: 0x221B, // XK_cuberoot: CUBE ROOT + 0x100221C: 0x221C, // XK_fourthroot: FOURTH ROOT + 0x100222C: 0x222C, // XK_dintegral: DOUBLE INTEGRAL + 0x100222D: 0x222D, // XK_tintegral: TRIPLE INTEGRAL + 0x1002235: 0x2235, // XK_because: BECAUSE + 0x1002248: 0x2245, // XK_approxeq: ALMOST EQUAL TO + 0x1002247: 0x2247, // XK_notapproxeq: NOT ALMOST EQUAL TO + 0x1002262: 0x2262, // XK_notidentical: NOT IDENTICAL TO + 0x1002263: 0x2263, // XK_stricteq: STRICTLY EQUIVALENT TO + 0x1002800: 0x2800, // XK_braille_blank: BRAILLE PATTERN BLANK + 0x1002801: 0x2801, // XK_braille_dots_1: BRAILLE PATTERN DOTS-1 + 0x1002802: 0x2802, // XK_braille_dots_2: BRAILLE PATTERN DOTS-2 + 0x1002803: 0x2803, // XK_braille_dots_12: BRAILLE PATTERN DOTS-12 + 0x1002804: 0x2804, // XK_braille_dots_3: BRAILLE PATTERN DOTS-3 + 0x1002805: 0x2805, // XK_braille_dots_13: BRAILLE PATTERN DOTS-13 + 0x1002806: 0x2806, // XK_braille_dots_23: BRAILLE PATTERN DOTS-23 + 0x1002807: 0x2807, // XK_braille_dots_123: BRAILLE PATTERN DOTS-123 + 0x1002808: 0x2808, // XK_braille_dots_4: BRAILLE PATTERN DOTS-4 + 0x1002809: 0x2809, // XK_braille_dots_14: BRAILLE PATTERN DOTS-14 + 0x100280a: 0x280a, // XK_braille_dots_24: BRAILLE PATTERN DOTS-24 + 0x100280b: 0x280b, // XK_braille_dots_124: BRAILLE PATTERN DOTS-124 + 0x100280c: 0x280c, // XK_braille_dots_34: BRAILLE PATTERN DOTS-34 + 0x100280d: 0x280d, // XK_braille_dots_134: BRAILLE PATTERN DOTS-134 + 0x100280e: 0x280e, // XK_braille_dots_234: BRAILLE PATTERN DOTS-234 + 0x100280f: 0x280f, // XK_braille_dots_1234: BRAILLE PATTERN DOTS-1234 + 0x1002810: 0x2810, // XK_braille_dots_5: BRAILLE PATTERN DOTS-5 + 0x1002811: 0x2811, // XK_braille_dots_15: BRAILLE PATTERN DOTS-15 + 0x1002812: 0x2812, // XK_braille_dots_25: BRAILLE PATTERN DOTS-25 + 0x1002813: 0x2813, // XK_braille_dots_125: BRAILLE PATTERN DOTS-125 + 0x1002814: 0x2814, // XK_braille_dots_35: BRAILLE PATTERN DOTS-35 + 0x1002815: 0x2815, // XK_braille_dots_135: BRAILLE PATTERN DOTS-135 + 0x1002816: 0x2816, // XK_braille_dots_235: BRAILLE PATTERN DOTS-235 + 0x1002817: 0x2817, // XK_braille_dots_1235: BRAILLE PATTERN DOTS-1235 + 0x1002818: 0x2818, // XK_braille_dots_45: BRAILLE PATTERN DOTS-45 + 0x1002819: 0x2819, // XK_braille_dots_145: BRAILLE PATTERN DOTS-145 + 0x100281a: 0x281a, // XK_braille_dots_245: BRAILLE PATTERN DOTS-245 + 0x100281b: 0x281b, // XK_braille_dots_1245: BRAILLE PATTERN DOTS-1245 + 0x100281c: 0x281c, // XK_braille_dots_345: BRAILLE PATTERN DOTS-345 + 0x100281d: 0x281d, // XK_braille_dots_1345: BRAILLE PATTERN DOTS-1345 + 0x100281e: 0x281e, // XK_braille_dots_2345: BRAILLE PATTERN DOTS-2345 + 0x100281f: 0x281f, // XK_braille_dots_12345: BRAILLE PATTERN DOTS-12345 + 0x1002820: 0x2820, // XK_braille_dots_6: BRAILLE PATTERN DOTS-6 + 0x1002821: 0x2821, // XK_braille_dots_16: BRAILLE PATTERN DOTS-16 + 0x1002822: 0x2822, // XK_braille_dots_26: BRAILLE PATTERN DOTS-26 + 0x1002823: 0x2823, // XK_braille_dots_126: BRAILLE PATTERN DOTS-126 + 0x1002824: 0x2824, // XK_braille_dots_36: BRAILLE PATTERN DOTS-36 + 0x1002825: 0x2825, // XK_braille_dots_136: BRAILLE PATTERN DOTS-136 + 0x1002826: 0x2826, // XK_braille_dots_236: BRAILLE PATTERN DOTS-236 + 0x1002827: 0x2827, // XK_braille_dots_1236: BRAILLE PATTERN DOTS-1236 + 0x1002828: 0x2828, // XK_braille_dots_46: BRAILLE PATTERN DOTS-46 + 0x1002829: 0x2829, // XK_braille_dots_146: BRAILLE PATTERN DOTS-146 + 0x100282a: 0x282a, // XK_braille_dots_246: BRAILLE PATTERN DOTS-246 + 0x100282b: 0x282b, // XK_braille_dots_1246: BRAILLE PATTERN DOTS-1246 + 0x100282c: 0x282c, // XK_braille_dots_346: BRAILLE PATTERN DOTS-346 + 0x100282d: 0x282d, // XK_braille_dots_1346: BRAILLE PATTERN DOTS-1346 + 0x100282e: 0x282e, // XK_braille_dots_2346: BRAILLE PATTERN DOTS-2346 + 0x100282f: 0x282f, // XK_braille_dots_12346: BRAILLE PATTERN DOTS-12346 + 0x1002830: 0x2830, // XK_braille_dots_56: BRAILLE PATTERN DOTS-56 + 0x1002831: 0x2831, // XK_braille_dots_156: BRAILLE PATTERN DOTS-156 + 0x1002832: 0x2832, // XK_braille_dots_256: BRAILLE PATTERN DOTS-256 + 0x1002833: 0x2833, // XK_braille_dots_1256: BRAILLE PATTERN DOTS-1256 + 0x1002834: 0x2834, // XK_braille_dots_356: BRAILLE PATTERN DOTS-356 + 0x1002835: 0x2835, // XK_braille_dots_1356: BRAILLE PATTERN DOTS-1356 + 0x1002836: 0x2836, // XK_braille_dots_2356: BRAILLE PATTERN DOTS-2356 + 0x1002837: 0x2837, // XK_braille_dots_12356: BRAILLE PATTERN DOTS-12356 + 0x1002838: 0x2838, // XK_braille_dots_456: BRAILLE PATTERN DOTS-456 + 0x1002839: 0x2839, // XK_braille_dots_1456: BRAILLE PATTERN DOTS-1456 + 0x100283a: 0x283a, // XK_braille_dots_2456: BRAILLE PATTERN DOTS-2456 + 0x100283b: 0x283b, // XK_braille_dots_12456: BRAILLE PATTERN DOTS-12456 + 0x100283c: 0x283c, // XK_braille_dots_3456: BRAILLE PATTERN DOTS-3456 + 0x100283d: 0x283d, // XK_braille_dots_13456: BRAILLE PATTERN DOTS-13456 + 0x100283e: 0x283e, // XK_braille_dots_23456: BRAILLE PATTERN DOTS-23456 + 0x100283f: 0x283f, // XK_braille_dots_123456: BRAILLE PATTERN DOTS-123456 + 0x1002840: 0x2840, // XK_braille_dots_7: BRAILLE PATTERN DOTS-7 + 0x1002841: 0x2841, // XK_braille_dots_17: BRAILLE PATTERN DOTS-17 + 0x1002842: 0x2842, // XK_braille_dots_27: BRAILLE PATTERN DOTS-27 + 0x1002843: 0x2843, // XK_braille_dots_127: BRAILLE PATTERN DOTS-127 + 0x1002844: 0x2844, // XK_braille_dots_37: BRAILLE PATTERN DOTS-37 + 0x1002845: 0x2845, // XK_braille_dots_137: BRAILLE PATTERN DOTS-137 + 0x1002846: 0x2846, // XK_braille_dots_237: BRAILLE PATTERN DOTS-237 + 0x1002847: 0x2847, // XK_braille_dots_1237: BRAILLE PATTERN DOTS-1237 + 0x1002848: 0x2848, // XK_braille_dots_47: BRAILLE PATTERN DOTS-47 + 0x1002849: 0x2849, // XK_braille_dots_147: BRAILLE PATTERN DOTS-147 + 0x100284a: 0x284a, // XK_braille_dots_247: BRAILLE PATTERN DOTS-247 + 0x100284b: 0x284b, // XK_braille_dots_1247: BRAILLE PATTERN DOTS-1247 + 0x100284c: 0x284c, // XK_braille_dots_347: BRAILLE PATTERN DOTS-347 + 0x100284d: 0x284d, // XK_braille_dots_1347: BRAILLE PATTERN DOTS-1347 + 0x100284e: 0x284e, // XK_braille_dots_2347: BRAILLE PATTERN DOTS-2347 + 0x100284f: 0x284f, // XK_braille_dots_12347: BRAILLE PATTERN DOTS-12347 + 0x1002850: 0x2850, // XK_braille_dots_57: BRAILLE PATTERN DOTS-57 + 0x1002851: 0x2851, // XK_braille_dots_157: BRAILLE PATTERN DOTS-157 + 0x1002852: 0x2852, // XK_braille_dots_257: BRAILLE PATTERN DOTS-257 + 0x1002853: 0x2853, // XK_braille_dots_1257: BRAILLE PATTERN DOTS-1257 + 0x1002854: 0x2854, // XK_braille_dots_357: BRAILLE PATTERN DOTS-357 + 0x1002855: 0x2855, // XK_braille_dots_1357: BRAILLE PATTERN DOTS-1357 + 0x1002856: 0x2856, // XK_braille_dots_2357: BRAILLE PATTERN DOTS-2357 + 0x1002857: 0x2857, // XK_braille_dots_12357: BRAILLE PATTERN DOTS-12357 + 0x1002858: 0x2858, // XK_braille_dots_457: BRAILLE PATTERN DOTS-457 + 0x1002859: 0x2859, // XK_braille_dots_1457: BRAILLE PATTERN DOTS-1457 + 0x100285a: 0x285a, // XK_braille_dots_2457: BRAILLE PATTERN DOTS-2457 + 0x100285b: 0x285b, // XK_braille_dots_12457: BRAILLE PATTERN DOTS-12457 + 0x100285c: 0x285c, // XK_braille_dots_3457: BRAILLE PATTERN DOTS-3457 + 0x100285d: 0x285d, // XK_braille_dots_13457: BRAILLE PATTERN DOTS-13457 + 0x100285e: 0x285e, // XK_braille_dots_23457: BRAILLE PATTERN DOTS-23457 + 0x100285f: 0x285f, // XK_braille_dots_123457: BRAILLE PATTERN DOTS-123457 + 0x1002860: 0x2860, // XK_braille_dots_67: BRAILLE PATTERN DOTS-67 + 0x1002861: 0x2861, // XK_braille_dots_167: BRAILLE PATTERN DOTS-167 + 0x1002862: 0x2862, // XK_braille_dots_267: BRAILLE PATTERN DOTS-267 + 0x1002863: 0x2863, // XK_braille_dots_1267: BRAILLE PATTERN DOTS-1267 + 0x1002864: 0x2864, // XK_braille_dots_367: BRAILLE PATTERN DOTS-367 + 0x1002865: 0x2865, // XK_braille_dots_1367: BRAILLE PATTERN DOTS-1367 + 0x1002866: 0x2866, // XK_braille_dots_2367: BRAILLE PATTERN DOTS-2367 + 0x1002867: 0x2867, // XK_braille_dots_12367: BRAILLE PATTERN DOTS-12367 + 0x1002868: 0x2868, // XK_braille_dots_467: BRAILLE PATTERN DOTS-467 + 0x1002869: 0x2869, // XK_braille_dots_1467: BRAILLE PATTERN DOTS-1467 + 0x100286a: 0x286a, // XK_braille_dots_2467: BRAILLE PATTERN DOTS-2467 + 0x100286b: 0x286b, // XK_braille_dots_12467: BRAILLE PATTERN DOTS-12467 + 0x100286c: 0x286c, // XK_braille_dots_3467: BRAILLE PATTERN DOTS-3467 + 0x100286d: 0x286d, // XK_braille_dots_13467: BRAILLE PATTERN DOTS-13467 + 0x100286e: 0x286e, // XK_braille_dots_23467: BRAILLE PATTERN DOTS-23467 + 0x100286f: 0x286f, // XK_braille_dots_123467: BRAILLE PATTERN DOTS-123467 + 0x1002870: 0x2870, // XK_braille_dots_567: BRAILLE PATTERN DOTS-567 + 0x1002871: 0x2871, // XK_braille_dots_1567: BRAILLE PATTERN DOTS-1567 + 0x1002872: 0x2872, // XK_braille_dots_2567: BRAILLE PATTERN DOTS-2567 + 0x1002873: 0x2873, // XK_braille_dots_12567: BRAILLE PATTERN DOTS-12567 + 0x1002874: 0x2874, // XK_braille_dots_3567: BRAILLE PATTERN DOTS-3567 + 0x1002875: 0x2875, // XK_braille_dots_13567: BRAILLE PATTERN DOTS-13567 + 0x1002876: 0x2876, // XK_braille_dots_23567: BRAILLE PATTERN DOTS-23567 + 0x1002877: 0x2877, // XK_braille_dots_123567: BRAILLE PATTERN DOTS-123567 + 0x1002878: 0x2878, // XK_braille_dots_4567: BRAILLE PATTERN DOTS-4567 + 0x1002879: 0x2879, // XK_braille_dots_14567: BRAILLE PATTERN DOTS-14567 + 0x100287a: 0x287a, // XK_braille_dots_24567: BRAILLE PATTERN DOTS-24567 + 0x100287b: 0x287b, // XK_braille_dots_124567: BRAILLE PATTERN DOTS-124567 + 0x100287c: 0x287c, // XK_braille_dots_34567: BRAILLE PATTERN DOTS-34567 + 0x100287d: 0x287d, // XK_braille_dots_134567: BRAILLE PATTERN DOTS-134567 + 0x100287e: 0x287e, // XK_braille_dots_234567: BRAILLE PATTERN DOTS-234567 + 0x100287f: 0x287f, // XK_braille_dots_1234567: BRAILLE PATTERN DOTS-1234567 + 0x1002880: 0x2880, // XK_braille_dots_8: BRAILLE PATTERN DOTS-8 + 0x1002881: 0x2881, // XK_braille_dots_18: BRAILLE PATTERN DOTS-18 + 0x1002882: 0x2882, // XK_braille_dots_28: BRAILLE PATTERN DOTS-28 + 0x1002883: 0x2883, // XK_braille_dots_128: BRAILLE PATTERN DOTS-128 + 0x1002884: 0x2884, // XK_braille_dots_38: BRAILLE PATTERN DOTS-38 + 0x1002885: 0x2885, // XK_braille_dots_138: BRAILLE PATTERN DOTS-138 + 0x1002886: 0x2886, // XK_braille_dots_238: BRAILLE PATTERN DOTS-238 + 0x1002887: 0x2887, // XK_braille_dots_1238: BRAILLE PATTERN DOTS-1238 + 0x1002888: 0x2888, // XK_braille_dots_48: BRAILLE PATTERN DOTS-48 + 0x1002889: 0x2889, // XK_braille_dots_148: BRAILLE PATTERN DOTS-148 + 0x100288a: 0x288a, // XK_braille_dots_248: BRAILLE PATTERN DOTS-248 + 0x100288b: 0x288b, // XK_braille_dots_1248: BRAILLE PATTERN DOTS-1248 + 0x100288c: 0x288c, // XK_braille_dots_348: BRAILLE PATTERN DOTS-348 + 0x100288d: 0x288d, // XK_braille_dots_1348: BRAILLE PATTERN DOTS-1348 + 0x100288e: 0x288e, // XK_braille_dots_2348: BRAILLE PATTERN DOTS-2348 + 0x100288f: 0x288f, // XK_braille_dots_12348: BRAILLE PATTERN DOTS-12348 + 0x1002890: 0x2890, // XK_braille_dots_58: BRAILLE PATTERN DOTS-58 + 0x1002891: 0x2891, // XK_braille_dots_158: BRAILLE PATTERN DOTS-158 + 0x1002892: 0x2892, // XK_braille_dots_258: BRAILLE PATTERN DOTS-258 + 0x1002893: 0x2893, // XK_braille_dots_1258: BRAILLE PATTERN DOTS-1258 + 0x1002894: 0x2894, // XK_braille_dots_358: BRAILLE PATTERN DOTS-358 + 0x1002895: 0x2895, // XK_braille_dots_1358: BRAILLE PATTERN DOTS-1358 + 0x1002896: 0x2896, // XK_braille_dots_2358: BRAILLE PATTERN DOTS-2358 + 0x1002897: 0x2897, // XK_braille_dots_12358: BRAILLE PATTERN DOTS-12358 + 0x1002898: 0x2898, // XK_braille_dots_458: BRAILLE PATTERN DOTS-458 + 0x1002899: 0x2899, // XK_braille_dots_1458: BRAILLE PATTERN DOTS-1458 + 0x100289a: 0x289a, // XK_braille_dots_2458: BRAILLE PATTERN DOTS-2458 + 0x100289b: 0x289b, // XK_braille_dots_12458: BRAILLE PATTERN DOTS-12458 + 0x100289c: 0x289c, // XK_braille_dots_3458: BRAILLE PATTERN DOTS-3458 + 0x100289d: 0x289d, // XK_braille_dots_13458: BRAILLE PATTERN DOTS-13458 + 0x100289e: 0x289e, // XK_braille_dots_23458: BRAILLE PATTERN DOTS-23458 + 0x100289f: 0x289f, // XK_braille_dots_123458: BRAILLE PATTERN DOTS-123458 + 0x10028a0: 0x28a0, // XK_braille_dots_68: BRAILLE PATTERN DOTS-68 + 0x10028a1: 0x28a1, // XK_braille_dots_168: BRAILLE PATTERN DOTS-168 + 0x10028a2: 0x28a2, // XK_braille_dots_268: BRAILLE PATTERN DOTS-268 + 0x10028a3: 0x28a3, // XK_braille_dots_1268: BRAILLE PATTERN DOTS-1268 + 0x10028a4: 0x28a4, // XK_braille_dots_368: BRAILLE PATTERN DOTS-368 + 0x10028a5: 0x28a5, // XK_braille_dots_1368: BRAILLE PATTERN DOTS-1368 + 0x10028a6: 0x28a6, // XK_braille_dots_2368: BRAILLE PATTERN DOTS-2368 + 0x10028a7: 0x28a7, // XK_braille_dots_12368: BRAILLE PATTERN DOTS-12368 + 0x10028a8: 0x28a8, // XK_braille_dots_468: BRAILLE PATTERN DOTS-468 + 0x10028a9: 0x28a9, // XK_braille_dots_1468: BRAILLE PATTERN DOTS-1468 + 0x10028aa: 0x28aa, // XK_braille_dots_2468: BRAILLE PATTERN DOTS-2468 + 0x10028ab: 0x28ab, // XK_braille_dots_12468: BRAILLE PATTERN DOTS-12468 + 0x10028ac: 0x28ac, // XK_braille_dots_3468: BRAILLE PATTERN DOTS-3468 + 0x10028ad: 0x28ad, // XK_braille_dots_13468: BRAILLE PATTERN DOTS-13468 + 0x10028ae: 0x28ae, // XK_braille_dots_23468: BRAILLE PATTERN DOTS-23468 + 0x10028af: 0x28af, // XK_braille_dots_123468: BRAILLE PATTERN DOTS-123468 + 0x10028b0: 0x28b0, // XK_braille_dots_568: BRAILLE PATTERN DOTS-568 + 0x10028b1: 0x28b1, // XK_braille_dots_1568: BRAILLE PATTERN DOTS-1568 + 0x10028b2: 0x28b2, // XK_braille_dots_2568: BRAILLE PATTERN DOTS-2568 + 0x10028b3: 0x28b3, // XK_braille_dots_12568: BRAILLE PATTERN DOTS-12568 + 0x10028b4: 0x28b4, // XK_braille_dots_3568: BRAILLE PATTERN DOTS-3568 + 0x10028b5: 0x28b5, // XK_braille_dots_13568: BRAILLE PATTERN DOTS-13568 + 0x10028b6: 0x28b6, // XK_braille_dots_23568: BRAILLE PATTERN DOTS-23568 + 0x10028b7: 0x28b7, // XK_braille_dots_123568: BRAILLE PATTERN DOTS-123568 + 0x10028b8: 0x28b8, // XK_braille_dots_4568: BRAILLE PATTERN DOTS-4568 + 0x10028b9: 0x28b9, // XK_braille_dots_14568: BRAILLE PATTERN DOTS-14568 + 0x10028ba: 0x28ba, // XK_braille_dots_24568: BRAILLE PATTERN DOTS-24568 + 0x10028bb: 0x28bb, // XK_braille_dots_124568: BRAILLE PATTERN DOTS-124568 + 0x10028bc: 0x28bc, // XK_braille_dots_34568: BRAILLE PATTERN DOTS-34568 + 0x10028bd: 0x28bd, // XK_braille_dots_134568: BRAILLE PATTERN DOTS-134568 + 0x10028be: 0x28be, // XK_braille_dots_234568: BRAILLE PATTERN DOTS-234568 + 0x10028bf: 0x28bf, // XK_braille_dots_1234568: BRAILLE PATTERN DOTS-1234568 + 0x10028c0: 0x28c0, // XK_braille_dots_78: BRAILLE PATTERN DOTS-78 + 0x10028c1: 0x28c1, // XK_braille_dots_178: BRAILLE PATTERN DOTS-178 + 0x10028c2: 0x28c2, // XK_braille_dots_278: BRAILLE PATTERN DOTS-278 + 0x10028c3: 0x28c3, // XK_braille_dots_1278: BRAILLE PATTERN DOTS-1278 + 0x10028c4: 0x28c4, // XK_braille_dots_378: BRAILLE PATTERN DOTS-378 + 0x10028c5: 0x28c5, // XK_braille_dots_1378: BRAILLE PATTERN DOTS-1378 + 0x10028c6: 0x28c6, // XK_braille_dots_2378: BRAILLE PATTERN DOTS-2378 + 0x10028c7: 0x28c7, // XK_braille_dots_12378: BRAILLE PATTERN DOTS-12378 + 0x10028c8: 0x28c8, // XK_braille_dots_478: BRAILLE PATTERN DOTS-478 + 0x10028c9: 0x28c9, // XK_braille_dots_1478: BRAILLE PATTERN DOTS-1478 + 0x10028ca: 0x28ca, // XK_braille_dots_2478: BRAILLE PATTERN DOTS-2478 + 0x10028cb: 0x28cb, // XK_braille_dots_12478: BRAILLE PATTERN DOTS-12478 + 0x10028cc: 0x28cc, // XK_braille_dots_3478: BRAILLE PATTERN DOTS-3478 + 0x10028cd: 0x28cd, // XK_braille_dots_13478: BRAILLE PATTERN DOTS-13478 + 0x10028ce: 0x28ce, // XK_braille_dots_23478: BRAILLE PATTERN DOTS-23478 + 0x10028cf: 0x28cf, // XK_braille_dots_123478: BRAILLE PATTERN DOTS-123478 + 0x10028d0: 0x28d0, // XK_braille_dots_578: BRAILLE PATTERN DOTS-578 + 0x10028d1: 0x28d1, // XK_braille_dots_1578: BRAILLE PATTERN DOTS-1578 + 0x10028d2: 0x28d2, // XK_braille_dots_2578: BRAILLE PATTERN DOTS-2578 + 0x10028d3: 0x28d3, // XK_braille_dots_12578: BRAILLE PATTERN DOTS-12578 + 0x10028d4: 0x28d4, // XK_braille_dots_3578: BRAILLE PATTERN DOTS-3578 + 0x10028d5: 0x28d5, // XK_braille_dots_13578: BRAILLE PATTERN DOTS-13578 + 0x10028d6: 0x28d6, // XK_braille_dots_23578: BRAILLE PATTERN DOTS-23578 + 0x10028d7: 0x28d7, // XK_braille_dots_123578: BRAILLE PATTERN DOTS-123578 + 0x10028d8: 0x28d8, // XK_braille_dots_4578: BRAILLE PATTERN DOTS-4578 + 0x10028d9: 0x28d9, // XK_braille_dots_14578: BRAILLE PATTERN DOTS-14578 + 0x10028da: 0x28da, // XK_braille_dots_24578: BRAILLE PATTERN DOTS-24578 + 0x10028db: 0x28db, // XK_braille_dots_124578: BRAILLE PATTERN DOTS-124578 + 0x10028dc: 0x28dc, // XK_braille_dots_34578: BRAILLE PATTERN DOTS-34578 + 0x10028dd: 0x28dd, // XK_braille_dots_134578: BRAILLE PATTERN DOTS-134578 + 0x10028de: 0x28de, // XK_braille_dots_234578: BRAILLE PATTERN DOTS-234578 + 0x10028df: 0x28df, // XK_braille_dots_1234578: BRAILLE PATTERN DOTS-1234578 + 0x10028e0: 0x28e0, // XK_braille_dots_678: BRAILLE PATTERN DOTS-678 + 0x10028e1: 0x28e1, // XK_braille_dots_1678: BRAILLE PATTERN DOTS-1678 + 0x10028e2: 0x28e2, // XK_braille_dots_2678: BRAILLE PATTERN DOTS-2678 + 0x10028e3: 0x28e3, // XK_braille_dots_12678: BRAILLE PATTERN DOTS-12678 + 0x10028e4: 0x28e4, // XK_braille_dots_3678: BRAILLE PATTERN DOTS-3678 + 0x10028e5: 0x28e5, // XK_braille_dots_13678: BRAILLE PATTERN DOTS-13678 + 0x10028e6: 0x28e6, // XK_braille_dots_23678: BRAILLE PATTERN DOTS-23678 + 0x10028e7: 0x28e7, // XK_braille_dots_123678: BRAILLE PATTERN DOTS-123678 + 0x10028e8: 0x28e8, // XK_braille_dots_4678: BRAILLE PATTERN DOTS-4678 + 0x10028e9: 0x28e9, // XK_braille_dots_14678: BRAILLE PATTERN DOTS-14678 + 0x10028ea: 0x28ea, // XK_braille_dots_24678: BRAILLE PATTERN DOTS-24678 + 0x10028eb: 0x28eb, // XK_braille_dots_124678: BRAILLE PATTERN DOTS-124678 + 0x10028ec: 0x28ec, // XK_braille_dots_34678: BRAILLE PATTERN DOTS-34678 + 0x10028ed: 0x28ed, // XK_braille_dots_134678: BRAILLE PATTERN DOTS-134678 + 0x10028ee: 0x28ee, // XK_braille_dots_234678: BRAILLE PATTERN DOTS-234678 + 0x10028ef: 0x28ef, // XK_braille_dots_1234678: BRAILLE PATTERN DOTS-1234678 + 0x10028f0: 0x28f0, // XK_braille_dots_5678: BRAILLE PATTERN DOTS-5678 + 0x10028f1: 0x28f1, // XK_braille_dots_15678: BRAILLE PATTERN DOTS-15678 + 0x10028f2: 0x28f2, // XK_braille_dots_25678: BRAILLE PATTERN DOTS-25678 + 0x10028f3: 0x28f3, // XK_braille_dots_125678: BRAILLE PATTERN DOTS-125678 + 0x10028f4: 0x28f4, // XK_braille_dots_35678: BRAILLE PATTERN DOTS-35678 + 0x10028f5: 0x28f5, // XK_braille_dots_135678: BRAILLE PATTERN DOTS-135678 + 0x10028f6: 0x28f6, // XK_braille_dots_235678: BRAILLE PATTERN DOTS-235678 + 0x10028f7: 0x28f7, // XK_braille_dots_1235678: BRAILLE PATTERN DOTS-1235678 + 0x10028f8: 0x28f8, // XK_braille_dots_45678: BRAILLE PATTERN DOTS-45678 + 0x10028f9: 0x28f9, // XK_braille_dots_145678: BRAILLE PATTERN DOTS-145678 + 0x10028fa: 0x28fa, // XK_braille_dots_245678: BRAILLE PATTERN DOTS-245678 + 0x10028fb: 0x28fb, // XK_braille_dots_1245678: BRAILLE PATTERN DOTS-1245678 + 0x10028fc: 0x28fc, // XK_braille_dots_345678: BRAILLE PATTERN DOTS-345678 + 0x10028fd: 0x28fd, // XK_braille_dots_1345678: BRAILLE PATTERN DOTS-1345678 + 0x10028fe: 0x28fe, // XK_braille_dots_2345678: BRAILLE PATTERN DOTS-2345678 + 0x10028ff: 0x28ff, // XK_braille_dots_12345678: BRAILLE PATTERN DOTS-12345678 + 0x1000d82: 0x0D82, // XK_Sinh_ng: SINHALA ANUSVARAYA + 0x1000d83: 0x0D83, // XK_Sinh_h2: SINHALA VISARGAYA + 0x1000d85: 0x0D85, // XK_Sinh_a: SINHALA AYANNA + 0x1000d86: 0x0D86, // XK_Sinh_aa: SINHALA AAYANNA + 0x1000d87: 0x0D87, // XK_Sinh_ae: SINHALA AEYANNA + 0x1000d88: 0x0D88, // XK_Sinh_aee: SINHALA AEEYANNA + 0x1000d89: 0x0D89, // XK_Sinh_i: SINHALA IYANNA + 0x1000d8a: 0x0D8A, // XK_Sinh_ii: SINHALA IIYANNA + 0x1000d8b: 0x0D8B, // XK_Sinh_u: SINHALA UYANNA + 0x1000d8c: 0x0D8C, // XK_Sinh_uu: SINHALA UUYANNA + 0x1000d8d: 0x0D8D, // XK_Sinh_ri: SINHALA IRUYANNA + 0x1000d8e: 0x0D8E, // XK_Sinh_rii: SINHALA IRUUYANNA + 0x1000d8f: 0x0D8F, // XK_Sinh_lu: SINHALA ILUYANNA + 0x1000d90: 0x0D90, // XK_Sinh_luu: SINHALA ILUUYANNA + 0x1000d91: 0x0D91, // XK_Sinh_e: SINHALA EYANNA + 0x1000d92: 0x0D92, // XK_Sinh_ee: SINHALA EEYANNA + 0x1000d93: 0x0D93, // XK_Sinh_ai: SINHALA AIYANNA + 0x1000d94: 0x0D94, // XK_Sinh_o: SINHALA OYANNA + 0x1000d95: 0x0D95, // XK_Sinh_oo: SINHALA OOYANNA + 0x1000d96: 0x0D96, // XK_Sinh_au: SINHALA AUYANNA + 0x1000d9a: 0x0D9A, // XK_Sinh_ka: SINHALA KAYANNA + 0x1000d9b: 0x0D9B, // XK_Sinh_kha: SINHALA MAHA. KAYANNA + 0x1000d9c: 0x0D9C, // XK_Sinh_ga: SINHALA GAYANNA + 0x1000d9d: 0x0D9D, // XK_Sinh_gha: SINHALA MAHA. GAYANNA + 0x1000d9e: 0x0D9E, // XK_Sinh_ng2: SINHALA KANTAJA NAASIKYAYA + 0x1000d9f: 0x0D9F, // XK_Sinh_nga: SINHALA SANYAKA GAYANNA + 0x1000da0: 0x0DA0, // XK_Sinh_ca: SINHALA CAYANNA + 0x1000da1: 0x0DA1, // XK_Sinh_cha: SINHALA MAHA. CAYANNA + 0x1000da2: 0x0DA2, // XK_Sinh_ja: SINHALA JAYANNA + 0x1000da3: 0x0DA3, // XK_Sinh_jha: SINHALA MAHA. JAYANNA + 0x1000da4: 0x0DA4, // XK_Sinh_nya: SINHALA TAALUJA NAASIKYAYA + 0x1000da5: 0x0DA5, // XK_Sinh_jnya: SINHALA TAALUJA SANYOOGA NAASIKYAYA + 0x1000da6: 0x0DA6, // XK_Sinh_nja: SINHALA SANYAKA JAYANNA + 0x1000da7: 0x0DA7, // XK_Sinh_tta: SINHALA TTAYANNA + 0x1000da8: 0x0DA8, // XK_Sinh_ttha: SINHALA MAHA. TTAYANNA + 0x1000da9: 0x0DA9, // XK_Sinh_dda: SINHALA DDAYANNA + 0x1000daa: 0x0DAA, // XK_Sinh_ddha: SINHALA MAHA. DDAYANNA + 0x1000dab: 0x0DAB, // XK_Sinh_nna: SINHALA MUURDHAJA NAYANNA + 0x1000dac: 0x0DAC, // XK_Sinh_ndda: SINHALA SANYAKA DDAYANNA + 0x1000dad: 0x0DAD, // XK_Sinh_tha: SINHALA TAYANNA + 0x1000dae: 0x0DAE, // XK_Sinh_thha: SINHALA MAHA. TAYANNA + 0x1000daf: 0x0DAF, // XK_Sinh_dha: SINHALA DAYANNA + 0x1000db0: 0x0DB0, // XK_Sinh_dhha: SINHALA MAHA. DAYANNA + 0x1000db1: 0x0DB1, // XK_Sinh_na: SINHALA DANTAJA NAYANNA + 0x1000db3: 0x0DB3, // XK_Sinh_ndha: SINHALA SANYAKA DAYANNA + 0x1000db4: 0x0DB4, // XK_Sinh_pa: SINHALA PAYANNA + 0x1000db5: 0x0DB5, // XK_Sinh_pha: SINHALA MAHA. PAYANNA + 0x1000db6: 0x0DB6, // XK_Sinh_ba: SINHALA BAYANNA + 0x1000db7: 0x0DB7, // XK_Sinh_bha: SINHALA MAHA. BAYANNA + 0x1000db8: 0x0DB8, // XK_Sinh_ma: SINHALA MAYANNA + 0x1000db9: 0x0DB9, // XK_Sinh_mba: SINHALA AMBA BAYANNA + 0x1000dba: 0x0DBA, // XK_Sinh_ya: SINHALA YAYANNA + 0x1000dbb: 0x0DBB, // XK_Sinh_ra: SINHALA RAYANNA + 0x1000dbd: 0x0DBD, // XK_Sinh_la: SINHALA DANTAJA LAYANNA + 0x1000dc0: 0x0DC0, // XK_Sinh_va: SINHALA VAYANNA + 0x1000dc1: 0x0DC1, // XK_Sinh_sha: SINHALA TAALUJA SAYANNA + 0x1000dc2: 0x0DC2, // XK_Sinh_ssha: SINHALA MUURDHAJA SAYANNA + 0x1000dc3: 0x0DC3, // XK_Sinh_sa: SINHALA DANTAJA SAYANNA + 0x1000dc4: 0x0DC4, // XK_Sinh_ha: SINHALA HAYANNA + 0x1000dc5: 0x0DC5, // XK_Sinh_lla: SINHALA MUURDHAJA LAYANNA + 0x1000dc6: 0x0DC6, // XK_Sinh_fa: SINHALA FAYANNA + 0x1000dca: 0x0DCA, // XK_Sinh_al: SINHALA AL-LAKUNA + 0x1000dcf: 0x0DCF, // XK_Sinh_aa2: SINHALA AELA-PILLA + 0x1000dd0: 0x0DD0, // XK_Sinh_ae2: SINHALA AEDA-PILLA + 0x1000dd1: 0x0DD1, // XK_Sinh_aee2: SINHALA DIGA AEDA-PILLA + 0x1000dd2: 0x0DD2, // XK_Sinh_i2: SINHALA IS-PILLA + 0x1000dd3: 0x0DD3, // XK_Sinh_ii2: SINHALA DIGA IS-PILLA + 0x1000dd4: 0x0DD4, // XK_Sinh_u2: SINHALA PAA-PILLA + 0x1000dd6: 0x0DD6, // XK_Sinh_uu2: SINHALA DIGA PAA-PILLA + 0x1000dd8: 0x0DD8, // XK_Sinh_ru2: SINHALA GAETTA-PILLA + 0x1000dd9: 0x0DD9, // XK_Sinh_e2: SINHALA KOMBUVA + 0x1000dda: 0x0DDA, // XK_Sinh_ee2: SINHALA DIGA KOMBUVA + 0x1000ddb: 0x0DDB, // XK_Sinh_ai2: SINHALA KOMBU DEKA + 0x1000dde: 0x0DDE, // XK_Sinh_au2: SINHALA KOMBUVA HAA GAYANUKITTA + 0x1000ddf: 0x0DDF, // XK_Sinh_lu2: SINHALA GAYANUKITTA + 0x1000df2: 0x0DF2, // XK_Sinh_ruu2: SINHALA DIGA GAETTA-PILLA + 0x1000df3: 0x0DF3, // XK_Sinh_luu2: SINHALA DIGA GAYANUKITTA + 0x1000df4: 0x0DF4, // XK_Sinh_kunddaliya: SINHALA KUNDDALIYA +} diff --git a/vendor/golang.org/x/exp/shiny/driver/internal/x11key/x11key.go b/vendor/golang.org/x/exp/shiny/driver/internal/x11key/x11key.go new file mode 100644 index 00000000..546d4630 --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/driver/internal/x11key/x11key.go @@ -0,0 +1,323 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate go run gen.go + +// x11key contains X11 numeric codes for the keyboard and mouse. +package x11key // import "golang.org/x/exp/shiny/driver/internal/x11key" + +import ( + "unicode" + + "golang.org/x/mobile/event/key" +) + +// These constants come from /usr/include/X11/X.h +const ( + ShiftMask = 1 << 0 + LockMask = 1 << 1 + ControlMask = 1 << 2 + Mod1Mask = 1 << 3 + Mod2Mask = 1 << 4 + Mod3Mask = 1 << 5 + Mod4Mask = 1 << 6 + Mod5Mask = 1 << 7 + Button1Mask = 1 << 8 + Button2Mask = 1 << 9 + Button3Mask = 1 << 10 + Button4Mask = 1 << 11 + Button5Mask = 1 << 12 +) + +type KeysymTable struct { + Table [256][6]uint32 + + NumLockMod, ModeSwitchMod, ISOLevel3ShiftMod uint16 +} + +func (t *KeysymTable) Lookup(detail uint8, state uint16) (rune, key.Code) { + te := t.Table[detail][0:2] + if state&t.ModeSwitchMod != 0 { + te = t.Table[detail][2:4] + } + if state&t.ISOLevel3ShiftMod != 0 { + te = t.Table[detail][4:6] + } + + // The key event's rune depends on whether the shift key is down. + unshifted := rune(te[0]) + r := unshifted + if state&t.NumLockMod != 0 && isKeypad(te[1]) { + if state&ShiftMask == 0 { + r = rune(te[1]) + } + } else if state&ShiftMask != 0 { + r = rune(te[1]) + // In X11, a zero keysym when shift is down means to use what the + // keysym is when shift is up. + if r == 0 { + r = unshifted + } + } + + // The key event's code is independent of whether the shift key is down. + var c key.Code + if 0 <= unshifted && unshifted < 0x80 { + c = asciiKeycodes[unshifted] + if state&LockMask != 0 { + r = unicode.ToUpper(r) + } + } else if kk, isKeypad := keypadKeysyms[r]; isKeypad { + r, c = kk.rune, kk.code + } else if nuk := nonUnicodeKeycodes[unshifted]; nuk != key.CodeUnknown { + r, c = -1, nuk + } else { + r = keysymCodePoints[r] + if state&LockMask != 0 { + r = unicode.ToUpper(r) + } + } + + return r, c +} + +func isKeypad(keysym uint32) bool { + return keysym >= 0xff80 && keysym <= 0xffbd +} + +func KeyModifiers(state uint16) (m key.Modifiers) { + if state&ShiftMask != 0 { + m |= key.ModShift + } + if state&ControlMask != 0 { + m |= key.ModControl + } + if state&Mod1Mask != 0 { + m |= key.ModAlt + } + if state&Mod4Mask != 0 { + m |= key.ModMeta + } + return m +} + +// These constants come from /usr/include/X11/{keysymdef,XF86keysym}.h +const ( + xkISOLeftTab = 0xfe20 + xkBackSpace = 0xff08 + xkTab = 0xff09 + xkReturn = 0xff0d + xkEscape = 0xff1b + xkMultiKey = 0xff20 + xkHome = 0xff50 + xkLeft = 0xff51 + xkUp = 0xff52 + xkRight = 0xff53 + xkDown = 0xff54 + xkPageUp = 0xff55 + xkPageDown = 0xff56 + xkEnd = 0xff57 + xkInsert = 0xff63 + xkMenu = 0xff67 + xkHelp = 0xff6a + + xkNumLock = 0xff7f + xkKeypadEnter = 0xff8d + xkKeypadHome = 0xff95 + xkKeypadLeft = 0xff96 + xkKeypadUp = 0xff97 + xkKeypadRight = 0xff98 + xkKeypadDown = 0xff99 + xkKeypadPageUp = 0xff9a + xkKeypadPageDown = 0xff9b + xkKeypadEnd = 0xff9c + xkKeypadInsert = 0xff9e + xkKeypadDelete = 0xff9f + xkKeypadEqual = 0xffbd + xkKeypadMultiply = 0xffaa + xkKeypadAdd = 0xffab + xkKeypadSubtract = 0xffad + xkKeypadDecimal = 0xffae + xkKeypadDivide = 0xffaf + xkKeypad0 = 0xffb0 + xkKeypad1 = 0xffb1 + xkKeypad2 = 0xffb2 + xkKeypad3 = 0xffb3 + xkKeypad4 = 0xffb4 + xkKeypad5 = 0xffb5 + xkKeypad6 = 0xffb6 + xkKeypad7 = 0xffb7 + xkKeypad8 = 0xffb8 + xkKeypad9 = 0xffb9 + + xkF1 = 0xffbe + xkF2 = 0xffbf + xkF3 = 0xffc0 + xkF4 = 0xffc1 + xkF5 = 0xffc2 + xkF6 = 0xffc3 + xkF7 = 0xffc4 + xkF8 = 0xffc5 + xkF9 = 0xffc6 + xkF10 = 0xffc7 + xkF11 = 0xffc8 + xkF12 = 0xffc9 + xkShiftL = 0xffe1 + xkShiftR = 0xffe2 + xkControlL = 0xffe3 + xkControlR = 0xffe4 + xkCapsLock = 0xffe5 + xkAltL = 0xffe9 + xkAltR = 0xffea + xkSuperL = 0xffeb + xkSuperR = 0xffec + xkDelete = 0xffff + + xf86xkAudioLowerVolume = 0x1008ff11 + xf86xkAudioMute = 0x1008ff12 + xf86xkAudioRaiseVolume = 0x1008ff13 +) + +// nonUnicodeKeycodes maps from those xproto.Keysym values (converted to runes) +// that do not correspond to a Unicode code point, such as "Page Up", "F1" or +// "Left Shift", to key.Code values. +var nonUnicodeKeycodes = map[rune]key.Code{ + xkISOLeftTab: key.CodeTab, + xkBackSpace: key.CodeDeleteBackspace, + xkTab: key.CodeTab, + xkReturn: key.CodeReturnEnter, + xkEscape: key.CodeEscape, + xkHome: key.CodeHome, + xkLeft: key.CodeLeftArrow, + xkUp: key.CodeUpArrow, + xkRight: key.CodeRightArrow, + xkDown: key.CodeDownArrow, + xkPageUp: key.CodePageUp, + xkPageDown: key.CodePageDown, + xkEnd: key.CodeEnd, + xkInsert: key.CodeInsert, + xkMenu: key.CodeRightGUI, // TODO: CodeRightGUI or CodeMenu?? + xkHelp: key.CodeHelp, + xkNumLock: key.CodeKeypadNumLock, + xkMultiKey: key.CodeCompose, + + xkKeypadEnter: key.CodeKeypadEnter, + xkKeypadHome: key.CodeHome, + xkKeypadLeft: key.CodeLeftArrow, + xkKeypadUp: key.CodeUpArrow, + xkKeypadRight: key.CodeRightArrow, + xkKeypadDown: key.CodeDownArrow, + xkKeypadPageUp: key.CodePageUp, + xkKeypadPageDown: key.CodePageDown, + xkKeypadEnd: key.CodeEnd, + xkKeypadInsert: key.CodeInsert, + xkKeypadDelete: key.CodeDeleteForward, + + xkF1: key.CodeF1, + xkF2: key.CodeF2, + xkF3: key.CodeF3, + xkF4: key.CodeF4, + xkF5: key.CodeF5, + xkF6: key.CodeF6, + xkF7: key.CodeF7, + xkF8: key.CodeF8, + xkF9: key.CodeF9, + xkF10: key.CodeF10, + xkF11: key.CodeF11, + xkF12: key.CodeF12, + + xkShiftL: key.CodeLeftShift, + xkShiftR: key.CodeRightShift, + xkControlL: key.CodeLeftControl, + xkControlR: key.CodeRightControl, + xkCapsLock: key.CodeCapsLock, + xkAltL: key.CodeLeftAlt, + xkAltR: key.CodeRightAlt, + xkSuperL: key.CodeLeftGUI, + xkSuperR: key.CodeRightGUI, + + xkDelete: key.CodeDeleteForward, + + xf86xkAudioRaiseVolume: key.CodeVolumeUp, + xf86xkAudioLowerVolume: key.CodeVolumeDown, + xf86xkAudioMute: key.CodeMute, +} + +// asciiKeycodes maps lower-case ASCII runes to key.Code values. +var asciiKeycodes = [0x80]key.Code{ + 'a': key.CodeA, + 'b': key.CodeB, + 'c': key.CodeC, + 'd': key.CodeD, + 'e': key.CodeE, + 'f': key.CodeF, + 'g': key.CodeG, + 'h': key.CodeH, + 'i': key.CodeI, + 'j': key.CodeJ, + 'k': key.CodeK, + 'l': key.CodeL, + 'm': key.CodeM, + 'n': key.CodeN, + 'o': key.CodeO, + 'p': key.CodeP, + 'q': key.CodeQ, + 'r': key.CodeR, + 's': key.CodeS, + 't': key.CodeT, + 'u': key.CodeU, + 'v': key.CodeV, + 'w': key.CodeW, + 'x': key.CodeX, + 'y': key.CodeY, + 'z': key.CodeZ, + + '1': key.Code1, + '2': key.Code2, + '3': key.Code3, + '4': key.Code4, + '5': key.Code5, + '6': key.Code6, + '7': key.Code7, + '8': key.Code8, + '9': key.Code9, + '0': key.Code0, + + ' ': key.CodeSpacebar, + '-': key.CodeHyphenMinus, + '=': key.CodeEqualSign, + '[': key.CodeLeftSquareBracket, + ']': key.CodeRightSquareBracket, + '\\': key.CodeBackslash, + ';': key.CodeSemicolon, + '\'': key.CodeApostrophe, + '`': key.CodeGraveAccent, + ',': key.CodeComma, + '.': key.CodeFullStop, + '/': key.CodeSlash, +} + +type keypadKeysym struct { + rune rune + code key.Code +} + +var keypadKeysyms = map[rune]keypadKeysym{ + xkKeypadEqual: {'=', key.CodeKeypadEqualSign}, + xkKeypadMultiply: {'*', key.CodeKeypadAsterisk}, + xkKeypadAdd: {'+', key.CodeKeypadPlusSign}, + xkKeypadSubtract: {'-', key.CodeKeypadHyphenMinus}, + xkKeypadDecimal: {'.', key.CodeKeypadFullStop}, + xkKeypadDivide: {'/', key.CodeKeypadSlash}, + xkKeypad0: {'0', key.CodeKeypad0}, + xkKeypad1: {'1', key.CodeKeypad1}, + xkKeypad2: {'2', key.CodeKeypad2}, + xkKeypad3: {'3', key.CodeKeypad3}, + xkKeypad4: {'4', key.CodeKeypad4}, + xkKeypad5: {'5', key.CodeKeypad5}, + xkKeypad6: {'6', key.CodeKeypad6}, + xkKeypad7: {'7', key.CodeKeypad7}, + xkKeypad8: {'8', key.CodeKeypad8}, + xkKeypad9: {'9', key.CodeKeypad9}, +} diff --git a/vendor/golang.org/x/exp/shiny/screen/screen.go b/vendor/golang.org/x/exp/shiny/screen/screen.go new file mode 100644 index 00000000..5d89fe8c --- /dev/null +++ b/vendor/golang.org/x/exp/shiny/screen/screen.go @@ -0,0 +1,354 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package screen provides interfaces for portable two-dimensional graphics and +// input events. +// +// Screens are not created directly. Instead, driver packages provide access to +// the screen through a Main function that is designed to be called by the +// program's main function. The golang.org/x/exp/shiny/driver package provides +// the default driver for the system, such as the X11 driver for desktop Linux, +// but other drivers, such as the OpenGL driver, can be explicitly invoked by +// calling that driver's Main function. To use the default driver: +// +// package main +// +// import ( +// "golang.org/x/exp/shiny/driver" +// "golang.org/x/exp/shiny/screen" +// "golang.org/x/mobile/event/lifecycle" +// ) +// +// func main() { +// driver.Main(func(s screen.Screen) { +// w, err := s.NewWindow(nil) +// if err != nil { +// handleError(err) +// return +// } +// defer w.Release() +// +// for { +// switch e := w.NextEvent().(type) { +// case lifecycle.Event: +// if e.To == lifecycle.StageDead { +// return +// } +// etc +// case etc: +// etc +// } +// } +// }) +// } +// +// Complete examples can be found in the shiny/example directory. +// +// Each driver package provides Screen, Buffer, Texture and Window +// implementations that work together. Such types are interface types because +// this package is driver-independent, but those interfaces aren't expected to +// be implemented outside of drivers. For example, a driver's Window +// implementation will generally work only with that driver's Buffer +// implementation, and will not work with an arbitrary type that happens to +// implement the Buffer methods. +package screen // import "golang.org/x/exp/shiny/screen" + +import ( + "image" + "image/color" + "image/draw" + "unicode/utf8" + + "golang.org/x/image/math/f64" +) + +// TODO: specify image format (Alpha or Gray, not just RGBA) for NewBuffer +// and/or NewTexture? + +// Screen creates Buffers, Textures and Windows. +type Screen interface { + // NewBuffer returns a new Buffer for this screen. + NewBuffer(size image.Point) (Buffer, error) + + // NewTexture returns a new Texture for this screen. + NewTexture(size image.Point) (Texture, error) + + // NewWindow returns a new Window for this screen. + // + // A nil opts is valid and means to use the default option values. + NewWindow(opts *NewWindowOptions) (Window, error) +} + +// TODO: rename Buffer to Image, to be less confusing with a Window's back and +// front buffers. + +// Buffer is an in-memory pixel buffer. Its pixels can be modified by any Go +// code that takes an *image.RGBA, such as the standard library's image/draw +// package. A Buffer is essentially an *image.RGBA, but not all *image.RGBA +// values (including those returned by image.NewRGBA) are valid Buffers, as a +// driver may assume that the memory backing a Buffer's pixels are specially +// allocated. +// +// To see a Buffer's contents on a screen, upload it to a Texture (and then +// draw the Texture on a Window) or upload it directly to a Window. +// +// When specifying a sub-Buffer via Upload, a Buffer's top-left pixel is always +// (0, 0) in its own coordinate space. +type Buffer interface { + // Release releases the Buffer's resources, after all pending uploads and + // draws resolve. + // + // The behavior of the Buffer after Release, whether calling its methods or + // passing it as an argument, is undefined. + Release() + + // Size returns the size of the Buffer's image. + Size() image.Point + + // Bounds returns the bounds of the Buffer's image. It is equal to + // image.Rectangle{Max: b.Size()}. + Bounds() image.Rectangle + + // RGBA returns the pixel buffer as an *image.RGBA. + // + // Its contents should not be accessed while the Buffer is uploading. + // + // The contents of the returned *image.RGBA's Pix field (of type []byte) + // can be modified at other times, but that Pix slice itself (i.e. its + // underlying pointer, length and capacity) should not be modified at any + // time. + // + // The following is valid: + // m := buffer.RGBA() + // if len(m.Pix) >= 4 { + // m.Pix[0] = 0xff + // m.Pix[1] = 0x00 + // m.Pix[2] = 0x00 + // m.Pix[3] = 0xff + // } + // or, equivalently: + // m := buffer.RGBA() + // m.SetRGBA(m.Rect.Min.X, m.Rect.Min.Y, color.RGBA{0xff, 0x00, 0x00, 0xff}) + // and using the standard library's image/draw package is also valid: + // dst := buffer.RGBA() + // draw.Draw(dst, dst.Bounds(), etc) + // but the following is invalid: + // m := buffer.RGBA() + // m.Pix = anotherByteSlice + // and so is this: + // *buffer.RGBA() = anotherImageRGBA + RGBA() *image.RGBA +} + +// Texture is a pixel buffer, but not one that is directly accessible as a +// []byte. Conceptually, it could live on a GPU, in another process or even be +// across a network, instead of on a CPU in this process. +// +// Buffers can be uploaded to Textures, and Textures can be drawn on Windows. +// +// When specifying a sub-Texture via Draw, a Texture's top-left pixel is always +// (0, 0) in its own coordinate space. +type Texture interface { + // Release releases the Texture's resources, after all pending uploads and + // draws resolve. + // + // The behavior of the Texture after Release, whether calling its methods + // or passing it as an argument, is undefined. + Release() + + // Size returns the size of the Texture's image. + Size() image.Point + + // Bounds returns the bounds of the Texture's image. It is equal to + // image.Rectangle{Max: t.Size()}. + Bounds() image.Rectangle + + Uploader + + // TODO: also implement Drawer? If so, merge the Uploader and Drawer + // interfaces?? +} + +// EventDeque is an infinitely buffered double-ended queue of events. +type EventDeque interface { + // Send adds an event to the end of the deque. They are returned by + // NextEvent in FIFO order. + Send(event interface{}) + + // SendFirst adds an event to the start of the deque. They are returned by + // NextEvent in LIFO order, and have priority over events sent via Send. + SendFirst(event interface{}) + + // NextEvent returns the next event in the deque. It blocks until such an + // event has been sent. + // + // Typical event types include: + // - lifecycle.Event + // - size.Event + // - paint.Event + // - key.Event + // - mouse.Event + // - touch.Event + // from the golang.org/x/mobile/event/... packages. Other packages may send + // events, of those types above or of other types, via Send or SendFirst. + NextEvent() interface{} + + // TODO: LatestLifecycleEvent? Is that still worth it if the + // lifecycle.Event struct type loses its DrawContext field? + + // TODO: LatestSizeEvent? +} + +// Window is a top-level, double-buffered GUI window. +type Window interface { + // Release closes the window. + // + // The behavior of the Window after Release, whether calling its methods or + // passing it as an argument, is undefined. + Release() + + EventDeque + + Uploader + + Drawer + + // Publish flushes any pending Upload and Draw calls to the window, and + // swaps the back buffer to the front. + Publish() PublishResult +} + +// PublishResult is the result of an Window.Publish call. +type PublishResult struct { + // BackBufferPreserved is whether the contents of the back buffer was + // preserved. If false, the contents are undefined. + BackBufferPreserved bool +} + +// NewWindowOptions are optional arguments to NewWindow. +type NewWindowOptions struct { + // Width and Height specify the dimensions of the new window. If Width + // or Height are zero, a driver-dependent default will be used for each + // zero value dimension. + Width, Height int + + // Title specifies the window title. + Title string + + // TODO: fullscreen, icon, cursorHidden? +} + +// GetTitle returns a sanitized form of o.Title. In particular, its length will +// not exceed 4096, and it may be further truncated so that it is valid UTF-8 +// and will not contain the NUL byte. +// +// o may be nil, in which case "" is returned. +func (o *NewWindowOptions) GetTitle() string { + if o == nil { + return "" + } + return sanitizeUTF8(o.Title, 4096) +} + +func sanitizeUTF8(s string, n int) string { + if n < len(s) { + s = s[:n] + } + i := 0 + for i < len(s) { + r, n := utf8.DecodeRuneInString(s[i:]) + if r == 0 || (r == utf8.RuneError && n == 1) { + break + } + i += n + } + return s[:i] +} + +// Uploader is something you can upload a Buffer to. +type Uploader interface { + // Upload uploads the sub-Buffer defined by src and sr to the destination + // (the method receiver), such that sr.Min in src-space aligns with dp in + // dst-space. The destination's contents are overwritten; the draw operator + // is implicitly draw.Src. + // + // It is valid to upload a Buffer while another upload of the same Buffer + // is in progress, but a Buffer's image.RGBA pixel contents should not be + // accessed while it is uploading. A Buffer is re-usable, in that its pixel + // contents can be further modified, once all outstanding calls to Upload + // have returned. + // + // TODO: make it optional that a Buffer's contents is preserved after + // Upload? Undoing a swizzle is a non-trivial amount of work, and can be + // redundant if the next paint cycle starts by clearing the buffer. + // + // When uploading to a Window, there will not be any visible effect until + // Publish is called. + Upload(dp image.Point, src Buffer, sr image.Rectangle) + + // Fill fills that part of the destination (the method receiver) defined by + // dr with the given color. + // + // When filling a Window, there will not be any visible effect until + // Publish is called. + Fill(dr image.Rectangle, src color.Color, op draw.Op) +} + +// TODO: have a Downloader interface? Not every graphical app needs to be +// interactive or involve a window. You could use the GPU for hardware- +// accelerated image manipulation: upload a buffer, do some texture ops, then +// download the result. + +// Drawer is something you can draw Textures on. +// +// Draw is the most general purpose of this interface's methods. It supports +// arbitrary affine transformations, such as translations, scales and +// rotations. +// +// Copy and Scale are more specific versions of Draw. The affected dst pixels +// are an axis-aligned rectangle, quantized to the pixel grid. Copy copies +// pixels in a 1:1 manner, Scale is more general. They have simpler parameters +// than Draw, using ints instead of float64s. +// +// When drawing on a Window, there will not be any visible effect until Publish +// is called. +type Drawer interface { + // Draw draws the sub-Texture defined by src and sr to the destination (the + // method receiver). src2dst defines how to transform src coordinates to + // dst coordinates. For example, if src2dst is the matrix + // + // m00 m01 m02 + // m10 m11 m12 + // + // then the src-space point (sx, sy) maps to the dst-space point + // (m00*sx + m01*sy + m02, m10*sx + m11*sy + m12). + Draw(src2dst f64.Aff3, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions) + + // DrawUniform is like Draw except that the src is a uniform color instead + // of a Texture. + DrawUniform(src2dst f64.Aff3, src color.Color, sr image.Rectangle, op draw.Op, opts *DrawOptions) + + // Copy copies the sub-Texture defined by src and sr to the destination + // (the method receiver), such that sr.Min in src-space aligns with dp in + // dst-space. + Copy(dp image.Point, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions) + + // Scale scales the sub-Texture defined by src and sr to the destination + // (the method receiver), such that sr in src-space is mapped to dr in + // dst-space. + Scale(dr image.Rectangle, src Texture, sr image.Rectangle, op draw.Op, opts *DrawOptions) +} + +// These draw.Op constants are provided so that users of this package don't +// have to explicitly import "image/draw". +const ( + Over = draw.Over + Src = draw.Src +) + +// DrawOptions are optional arguments to Draw. +type DrawOptions struct { + // TODO: transparency in [0x0000, 0xffff]? + // TODO: scaler (nearest neighbor vs linear)? +} diff --git a/vendor/golang.org/x/image/LICENSE b/vendor/golang.org/x/image/LICENSE new file mode 100644 index 00000000..2a7cf70d --- /dev/null +++ b/vendor/golang.org/x/image/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/image/PATENTS b/vendor/golang.org/x/image/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/golang.org/x/image/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/image/bmp/reader.go b/vendor/golang.org/x/image/bmp/reader.go new file mode 100644 index 00000000..1939c112 --- /dev/null +++ b/vendor/golang.org/x/image/bmp/reader.go @@ -0,0 +1,253 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package bmp implements a BMP image decoder and encoder. +// +// The BMP specification is at http://www.digicamsoft.com/bmp/bmp.html. +package bmp // import "golang.org/x/image/bmp" + +import ( + "errors" + "image" + "image/color" + "io" +) + +// ErrUnsupported means that the input BMP image uses a valid but unsupported +// feature. +var ErrUnsupported = errors.New("bmp: unsupported BMP image") + +func readUint16(b []byte) uint16 { + return uint16(b[0]) | uint16(b[1])<<8 +} + +func readUint32(b []byte) uint32 { + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 +} + +// decodePaletted reads an 8 bit-per-pixel BMP image from r. +// If topDown is false, the image rows will be read bottom-up. +func decodePaletted(r io.Reader, c image.Config, topDown bool) (image.Image, error) { + paletted := image.NewPaletted(image.Rect(0, 0, c.Width, c.Height), c.ColorModel.(color.Palette)) + if c.Width == 0 || c.Height == 0 { + return paletted, nil + } + var tmp [4]byte + y0, y1, yDelta := c.Height-1, -1, -1 + if topDown { + y0, y1, yDelta = 0, c.Height, +1 + } + for y := y0; y != y1; y += yDelta { + p := paletted.Pix[y*paletted.Stride : y*paletted.Stride+c.Width] + if _, err := io.ReadFull(r, p); err != nil { + return nil, err + } + // Each row is 4-byte aligned. + if c.Width%4 != 0 { + _, err := io.ReadFull(r, tmp[:4-c.Width%4]) + if err != nil { + return nil, err + } + } + } + return paletted, nil +} + +// decodeRGB reads a 24 bit-per-pixel BMP image from r. +// If topDown is false, the image rows will be read bottom-up. +func decodeRGB(r io.Reader, c image.Config, topDown bool) (image.Image, error) { + rgba := image.NewRGBA(image.Rect(0, 0, c.Width, c.Height)) + if c.Width == 0 || c.Height == 0 { + return rgba, nil + } + // There are 3 bytes per pixel, and each row is 4-byte aligned. + b := make([]byte, (3*c.Width+3)&^3) + y0, y1, yDelta := c.Height-1, -1, -1 + if topDown { + y0, y1, yDelta = 0, c.Height, +1 + } + for y := y0; y != y1; y += yDelta { + if _, err := io.ReadFull(r, b); err != nil { + return nil, err + } + p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4] + for i, j := 0, 0; i < len(p); i, j = i+4, j+3 { + // BMP images are stored in BGR order rather than RGB order. + p[i+0] = b[j+2] + p[i+1] = b[j+1] + p[i+2] = b[j+0] + p[i+3] = 0xFF + } + } + return rgba, nil +} + +// decodeNRGBA reads a 32 bit-per-pixel BMP image from r. +// If topDown is false, the image rows will be read bottom-up. +func decodeNRGBA(r io.Reader, c image.Config, topDown, allowAlpha bool) (image.Image, error) { + rgba := image.NewNRGBA(image.Rect(0, 0, c.Width, c.Height)) + if c.Width == 0 || c.Height == 0 { + return rgba, nil + } + y0, y1, yDelta := c.Height-1, -1, -1 + if topDown { + y0, y1, yDelta = 0, c.Height, +1 + } + for y := y0; y != y1; y += yDelta { + p := rgba.Pix[y*rgba.Stride : y*rgba.Stride+c.Width*4] + if _, err := io.ReadFull(r, p); err != nil { + return nil, err + } + for i := 0; i < len(p); i += 4 { + // BMP images are stored in BGRA order rather than RGBA order. + p[i+0], p[i+2] = p[i+2], p[i+0] + if !allowAlpha { + p[i+3] = 0xFF + } + } + } + return rgba, nil +} + +// Decode reads a BMP image from r and returns it as an image.Image. +// Limitation: The file must be 8, 24 or 32 bits per pixel. +func Decode(r io.Reader) (image.Image, error) { + c, bpp, topDown, allowAlpha, err := decodeConfig(r) + if err != nil { + return nil, err + } + switch bpp { + case 8: + return decodePaletted(r, c, topDown) + case 24: + return decodeRGB(r, c, topDown) + case 32: + return decodeNRGBA(r, c, topDown, allowAlpha) + } + panic("unreachable") +} + +// DecodeConfig returns the color model and dimensions of a BMP image without +// decoding the entire image. +// Limitation: The file must be 8, 24 or 32 bits per pixel. +func DecodeConfig(r io.Reader) (image.Config, error) { + config, _, _, _, err := decodeConfig(r) + return config, err +} + +func decodeConfig(r io.Reader) (config image.Config, bitsPerPixel int, topDown bool, allowAlpha bool, err error) { + // We only support those BMP images with one of the following DIB headers: + // - BITMAPINFOHEADER (40 bytes) + // - BITMAPV4HEADER (108 bytes) + // - BITMAPV5HEADER (124 bytes) + const ( + fileHeaderLen = 14 + infoHeaderLen = 40 + v4InfoHeaderLen = 108 + v5InfoHeaderLen = 124 + ) + var b [1024]byte + if _, err := io.ReadFull(r, b[:fileHeaderLen+4]); err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return image.Config{}, 0, false, false, err + } + if string(b[:2]) != "BM" { + return image.Config{}, 0, false, false, errors.New("bmp: invalid format") + } + offset := readUint32(b[10:14]) + infoLen := readUint32(b[14:18]) + if infoLen != infoHeaderLen && infoLen != v4InfoHeaderLen && infoLen != v5InfoHeaderLen { + return image.Config{}, 0, false, false, ErrUnsupported + } + if _, err := io.ReadFull(r, b[fileHeaderLen+4:fileHeaderLen+infoLen]); err != nil { + if err == io.EOF { + err = io.ErrUnexpectedEOF + } + return image.Config{}, 0, false, false, err + } + width := int(int32(readUint32(b[18:22]))) + height := int(int32(readUint32(b[22:26]))) + if height < 0 { + height, topDown = -height, true + } + if width < 0 || height < 0 { + return image.Config{}, 0, false, false, ErrUnsupported + } + // We only support 1 plane and 8, 24 or 32 bits per pixel and no + // compression. + planes, bpp, compression := readUint16(b[26:28]), readUint16(b[28:30]), readUint32(b[30:34]) + // if compression is set to BI_BITFIELDS, but the bitmask is set to the default bitmask + // that would be used if compression was set to 0, we can continue as if compression was 0 + if compression == 3 && infoLen > infoHeaderLen && + readUint32(b[54:58]) == 0xff0000 && readUint32(b[58:62]) == 0xff00 && + readUint32(b[62:66]) == 0xff && readUint32(b[66:70]) == 0xff000000 { + compression = 0 + } + if planes != 1 || compression != 0 { + return image.Config{}, 0, false, false, ErrUnsupported + } + switch bpp { + case 8: + colorUsed := readUint32(b[46:50]) + // If colorUsed is 0, it is set to the maximum number of colors for the given bpp, which is 2^bpp. + if colorUsed == 0 { + colorUsed = 256 + } else if colorUsed > 256 { + return image.Config{}, 0, false, false, ErrUnsupported + } + + if offset != fileHeaderLen+infoLen+colorUsed*4 { + return image.Config{}, 0, false, false, ErrUnsupported + } + _, err = io.ReadFull(r, b[:colorUsed*4]) + if err != nil { + return image.Config{}, 0, false, false, err + } + pcm := make(color.Palette, colorUsed) + for i := range pcm { + // BMP images are stored in BGR order rather than RGB order. + // Every 4th byte is padding. + pcm[i] = color.RGBA{b[4*i+2], b[4*i+1], b[4*i+0], 0xFF} + } + return image.Config{ColorModel: pcm, Width: width, Height: height}, 8, topDown, false, nil + case 24: + if offset != fileHeaderLen+infoLen { + return image.Config{}, 0, false, false, ErrUnsupported + } + return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 24, topDown, false, nil + case 32: + if offset != fileHeaderLen+infoLen { + return image.Config{}, 0, false, false, ErrUnsupported + } + // 32 bits per pixel is possibly RGBX (X is padding) or RGBA (A is + // alpha transparency). However, for BMP images, "Alpha is a + // poorly-documented and inconsistently-used feature" says + // https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=621 + // + // That goes on to say "BITMAPV3HEADER+ have an alpha bitmask in the + // info header... so we respect it at all times... [For earlier + // (smaller) headers we] ignore alpha in Windows V3 BMPs except inside + // ICO files". + // + // "Ignore" means to always set alpha to 0xFF (fully opaque): + // https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.h;l=272 + // + // Confusingly, "Windows V3" does not correspond to BITMAPV3HEADER, but + // instead corresponds to the earlier (smaller) BITMAPINFOHEADER: + // https://source.chromium.org/chromium/chromium/src/+/bc0a792d7ebc587190d1a62ccddba10abeea274b:third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_reader.cc;l=258 + // + // This Go package does not support ICO files and the (infoLen > + // infoHeaderLen) condition distinguishes BITMAPINFOHEADER (40 bytes) + // vs later (larger) headers. + allowAlpha = infoLen > infoHeaderLen + return image.Config{ColorModel: color.RGBAModel, Width: width, Height: height}, 32, topDown, allowAlpha, nil + } + return image.Config{}, 0, false, false, ErrUnsupported +} + +func init() { + image.RegisterFormat("bmp", "BM????\x00\x00\x00\x00", Decode, DecodeConfig) +} diff --git a/vendor/golang.org/x/image/bmp/writer.go b/vendor/golang.org/x/image/bmp/writer.go new file mode 100644 index 00000000..f07b39db --- /dev/null +++ b/vendor/golang.org/x/image/bmp/writer.go @@ -0,0 +1,262 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package bmp + +import ( + "encoding/binary" + "errors" + "image" + "io" +) + +type header struct { + sigBM [2]byte + fileSize uint32 + resverved [2]uint16 + pixOffset uint32 + dibHeaderSize uint32 + width uint32 + height uint32 + colorPlane uint16 + bpp uint16 + compression uint32 + imageSize uint32 + xPixelsPerMeter uint32 + yPixelsPerMeter uint32 + colorUse uint32 + colorImportant uint32 +} + +func encodePaletted(w io.Writer, pix []uint8, dx, dy, stride, step int) error { + var padding []byte + if dx < step { + padding = make([]byte, step-dx) + } + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx + if _, err := w.Write(pix[min:max]); err != nil { + return err + } + if padding != nil { + if _, err := w.Write(padding); err != nil { + return err + } + } + } + return nil +} + +func encodeRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error { + buf := make([]byte, step) + if opaque { + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + for i := min; i < max; i += 4 { + buf[off+2] = pix[i+0] + buf[off+1] = pix[i+1] + buf[off+0] = pix[i+2] + off += 3 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + } else { + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + for i := min; i < max; i += 4 { + a := uint32(pix[i+3]) + if a == 0 { + buf[off+2] = 0 + buf[off+1] = 0 + buf[off+0] = 0 + buf[off+3] = 0 + off += 4 + continue + } else if a == 0xff { + buf[off+2] = pix[i+0] + buf[off+1] = pix[i+1] + buf[off+0] = pix[i+2] + buf[off+3] = 0xff + off += 4 + continue + } + buf[off+2] = uint8(((uint32(pix[i+0]) * 0xffff) / a) >> 8) + buf[off+1] = uint8(((uint32(pix[i+1]) * 0xffff) / a) >> 8) + buf[off+0] = uint8(((uint32(pix[i+2]) * 0xffff) / a) >> 8) + buf[off+3] = uint8(a) + off += 4 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + } + return nil +} + +func encodeNRGBA(w io.Writer, pix []uint8, dx, dy, stride, step int, opaque bool) error { + buf := make([]byte, step) + if opaque { + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + for i := min; i < max; i += 4 { + buf[off+2] = pix[i+0] + buf[off+1] = pix[i+1] + buf[off+0] = pix[i+2] + off += 3 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + } else { + for y := dy - 1; y >= 0; y-- { + min := y*stride + 0 + max := y*stride + dx*4 + off := 0 + for i := min; i < max; i += 4 { + buf[off+2] = pix[i+0] + buf[off+1] = pix[i+1] + buf[off+0] = pix[i+2] + buf[off+3] = pix[i+3] + off += 4 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + } + return nil +} + +func encode(w io.Writer, m image.Image, step int) error { + b := m.Bounds() + buf := make([]byte, step) + for y := b.Max.Y - 1; y >= b.Min.Y; y-- { + off := 0 + for x := b.Min.X; x < b.Max.X; x++ { + r, g, b, _ := m.At(x, y).RGBA() + buf[off+2] = byte(r >> 8) + buf[off+1] = byte(g >> 8) + buf[off+0] = byte(b >> 8) + off += 3 + } + if _, err := w.Write(buf); err != nil { + return err + } + } + return nil +} + +// Encode writes the image m to w in BMP format. +func Encode(w io.Writer, m image.Image) error { + d := m.Bounds().Size() + if d.X < 0 || d.Y < 0 { + return errors.New("bmp: negative bounds") + } + h := &header{ + sigBM: [2]byte{'B', 'M'}, + fileSize: 14 + 40, + pixOffset: 14 + 40, + dibHeaderSize: 40, + width: uint32(d.X), + height: uint32(d.Y), + colorPlane: 1, + } + + var step int + var palette []byte + var opaque bool + switch m := m.(type) { + case *image.Gray: + step = (d.X + 3) &^ 3 + palette = make([]byte, 1024) + for i := 0; i < 256; i++ { + palette[i*4+0] = uint8(i) + palette[i*4+1] = uint8(i) + palette[i*4+2] = uint8(i) + palette[i*4+3] = 0xFF + } + h.imageSize = uint32(d.Y * step) + h.fileSize += uint32(len(palette)) + h.imageSize + h.pixOffset += uint32(len(palette)) + h.bpp = 8 + + case *image.Paletted: + step = (d.X + 3) &^ 3 + palette = make([]byte, 1024) + for i := 0; i < len(m.Palette) && i < 256; i++ { + r, g, b, _ := m.Palette[i].RGBA() + palette[i*4+0] = uint8(b >> 8) + palette[i*4+1] = uint8(g >> 8) + palette[i*4+2] = uint8(r >> 8) + palette[i*4+3] = 0xFF + } + h.imageSize = uint32(d.Y * step) + h.fileSize += uint32(len(palette)) + h.imageSize + h.pixOffset += uint32(len(palette)) + h.bpp = 8 + case *image.RGBA: + opaque = m.Opaque() + if opaque { + step = (3*d.X + 3) &^ 3 + h.bpp = 24 + } else { + step = 4 * d.X + h.bpp = 32 + } + h.imageSize = uint32(d.Y * step) + h.fileSize += h.imageSize + case *image.NRGBA: + opaque = m.Opaque() + if opaque { + step = (3*d.X + 3) &^ 3 + h.bpp = 24 + } else { + step = 4 * d.X + h.bpp = 32 + } + h.imageSize = uint32(d.Y * step) + h.fileSize += h.imageSize + default: + step = (3*d.X + 3) &^ 3 + h.imageSize = uint32(d.Y * step) + h.fileSize += h.imageSize + h.bpp = 24 + } + + if err := binary.Write(w, binary.LittleEndian, h); err != nil { + return err + } + if palette != nil { + if err := binary.Write(w, binary.LittleEndian, palette); err != nil { + return err + } + } + + if d.X == 0 || d.Y == 0 { + return nil + } + + switch m := m.(type) { + case *image.Gray: + return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step) + case *image.Paletted: + return encodePaletted(w, m.Pix, d.X, d.Y, m.Stride, step) + case *image.RGBA: + return encodeRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque) + case *image.NRGBA: + return encodeNRGBA(w, m.Pix, d.X, d.Y, m.Stride, step, opaque) + } + return encode(w, m, step) +} diff --git a/vendor/golang.org/x/image/math/f64/f64.go b/vendor/golang.org/x/image/math/f64/f64.go new file mode 100644 index 00000000..a1f7fc0e --- /dev/null +++ b/vendor/golang.org/x/image/math/f64/f64.go @@ -0,0 +1,37 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package f64 implements float64 vector and matrix types. +package f64 // import "golang.org/x/image/math/f64" + +// Vec2 is a 2-element vector. +type Vec2 [2]float64 + +// Vec3 is a 3-element vector. +type Vec3 [3]float64 + +// Vec4 is a 4-element vector. +type Vec4 [4]float64 + +// Mat3 is a 3x3 matrix in row major order. +// +// m[3*r + c] is the element in the r'th row and c'th column. +type Mat3 [9]float64 + +// Mat4 is a 4x4 matrix in row major order. +// +// m[4*r + c] is the element in the r'th row and c'th column. +type Mat4 [16]float64 + +// Aff3 is a 3x3 affine transformation matrix in row major order, where the +// bottom row is implicitly [0 0 1]. +// +// m[3*r + c] is the element in the r'th row and c'th column. +type Aff3 [6]float64 + +// Aff4 is a 4x4 affine transformation matrix in row major order, where the +// bottom row is implicitly [0 0 0 1]. +// +// m[4*r + c] is the element in the r'th row and c'th column. +type Aff4 [12]float64 diff --git a/vendor/golang.org/x/mobile/LICENSE b/vendor/golang.org/x/mobile/LICENSE new file mode 100644 index 00000000..2a7cf70d --- /dev/null +++ b/vendor/golang.org/x/mobile/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/mobile/PATENTS b/vendor/golang.org/x/mobile/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/golang.org/x/mobile/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/mobile/app/GoNativeActivity.java b/vendor/golang.org/x/mobile/app/GoNativeActivity.java new file mode 100644 index 00000000..e829c8c4 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/GoNativeActivity.java @@ -0,0 +1,67 @@ +package org.golang.app; + +import android.app.Activity; +import android.app.NativeActivity; +import android.content.Context; +import android.content.pm.ActivityInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; +import android.util.Log; +import android.view.KeyCharacterMap; + +public class GoNativeActivity extends NativeActivity { + private static GoNativeActivity goNativeActivity; + + public GoNativeActivity() { + super(); + goNativeActivity = this; + } + + String getTmpdir() { + return getCacheDir().getAbsolutePath(); + } + + static int getRune(int deviceId, int keyCode, int metaState) { + try { + int rune = KeyCharacterMap.load(deviceId).get(keyCode, metaState); + if (rune == 0) { + return -1; + } + return rune; + } catch (KeyCharacterMap.UnavailableException e) { + return -1; + } catch (Exception e) { + Log.e("Go", "exception reading KeyCharacterMap", e); + return -1; + } + } + + private void load() { + // Interestingly, NativeActivity uses a different method + // to find native code to execute, avoiding + // System.loadLibrary. The result is Java methods + // implemented in C with JNIEXPORT (and JNI_OnLoad) are not + // available unless an explicit call to System.loadLibrary + // is done. So we do it here, borrowing the name of the + // library from the same AndroidManifest.xml metadata used + // by NativeActivity. + try { + ActivityInfo ai = getPackageManager().getActivityInfo( + getIntent().getComponent(), PackageManager.GET_META_DATA); + if (ai.metaData == null) { + Log.e("Go", "loadLibrary: no manifest metadata found"); + return; + } + String libName = ai.metaData.getString("android.app.lib_name"); + System.loadLibrary(libName); + } catch (Exception e) { + Log.e("Go", "loadLibrary failed", e); + } + } + + @Override + public void onCreate(Bundle savedInstanceState) { + load(); + super.onCreate(savedInstanceState); + } +} diff --git a/vendor/golang.org/x/mobile/app/android.c b/vendor/golang.org/x/mobile/app/android.c new file mode 100644 index 00000000..305d586a --- /dev/null +++ b/vendor/golang.org/x/mobile/app/android.c @@ -0,0 +1,201 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build android +// +build android + +#include +#include +#include +#include +#include +#include +#include "_cgo_export.h" + +#define LOG_INFO(...) __android_log_print(ANDROID_LOG_INFO, "Go", __VA_ARGS__) +#define LOG_FATAL(...) __android_log_print(ANDROID_LOG_FATAL, "Go", __VA_ARGS__) + +static jclass current_class; + +static jclass find_class(JNIEnv *env, const char *class_name) { + jclass clazz = (*env)->FindClass(env, class_name); + if (clazz == NULL) { + (*env)->ExceptionClear(env); + LOG_FATAL("cannot find %s", class_name); + return NULL; + } + return clazz; +} + +static jmethodID find_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) { + jmethodID m = (*env)->GetMethodID(env, clazz, name, sig); + if (m == 0) { + (*env)->ExceptionClear(env); + LOG_FATAL("cannot find method %s %s", name, sig); + return 0; + } + return m; +} + +static jmethodID find_static_method(JNIEnv *env, jclass clazz, const char *name, const char *sig) { + jmethodID m = (*env)->GetStaticMethodID(env, clazz, name, sig); + if (m == 0) { + (*env)->ExceptionClear(env); + LOG_FATAL("cannot find method %s %s", name, sig); + return 0; + } + return m; +} + +static jmethodID key_rune_method; + +jint JNI_OnLoad(JavaVM* vm, void* reserved) { + JNIEnv* env; + if ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) { + return -1; + } + + return JNI_VERSION_1_6; +} + +static int main_running = 0; + +// Entry point from our subclassed NativeActivity. +// +// By here, the Go runtime has been initialized (as we are running in +// -buildmode=c-shared) but the first time it is called, Go's main.main +// hasn't been called yet. +// +// The Activity may be created and destroyed multiple times throughout +// the life of a single process. Each time, onCreate is called. +void ANativeActivity_onCreate(ANativeActivity *activity, void* savedState, size_t savedStateSize) { + if (!main_running) { + JNIEnv* env = activity->env; + + // Note that activity->clazz is mis-named. + current_class = (*env)->GetObjectClass(env, activity->clazz); + current_class = (*env)->NewGlobalRef(env, current_class); + key_rune_method = find_static_method(env, current_class, "getRune", "(III)I"); + + setCurrentContext(activity->vm, (*env)->NewGlobalRef(env, activity->clazz)); + + // Set TMPDIR. + jmethodID gettmpdir = find_method(env, current_class, "getTmpdir", "()Ljava/lang/String;"); + jstring jpath = (jstring)(*env)->CallObjectMethod(env, activity->clazz, gettmpdir, NULL); + const char* tmpdir = (*env)->GetStringUTFChars(env, jpath, NULL); + if (setenv("TMPDIR", tmpdir, 1) != 0) { + LOG_INFO("setenv(\"TMPDIR\", \"%s\", 1) failed: %d", tmpdir, errno); + } + (*env)->ReleaseStringUTFChars(env, jpath, tmpdir); + + // Call the Go main.main. + uintptr_t mainPC = (uintptr_t)dlsym(RTLD_DEFAULT, "main.main"); + if (!mainPC) { + LOG_FATAL("missing main.main"); + } + callMain(mainPC); + main_running = 1; + } + + // These functions match the methods on Activity, described at + // http://developer.android.com/reference/android/app/Activity.html + // + // Note that onNativeWindowResized is not called on resize. Avoid it. + // https://code.google.com/p/android/issues/detail?id=180645 + activity->callbacks->onStart = onStart; + activity->callbacks->onResume = onResume; + activity->callbacks->onSaveInstanceState = onSaveInstanceState; + activity->callbacks->onPause = onPause; + activity->callbacks->onStop = onStop; + activity->callbacks->onDestroy = onDestroy; + activity->callbacks->onWindowFocusChanged = onWindowFocusChanged; + activity->callbacks->onNativeWindowCreated = onNativeWindowCreated; + activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded; + activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed; + activity->callbacks->onInputQueueCreated = onInputQueueCreated; + activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed; + activity->callbacks->onConfigurationChanged = onConfigurationChanged; + activity->callbacks->onLowMemory = onLowMemory; + + onCreate(activity); +} + +// TODO(crawshaw): Test configuration on more devices. +static const EGLint RGB_888[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_NONE +}; + +EGLDisplay display = NULL; +EGLSurface surface = NULL; + +static char* initEGLDisplay() { + display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (!eglInitialize(display, 0, 0)) { + return "EGL initialize failed"; + } + return NULL; +} + +char* createEGLSurface(ANativeWindow* window) { + char* err; + EGLint numConfigs, format; + EGLConfig config; + EGLContext context; + + if (display == 0) { + if ((err = initEGLDisplay()) != NULL) { + return err; + } + } + + if (!eglChooseConfig(display, RGB_888, &config, 1, &numConfigs)) { + return "EGL choose RGB_888 config failed"; + } + if (numConfigs <= 0) { + return "EGL no config found"; + } + + eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format); + if (ANativeWindow_setBuffersGeometry(window, 0, 0, format) != 0) { + return "EGL set buffers geometry failed"; + } + + surface = eglCreateWindowSurface(display, config, window, NULL); + if (surface == EGL_NO_SURFACE) { + return "EGL create surface failed"; + } + + const EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs); + + if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) { + return "eglMakeCurrent failed"; + } + return NULL; +} + +char* destroyEGLSurface() { + if (!eglDestroySurface(display, surface)) { + return "EGL destroy surface failed"; + } + return NULL; +} + +int32_t getKeyRune(JNIEnv* env, AInputEvent* e) { + return (int32_t)(*env)->CallStaticIntMethod( + env, + current_class, + key_rune_method, + AInputEvent_getDeviceId(e), + AKeyEvent_getKeyCode(e), + AKeyEvent_getMetaState(e) + ); +} diff --git a/vendor/golang.org/x/mobile/app/android.go b/vendor/golang.org/x/mobile/app/android.go new file mode 100644 index 00000000..5ee5605e --- /dev/null +++ b/vendor/golang.org/x/mobile/app/android.go @@ -0,0 +1,824 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build android + +/* +Android Apps are built with -buildmode=c-shared. They are loaded by a +running Java process. + +Before any entry point is reached, a global constructor initializes the +Go runtime, calling all Go init functions. All cgo calls will block +until this is complete. Next JNI_OnLoad is called. When that is +complete, one of two entry points is called. + +All-Go apps built using NativeActivity enter at ANativeActivity_onCreate. + +Go libraries (for example, those built with gomobile bind) do not use +the app package initialization. +*/ + +package app + +/* +#cgo LDFLAGS: -landroid -llog -lEGL -lGLESv2 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EGLDisplay display; +extern EGLSurface surface; + + +char* createEGLSurface(ANativeWindow* window); +char* destroyEGLSurface(); +int32_t getKeyRune(JNIEnv* env, AInputEvent* e); +*/ +import "C" +import ( + "fmt" + "log" + "os" + "time" + "unsafe" + + "golang.org/x/mobile/app/internal/callfn" + "golang.org/x/mobile/event/key" + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/event/touch" + "golang.org/x/mobile/geom" + "golang.org/x/mobile/internal/mobileinit" +) + +// RunOnJVM runs fn on a new goroutine locked to an OS thread with a JNIEnv. +// +// RunOnJVM blocks until the call to fn is complete. Any Java +// exception or failure to attach to the JVM is returned as an error. +// +// The function fn takes vm, the current JavaVM*, +// env, the current JNIEnv*, and +// ctx, a jobject representing the global android.context.Context. +func RunOnJVM(fn func(vm, jniEnv, ctx uintptr) error) error { + return mobileinit.RunOnJVM(fn) +} + +//export setCurrentContext +func setCurrentContext(vm *C.JavaVM, ctx C.jobject) { + mobileinit.SetCurrentContext(unsafe.Pointer(vm), uintptr(ctx)) +} + +//export callMain +func callMain(mainPC uintptr) { + for _, name := range []string{"TMPDIR", "PATH", "LD_LIBRARY_PATH"} { + n := C.CString(name) + os.Setenv(name, C.GoString(C.getenv(n))) + C.free(unsafe.Pointer(n)) + } + + // Set timezone. + // + // Note that Android zoneinfo is stored in /system/usr/share/zoneinfo, + // but it is in some kind of packed TZiff file that we do not support + // yet. As a stopgap, we build a fixed zone using the tm_zone name. + var curtime C.time_t + var curtm C.struct_tm + C.time(&curtime) + C.localtime_r(&curtime, &curtm) + tzOffset := int(curtm.tm_gmtoff) + tz := C.GoString(curtm.tm_zone) + time.Local = time.FixedZone(tz, tzOffset) + + go callfn.CallFn(mainPC) +} + +//export onStart +func onStart(activity *C.ANativeActivity) { +} + +//export onResume +func onResume(activity *C.ANativeActivity) { +} + +//export onSaveInstanceState +func onSaveInstanceState(activity *C.ANativeActivity, outSize *C.size_t) unsafe.Pointer { + return nil +} + +//export onPause +func onPause(activity *C.ANativeActivity) { +} + +//export onStop +func onStop(activity *C.ANativeActivity) { +} + +//export onCreate +func onCreate(activity *C.ANativeActivity) { + // Set the initial configuration. + // + // Note we use unbuffered channels to talk to the activity loop, and + // NativeActivity calls these callbacks sequentially, so configuration + // will be set before <-windowRedrawNeeded is processed. + windowConfigChange <- windowConfigRead(activity) +} + +//export onDestroy +func onDestroy(activity *C.ANativeActivity) { +} + +//export onWindowFocusChanged +func onWindowFocusChanged(activity *C.ANativeActivity, hasFocus C.int) { +} + +//export onNativeWindowCreated +func onNativeWindowCreated(activity *C.ANativeActivity, window *C.ANativeWindow) { +} + +//export onNativeWindowRedrawNeeded +func onNativeWindowRedrawNeeded(activity *C.ANativeActivity, window *C.ANativeWindow) { + // Called on orientation change and window resize. + // Send a request for redraw, and block this function + // until a complete draw and buffer swap is completed. + // This is required by the redraw documentation to + // avoid bad draws. + windowRedrawNeeded <- window + <-windowRedrawDone +} + +//export onNativeWindowDestroyed +func onNativeWindowDestroyed(activity *C.ANativeActivity, window *C.ANativeWindow) { + windowDestroyed <- window +} + +//export onInputQueueCreated +func onInputQueueCreated(activity *C.ANativeActivity, q *C.AInputQueue) { + inputQueue <- q + <-inputQueueDone +} + +//export onInputQueueDestroyed +func onInputQueueDestroyed(activity *C.ANativeActivity, q *C.AInputQueue) { + inputQueue <- nil + <-inputQueueDone +} + +//export onContentRectChanged +func onContentRectChanged(activity *C.ANativeActivity, rect *C.ARect) { +} + +type windowConfig struct { + orientation size.Orientation + pixelsPerPt float32 +} + +func windowConfigRead(activity *C.ANativeActivity) windowConfig { + aconfig := C.AConfiguration_new() + C.AConfiguration_fromAssetManager(aconfig, activity.assetManager) + orient := C.AConfiguration_getOrientation(aconfig) + density := C.AConfiguration_getDensity(aconfig) + C.AConfiguration_delete(aconfig) + + // Calculate the screen resolution. This value is approximate. For example, + // a physical resolution of 200 DPI may be quantized to one of the + // ACONFIGURATION_DENSITY_XXX values such as 160 or 240. + // + // A more accurate DPI could possibly be calculated from + // https://developer.android.com/reference/android/util/DisplayMetrics.html#xdpi + // but this does not appear to be accessible via the NDK. In any case, the + // hardware might not even provide a more accurate number, as the system + // does not apparently use the reported value. See golang.org/issue/13366 + // for a discussion. + var dpi int + switch density { + case C.ACONFIGURATION_DENSITY_DEFAULT: + dpi = 160 + case C.ACONFIGURATION_DENSITY_LOW, + C.ACONFIGURATION_DENSITY_MEDIUM, + 213, // C.ACONFIGURATION_DENSITY_TV + C.ACONFIGURATION_DENSITY_HIGH, + 320, // ACONFIGURATION_DENSITY_XHIGH + 480, // ACONFIGURATION_DENSITY_XXHIGH + 640: // ACONFIGURATION_DENSITY_XXXHIGH + dpi = int(density) + case C.ACONFIGURATION_DENSITY_NONE: + log.Print("android device reports no screen density") + dpi = 72 + default: + log.Printf("android device reports unknown density: %d", density) + // All we can do is guess. + if density > 0 { + dpi = int(density) + } else { + dpi = 72 + } + } + + o := size.OrientationUnknown + switch orient { + case C.ACONFIGURATION_ORIENTATION_PORT: + o = size.OrientationPortrait + case C.ACONFIGURATION_ORIENTATION_LAND: + o = size.OrientationLandscape + } + + return windowConfig{ + orientation: o, + pixelsPerPt: float32(dpi) / 72, + } +} + +//export onConfigurationChanged +func onConfigurationChanged(activity *C.ANativeActivity) { + // A rotation event first triggers onConfigurationChanged, then + // calls onNativeWindowRedrawNeeded. We extract the orientation + // here and save it for the redraw event. + windowConfigChange <- windowConfigRead(activity) +} + +//export onLowMemory +func onLowMemory(activity *C.ANativeActivity) { +} + +var ( + inputQueue = make(chan *C.AInputQueue) + inputQueueDone = make(chan struct{}) + windowDestroyed = make(chan *C.ANativeWindow) + windowRedrawNeeded = make(chan *C.ANativeWindow) + windowRedrawDone = make(chan struct{}) + windowConfigChange = make(chan windowConfig) +) + +func init() { + theApp.registerGLViewportFilter() +} + +func main(f func(App)) { + mainUserFn = f + // TODO: merge the runInputQueue and mainUI functions? + go func() { + if err := mobileinit.RunOnJVM(runInputQueue); err != nil { + log.Fatalf("app: %v", err) + } + }() + // Preserve this OS thread for: + // 1. the attached JNI thread + // 2. the GL context + if err := mobileinit.RunOnJVM(mainUI); err != nil { + log.Fatalf("app: %v", err) + } +} + +var mainUserFn func(App) + +func mainUI(vm, jniEnv, ctx uintptr) error { + workAvailable := theApp.worker.WorkAvailable() + + donec := make(chan struct{}) + go func() { + // close the donec channel in a defer statement + // so that we could still be able to return even + // if mainUserFn panics. + defer close(donec) + + mainUserFn(theApp) + }() + + var pixelsPerPt float32 + var orientation size.Orientation + + for { + select { + case <-donec: + return nil + case cfg := <-windowConfigChange: + pixelsPerPt = cfg.pixelsPerPt + orientation = cfg.orientation + case w := <-windowRedrawNeeded: + if C.surface == nil { + if errStr := C.createEGLSurface(w); errStr != nil { + return fmt.Errorf("%s (%s)", C.GoString(errStr), eglGetError()) + } + } + theApp.sendLifecycle(lifecycle.StageFocused) + widthPx := int(C.ANativeWindow_getWidth(w)) + heightPx := int(C.ANativeWindow_getHeight(w)) + theApp.eventsIn <- size.Event{ + WidthPx: widthPx, + HeightPx: heightPx, + WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt), + HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt), + PixelsPerPt: pixelsPerPt, + Orientation: orientation, + } + theApp.eventsIn <- paint.Event{External: true} + case <-windowDestroyed: + if C.surface != nil { + if errStr := C.destroyEGLSurface(); errStr != nil { + return fmt.Errorf("%s (%s)", C.GoString(errStr), eglGetError()) + } + } + C.surface = nil + theApp.sendLifecycle(lifecycle.StageAlive) + case <-workAvailable: + theApp.worker.DoWork() + case <-theApp.publish: + // TODO: compare a generation number to redrawGen for stale paints? + if C.surface != nil { + // eglSwapBuffers blocks until vsync. + if C.eglSwapBuffers(C.display, C.surface) == C.EGL_FALSE { + log.Printf("app: failed to swap buffers (%s)", eglGetError()) + } + } + select { + case windowRedrawDone <- struct{}{}: + default: + } + theApp.publishResult <- PublishResult{} + } + } +} + +func runInputQueue(vm, jniEnv, ctx uintptr) error { + env := (*C.JNIEnv)(unsafe.Pointer(jniEnv)) // not a Go heap pointer + + // Android loopers select on OS file descriptors, not Go channels, so we + // translate the inputQueue channel to an ALooper_wake call. + l := C.ALooper_prepare(C.ALOOPER_PREPARE_ALLOW_NON_CALLBACKS) + pending := make(chan *C.AInputQueue, 1) + go func() { + for q := range inputQueue { + pending <- q + C.ALooper_wake(l) + } + }() + + var q *C.AInputQueue + for { + if C.ALooper_pollOnce(-1, nil, nil, nil) == C.ALOOPER_POLL_WAKE { + select { + default: + case p := <-pending: + if q != nil { + processEvents(env, q) + C.AInputQueue_detachLooper(q) + } + q = p + if q != nil { + C.AInputQueue_attachLooper(q, l, 0, nil, nil) + } + inputQueueDone <- struct{}{} + } + } + if q != nil { + processEvents(env, q) + } + } +} + +func processEvents(env *C.JNIEnv, q *C.AInputQueue) { + var e *C.AInputEvent + for C.AInputQueue_getEvent(q, &e) >= 0 { + if C.AInputQueue_preDispatchEvent(q, e) != 0 { + continue + } + processEvent(env, e) + C.AInputQueue_finishEvent(q, e, 0) + } +} + +func processEvent(env *C.JNIEnv, e *C.AInputEvent) { + switch C.AInputEvent_getType(e) { + case C.AINPUT_EVENT_TYPE_KEY: + processKey(env, e) + case C.AINPUT_EVENT_TYPE_MOTION: + // At most one of the events in this batch is an up or down event; get its index and change. + upDownIndex := C.size_t(C.AMotionEvent_getAction(e)&C.AMOTION_EVENT_ACTION_POINTER_INDEX_MASK) >> C.AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT + upDownType := touch.TypeMove + switch C.AMotionEvent_getAction(e) & C.AMOTION_EVENT_ACTION_MASK { + case C.AMOTION_EVENT_ACTION_DOWN, C.AMOTION_EVENT_ACTION_POINTER_DOWN: + upDownType = touch.TypeBegin + case C.AMOTION_EVENT_ACTION_UP, C.AMOTION_EVENT_ACTION_POINTER_UP: + upDownType = touch.TypeEnd + } + + for i, n := C.size_t(0), C.AMotionEvent_getPointerCount(e); i < n; i++ { + t := touch.TypeMove + if i == upDownIndex { + t = upDownType + } + theApp.eventsIn <- touch.Event{ + X: float32(C.AMotionEvent_getX(e, i)), + Y: float32(C.AMotionEvent_getY(e, i)), + Sequence: touch.Sequence(C.AMotionEvent_getPointerId(e, i)), + Type: t, + } + } + default: + log.Printf("unknown input event, type=%d", C.AInputEvent_getType(e)) + } +} + +func processKey(env *C.JNIEnv, e *C.AInputEvent) { + deviceID := C.AInputEvent_getDeviceId(e) + if deviceID == 0 { + // Software keyboard input, leaving for scribe/IME. + return + } + + k := key.Event{ + Rune: rune(C.getKeyRune(env, e)), + Code: convAndroidKeyCode(int32(C.AKeyEvent_getKeyCode(e))), + } + switch C.AKeyEvent_getAction(e) { + case C.AKEY_EVENT_ACTION_DOWN: + k.Direction = key.DirPress + case C.AKEY_EVENT_ACTION_UP: + k.Direction = key.DirRelease + default: + k.Direction = key.DirNone + } + // TODO(crawshaw): set Modifiers. + theApp.eventsIn <- k +} + +func eglGetError() string { + switch errNum := C.eglGetError(); errNum { + case C.EGL_SUCCESS: + return "EGL_SUCCESS" + case C.EGL_NOT_INITIALIZED: + return "EGL_NOT_INITIALIZED" + case C.EGL_BAD_ACCESS: + return "EGL_BAD_ACCESS" + case C.EGL_BAD_ALLOC: + return "EGL_BAD_ALLOC" + case C.EGL_BAD_ATTRIBUTE: + return "EGL_BAD_ATTRIBUTE" + case C.EGL_BAD_CONTEXT: + return "EGL_BAD_CONTEXT" + case C.EGL_BAD_CONFIG: + return "EGL_BAD_CONFIG" + case C.EGL_BAD_CURRENT_SURFACE: + return "EGL_BAD_CURRENT_SURFACE" + case C.EGL_BAD_DISPLAY: + return "EGL_BAD_DISPLAY" + case C.EGL_BAD_SURFACE: + return "EGL_BAD_SURFACE" + case C.EGL_BAD_MATCH: + return "EGL_BAD_MATCH" + case C.EGL_BAD_PARAMETER: + return "EGL_BAD_PARAMETER" + case C.EGL_BAD_NATIVE_PIXMAP: + return "EGL_BAD_NATIVE_PIXMAP" + case C.EGL_BAD_NATIVE_WINDOW: + return "EGL_BAD_NATIVE_WINDOW" + case C.EGL_CONTEXT_LOST: + return "EGL_CONTEXT_LOST" + default: + return fmt.Sprintf("Unknown EGL err: %d", errNum) + } +} + +func convAndroidKeyCode(aKeyCode int32) key.Code { + // Many Android key codes do not map into USB HID codes. + // For those, key.CodeUnknown is returned. This switch has all + // cases, even the unknown ones, to serve as a documentation + // and search aid. + switch aKeyCode { + case C.AKEYCODE_UNKNOWN: + case C.AKEYCODE_SOFT_LEFT: + case C.AKEYCODE_SOFT_RIGHT: + case C.AKEYCODE_HOME: + return key.CodeHome + case C.AKEYCODE_BACK: + case C.AKEYCODE_CALL: + case C.AKEYCODE_ENDCALL: + case C.AKEYCODE_0: + return key.Code0 + case C.AKEYCODE_1: + return key.Code1 + case C.AKEYCODE_2: + return key.Code2 + case C.AKEYCODE_3: + return key.Code3 + case C.AKEYCODE_4: + return key.Code4 + case C.AKEYCODE_5: + return key.Code5 + case C.AKEYCODE_6: + return key.Code6 + case C.AKEYCODE_7: + return key.Code7 + case C.AKEYCODE_8: + return key.Code8 + case C.AKEYCODE_9: + return key.Code9 + case C.AKEYCODE_STAR: + case C.AKEYCODE_POUND: + case C.AKEYCODE_DPAD_UP: + case C.AKEYCODE_DPAD_DOWN: + case C.AKEYCODE_DPAD_LEFT: + case C.AKEYCODE_DPAD_RIGHT: + case C.AKEYCODE_DPAD_CENTER: + case C.AKEYCODE_VOLUME_UP: + return key.CodeVolumeUp + case C.AKEYCODE_VOLUME_DOWN: + return key.CodeVolumeDown + case C.AKEYCODE_POWER: + case C.AKEYCODE_CAMERA: + case C.AKEYCODE_CLEAR: + case C.AKEYCODE_A: + return key.CodeA + case C.AKEYCODE_B: + return key.CodeB + case C.AKEYCODE_C: + return key.CodeC + case C.AKEYCODE_D: + return key.CodeD + case C.AKEYCODE_E: + return key.CodeE + case C.AKEYCODE_F: + return key.CodeF + case C.AKEYCODE_G: + return key.CodeG + case C.AKEYCODE_H: + return key.CodeH + case C.AKEYCODE_I: + return key.CodeI + case C.AKEYCODE_J: + return key.CodeJ + case C.AKEYCODE_K: + return key.CodeK + case C.AKEYCODE_L: + return key.CodeL + case C.AKEYCODE_M: + return key.CodeM + case C.AKEYCODE_N: + return key.CodeN + case C.AKEYCODE_O: + return key.CodeO + case C.AKEYCODE_P: + return key.CodeP + case C.AKEYCODE_Q: + return key.CodeQ + case C.AKEYCODE_R: + return key.CodeR + case C.AKEYCODE_S: + return key.CodeS + case C.AKEYCODE_T: + return key.CodeT + case C.AKEYCODE_U: + return key.CodeU + case C.AKEYCODE_V: + return key.CodeV + case C.AKEYCODE_W: + return key.CodeW + case C.AKEYCODE_X: + return key.CodeX + case C.AKEYCODE_Y: + return key.CodeY + case C.AKEYCODE_Z: + return key.CodeZ + case C.AKEYCODE_COMMA: + return key.CodeComma + case C.AKEYCODE_PERIOD: + return key.CodeFullStop + case C.AKEYCODE_ALT_LEFT: + return key.CodeLeftAlt + case C.AKEYCODE_ALT_RIGHT: + return key.CodeRightAlt + case C.AKEYCODE_SHIFT_LEFT: + return key.CodeLeftShift + case C.AKEYCODE_SHIFT_RIGHT: + return key.CodeRightShift + case C.AKEYCODE_TAB: + return key.CodeTab + case C.AKEYCODE_SPACE: + return key.CodeSpacebar + case C.AKEYCODE_SYM: + case C.AKEYCODE_EXPLORER: + case C.AKEYCODE_ENVELOPE: + case C.AKEYCODE_ENTER: + return key.CodeReturnEnter + case C.AKEYCODE_DEL: + return key.CodeDeleteBackspace + case C.AKEYCODE_GRAVE: + return key.CodeGraveAccent + case C.AKEYCODE_MINUS: + return key.CodeHyphenMinus + case C.AKEYCODE_EQUALS: + return key.CodeEqualSign + case C.AKEYCODE_LEFT_BRACKET: + return key.CodeLeftSquareBracket + case C.AKEYCODE_RIGHT_BRACKET: + return key.CodeRightSquareBracket + case C.AKEYCODE_BACKSLASH: + return key.CodeBackslash + case C.AKEYCODE_SEMICOLON: + return key.CodeSemicolon + case C.AKEYCODE_APOSTROPHE: + return key.CodeApostrophe + case C.AKEYCODE_SLASH: + return key.CodeSlash + case C.AKEYCODE_AT: + case C.AKEYCODE_NUM: + case C.AKEYCODE_HEADSETHOOK: + case C.AKEYCODE_FOCUS: + case C.AKEYCODE_PLUS: + case C.AKEYCODE_MENU: + case C.AKEYCODE_NOTIFICATION: + case C.AKEYCODE_SEARCH: + case C.AKEYCODE_MEDIA_PLAY_PAUSE: + case C.AKEYCODE_MEDIA_STOP: + case C.AKEYCODE_MEDIA_NEXT: + case C.AKEYCODE_MEDIA_PREVIOUS: + case C.AKEYCODE_MEDIA_REWIND: + case C.AKEYCODE_MEDIA_FAST_FORWARD: + case C.AKEYCODE_MUTE: + case C.AKEYCODE_PAGE_UP: + return key.CodePageUp + case C.AKEYCODE_PAGE_DOWN: + return key.CodePageDown + case C.AKEYCODE_PICTSYMBOLS: + case C.AKEYCODE_SWITCH_CHARSET: + case C.AKEYCODE_BUTTON_A: + case C.AKEYCODE_BUTTON_B: + case C.AKEYCODE_BUTTON_C: + case C.AKEYCODE_BUTTON_X: + case C.AKEYCODE_BUTTON_Y: + case C.AKEYCODE_BUTTON_Z: + case C.AKEYCODE_BUTTON_L1: + case C.AKEYCODE_BUTTON_R1: + case C.AKEYCODE_BUTTON_L2: + case C.AKEYCODE_BUTTON_R2: + case C.AKEYCODE_BUTTON_THUMBL: + case C.AKEYCODE_BUTTON_THUMBR: + case C.AKEYCODE_BUTTON_START: + case C.AKEYCODE_BUTTON_SELECT: + case C.AKEYCODE_BUTTON_MODE: + case C.AKEYCODE_ESCAPE: + return key.CodeEscape + case C.AKEYCODE_FORWARD_DEL: + return key.CodeDeleteForward + case C.AKEYCODE_CTRL_LEFT: + return key.CodeLeftControl + case C.AKEYCODE_CTRL_RIGHT: + return key.CodeRightControl + case C.AKEYCODE_CAPS_LOCK: + return key.CodeCapsLock + case C.AKEYCODE_SCROLL_LOCK: + case C.AKEYCODE_META_LEFT: + return key.CodeLeftGUI + case C.AKEYCODE_META_RIGHT: + return key.CodeRightGUI + case C.AKEYCODE_FUNCTION: + case C.AKEYCODE_SYSRQ: + case C.AKEYCODE_BREAK: + case C.AKEYCODE_MOVE_HOME: + case C.AKEYCODE_MOVE_END: + case C.AKEYCODE_INSERT: + return key.CodeInsert + case C.AKEYCODE_FORWARD: + case C.AKEYCODE_MEDIA_PLAY: + case C.AKEYCODE_MEDIA_PAUSE: + case C.AKEYCODE_MEDIA_CLOSE: + case C.AKEYCODE_MEDIA_EJECT: + case C.AKEYCODE_MEDIA_RECORD: + case C.AKEYCODE_F1: + return key.CodeF1 + case C.AKEYCODE_F2: + return key.CodeF2 + case C.AKEYCODE_F3: + return key.CodeF3 + case C.AKEYCODE_F4: + return key.CodeF4 + case C.AKEYCODE_F5: + return key.CodeF5 + case C.AKEYCODE_F6: + return key.CodeF6 + case C.AKEYCODE_F7: + return key.CodeF7 + case C.AKEYCODE_F8: + return key.CodeF8 + case C.AKEYCODE_F9: + return key.CodeF9 + case C.AKEYCODE_F10: + return key.CodeF10 + case C.AKEYCODE_F11: + return key.CodeF11 + case C.AKEYCODE_F12: + return key.CodeF12 + case C.AKEYCODE_NUM_LOCK: + return key.CodeKeypadNumLock + case C.AKEYCODE_NUMPAD_0: + return key.CodeKeypad0 + case C.AKEYCODE_NUMPAD_1: + return key.CodeKeypad1 + case C.AKEYCODE_NUMPAD_2: + return key.CodeKeypad2 + case C.AKEYCODE_NUMPAD_3: + return key.CodeKeypad3 + case C.AKEYCODE_NUMPAD_4: + return key.CodeKeypad4 + case C.AKEYCODE_NUMPAD_5: + return key.CodeKeypad5 + case C.AKEYCODE_NUMPAD_6: + return key.CodeKeypad6 + case C.AKEYCODE_NUMPAD_7: + return key.CodeKeypad7 + case C.AKEYCODE_NUMPAD_8: + return key.CodeKeypad8 + case C.AKEYCODE_NUMPAD_9: + return key.CodeKeypad9 + case C.AKEYCODE_NUMPAD_DIVIDE: + return key.CodeKeypadSlash + case C.AKEYCODE_NUMPAD_MULTIPLY: + return key.CodeKeypadAsterisk + case C.AKEYCODE_NUMPAD_SUBTRACT: + return key.CodeKeypadHyphenMinus + case C.AKEYCODE_NUMPAD_ADD: + return key.CodeKeypadPlusSign + case C.AKEYCODE_NUMPAD_DOT: + return key.CodeKeypadFullStop + case C.AKEYCODE_NUMPAD_COMMA: + case C.AKEYCODE_NUMPAD_ENTER: + return key.CodeKeypadEnter + case C.AKEYCODE_NUMPAD_EQUALS: + return key.CodeKeypadEqualSign + case C.AKEYCODE_NUMPAD_LEFT_PAREN: + case C.AKEYCODE_NUMPAD_RIGHT_PAREN: + case C.AKEYCODE_VOLUME_MUTE: + return key.CodeMute + case C.AKEYCODE_INFO: + case C.AKEYCODE_CHANNEL_UP: + case C.AKEYCODE_CHANNEL_DOWN: + case C.AKEYCODE_ZOOM_IN: + case C.AKEYCODE_ZOOM_OUT: + case C.AKEYCODE_TV: + case C.AKEYCODE_WINDOW: + case C.AKEYCODE_GUIDE: + case C.AKEYCODE_DVR: + case C.AKEYCODE_BOOKMARK: + case C.AKEYCODE_CAPTIONS: + case C.AKEYCODE_SETTINGS: + case C.AKEYCODE_TV_POWER: + case C.AKEYCODE_TV_INPUT: + case C.AKEYCODE_STB_POWER: + case C.AKEYCODE_STB_INPUT: + case C.AKEYCODE_AVR_POWER: + case C.AKEYCODE_AVR_INPUT: + case C.AKEYCODE_PROG_RED: + case C.AKEYCODE_PROG_GREEN: + case C.AKEYCODE_PROG_YELLOW: + case C.AKEYCODE_PROG_BLUE: + case C.AKEYCODE_APP_SWITCH: + case C.AKEYCODE_BUTTON_1: + case C.AKEYCODE_BUTTON_2: + case C.AKEYCODE_BUTTON_3: + case C.AKEYCODE_BUTTON_4: + case C.AKEYCODE_BUTTON_5: + case C.AKEYCODE_BUTTON_6: + case C.AKEYCODE_BUTTON_7: + case C.AKEYCODE_BUTTON_8: + case C.AKEYCODE_BUTTON_9: + case C.AKEYCODE_BUTTON_10: + case C.AKEYCODE_BUTTON_11: + case C.AKEYCODE_BUTTON_12: + case C.AKEYCODE_BUTTON_13: + case C.AKEYCODE_BUTTON_14: + case C.AKEYCODE_BUTTON_15: + case C.AKEYCODE_BUTTON_16: + case C.AKEYCODE_LANGUAGE_SWITCH: + case C.AKEYCODE_MANNER_MODE: + case C.AKEYCODE_3D_MODE: + case C.AKEYCODE_CONTACTS: + case C.AKEYCODE_CALENDAR: + case C.AKEYCODE_MUSIC: + case C.AKEYCODE_CALCULATOR: + } + /* Defined in an NDK API version beyond what we use today: + C.AKEYCODE_ASSIST + C.AKEYCODE_BRIGHTNESS_DOWN + C.AKEYCODE_BRIGHTNESS_UP + C.AKEYCODE_EISU + C.AKEYCODE_HENKAN + C.AKEYCODE_KANA + C.AKEYCODE_KATAKANA_HIRAGANA + C.AKEYCODE_MEDIA_AUDIO_TRACK + C.AKEYCODE_MUHENKAN + C.AKEYCODE_RO + C.AKEYCODE_YEN + C.AKEYCODE_ZENKAKU_HANKAKU + */ + return key.CodeUnknown +} diff --git a/vendor/golang.org/x/mobile/app/app.go b/vendor/golang.org/x/mobile/app/app.go new file mode 100644 index 00000000..9817e13d --- /dev/null +++ b/vendor/golang.org/x/mobile/app/app.go @@ -0,0 +1,213 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux || darwin || windows + +package app + +import ( + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/gl" + _ "golang.org/x/mobile/internal/mobileinit" +) + +// Main is called by the main.main function to run the mobile application. +// +// It calls f on the App, in a separate goroutine, as some OS-specific +// libraries require being on 'the main thread'. +func Main(f func(App)) { + main(f) +} + +// App is how a GUI mobile application interacts with the OS. +type App interface { + // Events returns the events channel. It carries events from the system to + // the app. The type of such events include: + // - lifecycle.Event + // - mouse.Event + // - paint.Event + // - size.Event + // - touch.Event + // from the golang.org/x/mobile/event/etc packages. Other packages may + // define other event types that are carried on this channel. + Events() <-chan interface{} + + // Send sends an event on the events channel. It does not block. + Send(event interface{}) + + // Publish flushes any pending drawing commands, such as OpenGL calls, and + // swaps the back buffer to the screen. + Publish() PublishResult + + // TODO: replace filters (and the Events channel) with a NextEvent method? + + // Filter calls each registered event filter function in sequence. + Filter(event interface{}) interface{} + + // RegisterFilter registers a event filter function to be called by Filter. The + // function can return a different event, or return nil to consume the event, + // but the function can also return its argument unchanged, where its purpose + // is to trigger a side effect rather than modify the event. + RegisterFilter(f func(interface{}) interface{}) +} + +// PublishResult is the result of an App.Publish call. +type PublishResult struct { + // BackBufferPreserved is whether the contents of the back buffer was + // preserved. If false, the contents are undefined. + BackBufferPreserved bool +} + +var theApp = &app{ + eventsOut: make(chan interface{}), + lifecycleStage: lifecycle.StageDead, + publish: make(chan struct{}), + publishResult: make(chan PublishResult), +} + +func init() { + theApp.eventsIn = pump(theApp.eventsOut) + theApp.glctx, theApp.worker = gl.NewContext() +} + +func (a *app) sendLifecycle(to lifecycle.Stage) { + if a.lifecycleStage == to { + return + } + a.eventsIn <- lifecycle.Event{ + From: a.lifecycleStage, + To: to, + DrawContext: a.glctx, + } + a.lifecycleStage = to +} + +type app struct { + filters []func(interface{}) interface{} + + eventsOut chan interface{} + eventsIn chan interface{} + lifecycleStage lifecycle.Stage + publish chan struct{} + publishResult chan PublishResult + + glctx gl.Context + worker gl.Worker +} + +func (a *app) Events() <-chan interface{} { + return a.eventsOut +} + +func (a *app) Send(event interface{}) { + a.eventsIn <- event +} + +func (a *app) Publish() PublishResult { + // gl.Flush is a lightweight (on modern GL drivers) blocking call + // that ensures all GL functions pending in the gl package have + // been passed onto the GL driver before the app package attempts + // to swap the screen buffer. + // + // This enforces that the final receive (for this paint cycle) on + // gl.WorkAvailable happens before the send on endPaint. + a.glctx.Flush() + a.publish <- struct{}{} + return <-a.publishResult +} + +func (a *app) Filter(event interface{}) interface{} { + for _, f := range a.filters { + event = f(event) + } + return event +} + +func (a *app) RegisterFilter(f func(interface{}) interface{}) { + a.filters = append(a.filters, f) +} + +type stopPumping struct{} + +// pump returns a channel src such that sending on src will eventually send on +// dst, in order, but that src will always be ready to send/receive soon, even +// if dst currently isn't. It is effectively an infinitely buffered channel. +// +// In particular, goroutine A sending on src will not deadlock even if goroutine +// B that's responsible for receiving on dst is currently blocked trying to +// send to A on a separate channel. +// +// Send a stopPumping on the src channel to close the dst channel after all queued +// events are sent on dst. After that, other goroutines can still send to src, +// so that such sends won't block forever, but such events will be ignored. +func pump(dst chan interface{}) (src chan interface{}) { + src = make(chan interface{}) + go func() { + // initialSize is the initial size of the circular buffer. It must be a + // power of 2. + const initialSize = 16 + i, j, buf, mask := 0, 0, make([]interface{}, initialSize), initialSize-1 + + srcActive := true + for { + maybeDst := dst + if i == j { + maybeDst = nil + } + if maybeDst == nil && !srcActive { + // Pump is stopped and empty. + break + } + + select { + case maybeDst <- buf[i&mask]: + buf[i&mask] = nil + i++ + + case e := <-src: + if _, ok := e.(stopPumping); ok { + srcActive = false + continue + } + + if !srcActive { + continue + } + + // Allocate a bigger buffer if necessary. + if i+len(buf) == j { + b := make([]interface{}, 2*len(buf)) + n := copy(b, buf[j&mask:]) + copy(b[n:], buf[:j&mask]) + i, j = 0, len(buf) + buf, mask = b, len(b)-1 + } + + buf[j&mask] = e + j++ + } + } + + close(dst) + // Block forever. + for range src { + } + }() + return src +} + +// TODO: do this for all build targets, not just linux (x11 and Android)? If +// so, should package gl instead of this package call RegisterFilter?? +// +// TODO: does Android need this?? It seems to work without it (Nexus 7, +// KitKat). If only x11 needs this, should we move this to x11.go?? +func (a *app) registerGLViewportFilter() { + a.RegisterFilter(func(e interface{}) interface{} { + if e, ok := e.(size.Event); ok { + a.glctx.Viewport(0, 0, e.WidthPx, e.HeightPx) + } + return e + }) +} diff --git a/vendor/golang.org/x/mobile/app/darwin_desktop.go b/vendor/golang.org/x/mobile/app/darwin_desktop.go new file mode 100644 index 00000000..180c6027 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/darwin_desktop.go @@ -0,0 +1,495 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios + +package app + +// Simple on-screen app debugging for OS X. Not an officially supported +// development target for apps, as screens with mice are very different +// than screens with touch panels. + +/* +#cgo CFLAGS: -x objective-c -DGL_SILENCE_DEPRECATION +#cgo LDFLAGS: -framework Cocoa -framework OpenGL +#import // for HIToolbox/Events.h +#import +#include + +void runApp(void); +void stopApp(void); +void makeCurrentContext(GLintptr); +uint64 threadID(); +*/ +import "C" +import ( + "log" + "runtime" + "sync" + + "golang.org/x/mobile/event/key" + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/event/touch" + "golang.org/x/mobile/geom" +) + +var initThreadID uint64 + +func init() { + // Lock the goroutine responsible for initialization to an OS thread. + // This means the goroutine running main (and calling runApp below) + // is locked to the OS thread that started the program. This is + // necessary for the correct delivery of Cocoa events to the process. + // + // A discussion on this topic: + // https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ + runtime.LockOSThread() + initThreadID = uint64(C.threadID()) +} + +func main(f func(App)) { + if tid := uint64(C.threadID()); tid != initThreadID { + log.Fatalf("app.Main called on thread %d, but app.init ran on %d", tid, initThreadID) + } + + go func() { + f(theApp) + C.stopApp() + }() + + C.runApp() +} + +// loop is the primary drawing loop. +// +// After Cocoa has captured the initial OS thread for processing Cocoa +// events in runApp, it starts loop on another goroutine. It is locked +// to an OS thread for its OpenGL context. +// +// The loop processes GL calls until a publish event appears. +// Then it runs any remaining GL calls and flushes the screen. +// +// As NSOpenGLCPSwapInterval is set to 1, the call to CGLFlushDrawable +// blocks until the screen refresh. +func (a *app) loop(ctx C.GLintptr) { + runtime.LockOSThread() + C.makeCurrentContext(ctx) + + workAvailable := a.worker.WorkAvailable() + + for { + select { + case <-workAvailable: + a.worker.DoWork() + case <-theApp.publish: + loop1: + for { + select { + case <-workAvailable: + a.worker.DoWork() + default: + break loop1 + } + } + C.CGLFlushDrawable(C.CGLGetCurrentContext()) + theApp.publishResult <- PublishResult{} + select { + case drawDone <- struct{}{}: + default: + } + } + } +} + +var drawDone = make(chan struct{}) + +// drawgl is used by Cocoa to occasionally request screen updates. +// +//export drawgl +func drawgl() { + switch theApp.lifecycleStage { + case lifecycle.StageFocused, lifecycle.StageVisible: + theApp.Send(paint.Event{ + External: true, + }) + <-drawDone + } +} + +//export startloop +func startloop(ctx C.GLintptr) { + go theApp.loop(ctx) +} + +var windowHeightPx float32 + +//export setGeom +func setGeom(pixelsPerPt float32, widthPx, heightPx int) { + windowHeightPx = float32(heightPx) + theApp.eventsIn <- size.Event{ + WidthPx: widthPx, + HeightPx: heightPx, + WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt), + HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt), + PixelsPerPt: pixelsPerPt, + } +} + +var touchEvents struct { + sync.Mutex + pending []touch.Event +} + +func sendTouch(t touch.Type, x, y float32) { + theApp.eventsIn <- touch.Event{ + X: x, + Y: windowHeightPx - y, + Sequence: 0, + Type: t, + } +} + +//export eventMouseDown +func eventMouseDown(x, y float32) { sendTouch(touch.TypeBegin, x, y) } + +//export eventMouseDragged +func eventMouseDragged(x, y float32) { sendTouch(touch.TypeMove, x, y) } + +//export eventMouseEnd +func eventMouseEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) } + +//export lifecycleDead +func lifecycleDead() { theApp.sendLifecycle(lifecycle.StageDead) } + +//export eventKey +func eventKey(runeVal int32, direction uint8, code uint16, flags uint32) { + var modifiers key.Modifiers + for _, mod := range mods { + if flags&mod.flags == mod.flags { + modifiers |= mod.mod + } + } + + theApp.eventsIn <- key.Event{ + Rune: convRune(rune(runeVal)), + Code: convVirtualKeyCode(code), + Modifiers: modifiers, + Direction: key.Direction(direction), + } +} + +//export eventFlags +func eventFlags(flags uint32) { + for _, mod := range mods { + if flags&mod.flags == mod.flags && lastFlags&mod.flags != mod.flags { + eventKey(-1, uint8(key.DirPress), mod.code, flags) + } + if lastFlags&mod.flags == mod.flags && flags&mod.flags != mod.flags { + eventKey(-1, uint8(key.DirRelease), mod.code, flags) + } + } + lastFlags = flags +} + +var lastFlags uint32 + +var mods = [...]struct { + flags uint32 + code uint16 + mod key.Modifiers +}{ + // Left and right variants of modifier keys have their own masks, + // but they are not documented. These were determined empirically. + {1<<17 | 0x102, C.kVK_Shift, key.ModShift}, + {1<<17 | 0x104, C.kVK_RightShift, key.ModShift}, + {1<<18 | 0x101, C.kVK_Control, key.ModControl}, + // TODO key.ControlRight + {1<<19 | 0x120, C.kVK_Option, key.ModAlt}, + {1<<19 | 0x140, C.kVK_RightOption, key.ModAlt}, + {1<<20 | 0x108, C.kVK_Command, key.ModMeta}, + {1<<20 | 0x110, C.kVK_Command, key.ModMeta}, // TODO: missing kVK_RightCommand +} + +//export lifecycleAlive +func lifecycleAlive() { theApp.sendLifecycle(lifecycle.StageAlive) } + +//export lifecycleVisible +func lifecycleVisible() { + theApp.sendLifecycle(lifecycle.StageVisible) +} + +//export lifecycleFocused +func lifecycleFocused() { theApp.sendLifecycle(lifecycle.StageFocused) } + +// convRune marks the Carbon/Cocoa private-range unicode rune representing +// a non-unicode key event to -1, used for Rune in the key package. +// +// http://www.unicode.org/Public/MAPPINGS/VENDORS/APPLE/CORPCHAR.TXT +func convRune(r rune) rune { + if '\uE000' <= r && r <= '\uF8FF' { + return -1 + } + return r +} + +// convVirtualKeyCode converts a Carbon/Cocoa virtual key code number +// into the standard keycodes used by the key package. +// +// To get a sense of the key map, see the diagram on +// +// http://boredzo.org/blog/archives/2007-05-22/virtual-key-codes +func convVirtualKeyCode(vkcode uint16) key.Code { + switch vkcode { + case C.kVK_ANSI_A: + return key.CodeA + case C.kVK_ANSI_B: + return key.CodeB + case C.kVK_ANSI_C: + return key.CodeC + case C.kVK_ANSI_D: + return key.CodeD + case C.kVK_ANSI_E: + return key.CodeE + case C.kVK_ANSI_F: + return key.CodeF + case C.kVK_ANSI_G: + return key.CodeG + case C.kVK_ANSI_H: + return key.CodeH + case C.kVK_ANSI_I: + return key.CodeI + case C.kVK_ANSI_J: + return key.CodeJ + case C.kVK_ANSI_K: + return key.CodeK + case C.kVK_ANSI_L: + return key.CodeL + case C.kVK_ANSI_M: + return key.CodeM + case C.kVK_ANSI_N: + return key.CodeN + case C.kVK_ANSI_O: + return key.CodeO + case C.kVK_ANSI_P: + return key.CodeP + case C.kVK_ANSI_Q: + return key.CodeQ + case C.kVK_ANSI_R: + return key.CodeR + case C.kVK_ANSI_S: + return key.CodeS + case C.kVK_ANSI_T: + return key.CodeT + case C.kVK_ANSI_U: + return key.CodeU + case C.kVK_ANSI_V: + return key.CodeV + case C.kVK_ANSI_W: + return key.CodeW + case C.kVK_ANSI_X: + return key.CodeX + case C.kVK_ANSI_Y: + return key.CodeY + case C.kVK_ANSI_Z: + return key.CodeZ + case C.kVK_ANSI_1: + return key.Code1 + case C.kVK_ANSI_2: + return key.Code2 + case C.kVK_ANSI_3: + return key.Code3 + case C.kVK_ANSI_4: + return key.Code4 + case C.kVK_ANSI_5: + return key.Code5 + case C.kVK_ANSI_6: + return key.Code6 + case C.kVK_ANSI_7: + return key.Code7 + case C.kVK_ANSI_8: + return key.Code8 + case C.kVK_ANSI_9: + return key.Code9 + case C.kVK_ANSI_0: + return key.Code0 + // TODO: move the rest of these codes to constants in key.go + // if we are happy with them. + case C.kVK_Return: + return key.CodeReturnEnter + case C.kVK_Escape: + return key.CodeEscape + case C.kVK_Delete: + return key.CodeDeleteBackspace + case C.kVK_Tab: + return key.CodeTab + case C.kVK_Space: + return key.CodeSpacebar + case C.kVK_ANSI_Minus: + return key.CodeHyphenMinus + case C.kVK_ANSI_Equal: + return key.CodeEqualSign + case C.kVK_ANSI_LeftBracket: + return key.CodeLeftSquareBracket + case C.kVK_ANSI_RightBracket: + return key.CodeRightSquareBracket + case C.kVK_ANSI_Backslash: + return key.CodeBackslash + // 50: Keyboard Non-US "#" and ~ + case C.kVK_ANSI_Semicolon: + return key.CodeSemicolon + case C.kVK_ANSI_Quote: + return key.CodeApostrophe + case C.kVK_ANSI_Grave: + return key.CodeGraveAccent + case C.kVK_ANSI_Comma: + return key.CodeComma + case C.kVK_ANSI_Period: + return key.CodeFullStop + case C.kVK_ANSI_Slash: + return key.CodeSlash + case C.kVK_CapsLock: + return key.CodeCapsLock + case C.kVK_F1: + return key.CodeF1 + case C.kVK_F2: + return key.CodeF2 + case C.kVK_F3: + return key.CodeF3 + case C.kVK_F4: + return key.CodeF4 + case C.kVK_F5: + return key.CodeF5 + case C.kVK_F6: + return key.CodeF6 + case C.kVK_F7: + return key.CodeF7 + case C.kVK_F8: + return key.CodeF8 + case C.kVK_F9: + return key.CodeF9 + case C.kVK_F10: + return key.CodeF10 + case C.kVK_F11: + return key.CodeF11 + case C.kVK_F12: + return key.CodeF12 + // 70: PrintScreen + // 71: Scroll Lock + // 72: Pause + // 73: Insert + case C.kVK_Home: + return key.CodeHome + case C.kVK_PageUp: + return key.CodePageUp + case C.kVK_ForwardDelete: + return key.CodeDeleteForward + case C.kVK_End: + return key.CodeEnd + case C.kVK_PageDown: + return key.CodePageDown + case C.kVK_RightArrow: + return key.CodeRightArrow + case C.kVK_LeftArrow: + return key.CodeLeftArrow + case C.kVK_DownArrow: + return key.CodeDownArrow + case C.kVK_UpArrow: + return key.CodeUpArrow + case C.kVK_ANSI_KeypadClear: + return key.CodeKeypadNumLock + case C.kVK_ANSI_KeypadDivide: + return key.CodeKeypadSlash + case C.kVK_ANSI_KeypadMultiply: + return key.CodeKeypadAsterisk + case C.kVK_ANSI_KeypadMinus: + return key.CodeKeypadHyphenMinus + case C.kVK_ANSI_KeypadPlus: + return key.CodeKeypadPlusSign + case C.kVK_ANSI_KeypadEnter: + return key.CodeKeypadEnter + case C.kVK_ANSI_Keypad1: + return key.CodeKeypad1 + case C.kVK_ANSI_Keypad2: + return key.CodeKeypad2 + case C.kVK_ANSI_Keypad3: + return key.CodeKeypad3 + case C.kVK_ANSI_Keypad4: + return key.CodeKeypad4 + case C.kVK_ANSI_Keypad5: + return key.CodeKeypad5 + case C.kVK_ANSI_Keypad6: + return key.CodeKeypad6 + case C.kVK_ANSI_Keypad7: + return key.CodeKeypad7 + case C.kVK_ANSI_Keypad8: + return key.CodeKeypad8 + case C.kVK_ANSI_Keypad9: + return key.CodeKeypad9 + case C.kVK_ANSI_Keypad0: + return key.CodeKeypad0 + case C.kVK_ANSI_KeypadDecimal: + return key.CodeKeypadFullStop + case C.kVK_ANSI_KeypadEquals: + return key.CodeKeypadEqualSign + case C.kVK_F13: + return key.CodeF13 + case C.kVK_F14: + return key.CodeF14 + case C.kVK_F15: + return key.CodeF15 + case C.kVK_F16: + return key.CodeF16 + case C.kVK_F17: + return key.CodeF17 + case C.kVK_F18: + return key.CodeF18 + case C.kVK_F19: + return key.CodeF19 + case C.kVK_F20: + return key.CodeF20 + // 116: Keyboard Execute + case C.kVK_Help: + return key.CodeHelp + // 118: Keyboard Menu + // 119: Keyboard Select + // 120: Keyboard Stop + // 121: Keyboard Again + // 122: Keyboard Undo + // 123: Keyboard Cut + // 124: Keyboard Copy + // 125: Keyboard Paste + // 126: Keyboard Find + case C.kVK_Mute: + return key.CodeMute + case C.kVK_VolumeUp: + return key.CodeVolumeUp + case C.kVK_VolumeDown: + return key.CodeVolumeDown + // 130: Keyboard Locking Caps Lock + // 131: Keyboard Locking Num Lock + // 132: Keyboard Locking Scroll Lock + // 133: Keyboard Comma + // 134: Keyboard Equal Sign + // ...: Bunch of stuff + case C.kVK_Control: + return key.CodeLeftControl + case C.kVK_Shift: + return key.CodeLeftShift + case C.kVK_Option: + return key.CodeLeftAlt + case C.kVK_Command: + return key.CodeLeftGUI + case C.kVK_RightControl: + return key.CodeRightControl + case C.kVK_RightShift: + return key.CodeRightShift + case C.kVK_RightOption: + return key.CodeRightAlt + // TODO key.CodeRightGUI + default: + return key.CodeUnknown + } +} diff --git a/vendor/golang.org/x/mobile/app/darwin_desktop.m b/vendor/golang.org/x/mobile/app/darwin_desktop.m new file mode 100644 index 00000000..071124f6 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/darwin_desktop.m @@ -0,0 +1,251 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && !ios +// +build darwin +// +build !ios + +#include "_cgo_export.h" +#include +#include + +#import +#import +#import + +void makeCurrentContext(GLintptr context) { + NSOpenGLContext* ctx = (NSOpenGLContext*)context; + [ctx makeCurrentContext]; +} + +uint64 threadID() { + uint64 id; + if (pthread_threadid_np(pthread_self(), &id)) { + abort(); + } + return id; +} + +@interface MobileGLView : NSOpenGLView +{ +} +@end + +@implementation MobileGLView +- (void)prepareOpenGL { + [super prepareOpenGL]; + [self setWantsBestResolutionOpenGLSurface:YES]; + GLint swapInt = 1; + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + [[self openGLContext] setValues:&swapInt forParameter:NSOpenGLCPSwapInterval]; +#pragma clang diagnostic pop + + // Using attribute arrays in OpenGL 3.3 requires the use of a VBA. + // But VBAs don't exist in ES 2. So we bind a default one. + GLuint vba; + glGenVertexArrays(1, &vba); + glBindVertexArray(vba); + + startloop((GLintptr)[self openGLContext]); +} + +- (void)reshape { + [super reshape]; + + // Calculate screen PPI. + // + // Note that the backingScaleFactor converts from logical + // pixels to actual pixels, but both of these units vary + // independently from real world size. E.g. + // + // 13" Retina Macbook Pro, 2560x1600, 227ppi, backingScaleFactor=2, scale=3.15 + // 15" Retina Macbook Pro, 2880x1800, 220ppi, backingScaleFactor=2, scale=3.06 + // 27" iMac, 2560x1440, 109ppi, backingScaleFactor=1, scale=1.51 + // 27" Retina iMac, 5120x2880, 218ppi, backingScaleFactor=2, scale=3.03 + NSScreen *screen = [NSScreen mainScreen]; + double screenPixW = [screen frame].size.width * [screen backingScaleFactor]; + + CGDirectDisplayID display = (CGDirectDisplayID)[[[screen deviceDescription] valueForKey:@"NSScreenNumber"] intValue]; + CGSize screenSizeMM = CGDisplayScreenSize(display); // in millimeters + float ppi = 25.4 * screenPixW / screenSizeMM.width; + float pixelsPerPt = ppi/72.0; + + // The width and height reported to the geom package are the + // bounds of the OpenGL view. Several steps are necessary. + // First, [self bounds] gives us the number of logical pixels + // in the view. Multiplying this by the backingScaleFactor + // gives us the number of actual pixels. + NSRect r = [self bounds]; + int w = r.size.width * [screen backingScaleFactor]; + int h = r.size.height * [screen backingScaleFactor]; + + setGeom(pixelsPerPt, w, h); +} + +- (void)drawRect:(NSRect)theRect { + // Called during resize. This gets rid of flicker when resizing. + drawgl(); +} + +- (void)mouseDown:(NSEvent *)theEvent { + double scale = [[NSScreen mainScreen] backingScaleFactor]; + NSPoint p = [theEvent locationInWindow]; + eventMouseDown(p.x * scale, p.y * scale); +} + +- (void)mouseUp:(NSEvent *)theEvent { + double scale = [[NSScreen mainScreen] backingScaleFactor]; + NSPoint p = [theEvent locationInWindow]; + eventMouseEnd(p.x * scale, p.y * scale); +} + +- (void)mouseDragged:(NSEvent *)theEvent { + double scale = [[NSScreen mainScreen] backingScaleFactor]; + NSPoint p = [theEvent locationInWindow]; + eventMouseDragged(p.x * scale, p.y * scale); +} + +- (void)windowDidBecomeKey:(NSNotification *)notification { + lifecycleFocused(); +} + +- (void)windowDidResignKey:(NSNotification *)notification { + if (![NSApp isHidden]) { + lifecycleVisible(); + } +} + +- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { + lifecycleAlive(); + [[NSRunningApplication currentApplication] activateWithOptions:(NSApplicationActivateAllWindows | NSApplicationActivateIgnoringOtherApps)]; + [self.window makeKeyAndOrderFront:self]; + lifecycleVisible(); +} + +- (void)applicationWillTerminate:(NSNotification *)aNotification { + lifecycleDead(); +} + +- (void)applicationDidHide:(NSNotification *)aNotification { + lifecycleAlive(); +} + +- (void)applicationWillUnhide:(NSNotification *)notification { + lifecycleVisible(); +} + +- (void)windowWillClose:(NSNotification *)notification { + lifecycleAlive(); +} +@end + +@interface MobileResponder : NSResponder +{ +} +@end + +@implementation MobileResponder +- (void)keyDown:(NSEvent *)theEvent { + [self key:theEvent]; +} +- (void)keyUp:(NSEvent *)theEvent { + [self key:theEvent]; +} +- (void)key:(NSEvent *)theEvent { + NSRange range = [theEvent.characters rangeOfComposedCharacterSequenceAtIndex:0]; + + uint8_t buf[4] = {0, 0, 0, 0}; + if (![theEvent.characters getBytes:buf + maxLength:4 + usedLength:nil + encoding:NSUTF32LittleEndianStringEncoding + options:NSStringEncodingConversionAllowLossy + range:range + remainingRange:nil]) { + NSLog(@"failed to read key event %@", theEvent); + return; + } + + uint32_t rune = (uint32_t)buf[0]<<0 | (uint32_t)buf[1]<<8 | (uint32_t)buf[2]<<16 | (uint32_t)buf[3]<<24; + + uint8_t direction; + if ([theEvent isARepeat]) { + direction = 0; + } else if (theEvent.type == NSEventTypeKeyDown) { + direction = 1; + } else { + direction = 2; + } + eventKey((int32_t)rune, direction, theEvent.keyCode, theEvent.modifierFlags); +} + +- (void)flagsChanged:(NSEvent *)theEvent { + eventFlags(theEvent.modifierFlags); +} +@end + +void +runApp(void) { + [NSAutoreleasePool new]; + [NSApplication sharedApplication]; + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + + id menuBar = [[NSMenu new] autorelease]; + id menuItem = [[NSMenuItem new] autorelease]; + [menuBar addItem:menuItem]; + [NSApp setMainMenu:menuBar]; + + id menu = [[NSMenu new] autorelease]; + id name = [[NSProcessInfo processInfo] processName]; + + id hideMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Hide" + action:@selector(hide:) keyEquivalent:@"h"] + autorelease]; + [menu addItem:hideMenuItem]; + + id quitMenuItem = [[[NSMenuItem alloc] initWithTitle:@"Quit" + action:@selector(terminate:) keyEquivalent:@"q"] + autorelease]; + [menu addItem:quitMenuItem]; + [menuItem setSubmenu:menu]; + + NSRect rect = NSMakeRect(0, 0, 600, 800); + + NSWindow* window = [[[NSWindow alloc] initWithContentRect:rect + styleMask:NSWindowStyleMaskTitled + backing:NSBackingStoreBuffered + defer:NO] + autorelease]; + window.styleMask |= NSWindowStyleMaskResizable; + window.styleMask |= NSWindowStyleMaskMiniaturizable; + window.styleMask |= NSWindowStyleMaskClosable; + window.title = name; + [window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; + + NSOpenGLPixelFormatAttribute attr[] = { + NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion3_2Core, + NSOpenGLPFAColorSize, 24, + NSOpenGLPFAAlphaSize, 8, + NSOpenGLPFADepthSize, 16, + NSOpenGLPFAAccelerated, + NSOpenGLPFADoubleBuffer, + NSOpenGLPFAAllowOfflineRenderers, + 0 + }; + id pixFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attr]; + MobileGLView* view = [[MobileGLView alloc] initWithFrame:rect pixelFormat:pixFormat]; + [window setContentView:view]; + [window setDelegate:view]; + [NSApp setDelegate:view]; + + window.nextResponder = [[[MobileResponder alloc] init] autorelease]; + + [NSApp run]; +} + +void stopApp(void) { + [NSApp terminate:nil]; +} diff --git a/vendor/golang.org/x/mobile/app/darwin_ios.go b/vendor/golang.org/x/mobile/app/darwin_ios.go new file mode 100644 index 00000000..bef9f421 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/darwin_ios.go @@ -0,0 +1,215 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && ios + +package app + +/* +#cgo CFLAGS: -x objective-c -DGL_SILENCE_DEPRECATION -DGLES_SILENCE_DEPRECATION +#cgo LDFLAGS: -framework Foundation -framework UIKit -framework GLKit -framework OpenGLES -framework QuartzCore +#include +#include +#include +#include +#import + +extern struct utsname sysInfo; + +void runApp(void); +void makeCurrentContext(GLintptr ctx); +void swapBuffers(GLintptr ctx); +uint64_t threadID(); +*/ +import "C" +import ( + "log" + "runtime" + "strings" + "sync" + + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/event/touch" + "golang.org/x/mobile/geom" +) + +var initThreadID uint64 + +func init() { + // Lock the goroutine responsible for initialization to an OS thread. + // This means the goroutine running main (and calling the run function + // below) is locked to the OS thread that started the program. This is + // necessary for the correct delivery of UIKit events to the process. + // + // A discussion on this topic: + // https://groups.google.com/forum/#!msg/golang-nuts/IiWZ2hUuLDA/SNKYYZBelsYJ + runtime.LockOSThread() + initThreadID = uint64(C.threadID()) +} + +func main(f func(App)) { + if tid := uint64(C.threadID()); tid != initThreadID { + log.Fatalf("app.Run called on thread %d, but app.init ran on %d", tid, initThreadID) + } + + go func() { + f(theApp) + // TODO(crawshaw): trigger runApp to return + }() + C.runApp() + panic("unexpected return from app.runApp") +} + +var pixelsPerPt float32 +var screenScale int // [UIScreen mainScreen].scale, either 1, 2, or 3. + +//export setScreen +func setScreen(scale int) { + C.uname(&C.sysInfo) + name := C.GoString(&C.sysInfo.machine[0]) + + var v float32 + + switch { + case strings.HasPrefix(name, "iPhone"): + v = 163 + case strings.HasPrefix(name, "iPad"): + // TODO: is there a better way to distinguish the iPad Mini? + switch name { + case "iPad2,5", "iPad2,6", "iPad2,7", "iPad4,4", "iPad4,5", "iPad4,6", "iPad4,7": + v = 163 // iPad Mini + default: + v = 132 + } + default: + v = 163 // names like i386 and x86_64 are the simulator + } + + if v == 0 { + log.Printf("unknown machine: %s", name) + v = 163 // emergency fallback + } + + pixelsPerPt = v * float32(scale) / 72 + screenScale = scale +} + +//export updateConfig +func updateConfig(width, height, orientation int32) { + o := size.OrientationUnknown + switch orientation { + case C.UIDeviceOrientationPortrait, C.UIDeviceOrientationPortraitUpsideDown: + o = size.OrientationPortrait + case C.UIDeviceOrientationLandscapeLeft, C.UIDeviceOrientationLandscapeRight: + o = size.OrientationLandscape + } + widthPx := screenScale * int(width) + heightPx := screenScale * int(height) + theApp.eventsIn <- size.Event{ + WidthPx: widthPx, + HeightPx: heightPx, + WidthPt: geom.Pt(float32(widthPx) / pixelsPerPt), + HeightPt: geom.Pt(float32(heightPx) / pixelsPerPt), + PixelsPerPt: pixelsPerPt, + Orientation: o, + } + theApp.eventsIn <- paint.Event{External: true} +} + +// touchIDs is the current active touches. The position in the array +// is the ID, the value is the UITouch* pointer value. +// +// It is widely reported that the iPhone can handle up to 5 simultaneous +// touch events, while the iPad can handle 11. +var touchIDs [11]uintptr + +var touchEvents struct { + sync.Mutex + pending []touch.Event +} + +//export sendTouch +func sendTouch(cTouch, cTouchType uintptr, x, y float32) { + id := -1 + for i, val := range touchIDs { + if val == cTouch { + id = i + break + } + } + if id == -1 { + for i, val := range touchIDs { + if val == 0 { + touchIDs[i] = cTouch + id = i + break + } + } + if id == -1 { + panic("out of touchIDs") + } + } + + t := touch.Type(cTouchType) + if t == touch.TypeEnd { + touchIDs[id] = 0 + } + + theApp.eventsIn <- touch.Event{ + X: x, + Y: y, + Sequence: touch.Sequence(id), + Type: t, + } +} + +//export lifecycleDead +func lifecycleDead() { theApp.sendLifecycle(lifecycle.StageDead) } + +//export lifecycleAlive +func lifecycleAlive() { theApp.sendLifecycle(lifecycle.StageAlive) } + +//export lifecycleVisible +func lifecycleVisible() { theApp.sendLifecycle(lifecycle.StageVisible) } + +//export lifecycleFocused +func lifecycleFocused() { theApp.sendLifecycle(lifecycle.StageFocused) } + +//export startloop +func startloop(ctx C.GLintptr) { + go theApp.loop(ctx) +} + +// loop is the primary drawing loop. +// +// After UIKit has captured the initial OS thread for processing UIKit +// events in runApp, it starts loop on another goroutine. It is locked +// to an OS thread for its OpenGL context. +func (a *app) loop(ctx C.GLintptr) { + runtime.LockOSThread() + C.makeCurrentContext(ctx) + + workAvailable := a.worker.WorkAvailable() + + for { + select { + case <-workAvailable: + a.worker.DoWork() + case <-theApp.publish: + loop1: + for { + select { + case <-workAvailable: + a.worker.DoWork() + default: + break loop1 + } + } + C.swapBuffers(ctx) + theApp.publishResult <- PublishResult{} + } + } +} diff --git a/vendor/golang.org/x/mobile/app/darwin_ios.m b/vendor/golang.org/x/mobile/app/darwin_ios.m new file mode 100644 index 00000000..21d73a5d --- /dev/null +++ b/vendor/golang.org/x/mobile/app/darwin_ios.m @@ -0,0 +1,167 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin && ios +// +build darwin +// +build ios + +#include "_cgo_export.h" +#include +#include +#include + +#import +#import + +struct utsname sysInfo; + +@interface GoAppAppController : GLKViewController +@end + +@interface GoAppAppDelegate : UIResponder +@property (strong, nonatomic) UIWindow *window; +@property (strong, nonatomic) GoAppAppController *controller; +@end + +@implementation GoAppAppDelegate +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + lifecycleAlive(); + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + self.controller = [[GoAppAppController alloc] initWithNibName:nil bundle:nil]; + self.window.rootViewController = self.controller; + [self.window makeKeyAndVisible]; + return YES; +} + +- (void)applicationDidBecomeActive:(UIApplication * )application { + lifecycleFocused(); +} + +- (void)applicationWillResignActive:(UIApplication *)application { + lifecycleVisible(); +} + +- (void)applicationDidEnterBackground:(UIApplication *)application { + lifecycleAlive(); +} + +- (void)applicationWillTerminate:(UIApplication *)application { + lifecycleDead(); +} +@end + +@interface GoAppAppController () +@property (strong, nonatomic) EAGLContext *context; +@property (strong, nonatomic) GLKView *glview; +@end + +@implementation GoAppAppController +- (void)viewWillAppear:(BOOL)animated +{ + // TODO: replace by swapping out GLKViewController for a UIVIewController. + [super viewWillAppear:animated]; + self.paused = YES; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; + self.glview = (GLKView*)self.view; + self.glview.drawableDepthFormat = GLKViewDrawableDepthFormat24; + self.glview.multipleTouchEnabled = true; // TODO expose setting to user. + self.glview.context = self.context; + self.glview.userInteractionEnabled = YES; + self.glview.enableSetNeedsDisplay = YES; // only invoked once + + // Do not use the GLKViewController draw loop. + self.paused = YES; + self.resumeOnDidBecomeActive = NO; + self.preferredFramesPerSecond = 0; + + int scale = 1; + if ([[UIScreen mainScreen] respondsToSelector:@selector(displayLinkWithTarget:selector:)]) { + scale = (int)[UIScreen mainScreen].scale; // either 1.0, 2.0, or 3.0. + } + setScreen(scale); + + CGSize size = [UIScreen mainScreen].bounds.size; + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + updateConfig((int)size.width, (int)size.height, orientation); +} + +- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id)coordinator { + [coordinator animateAlongsideTransition:^(id context) { + // TODO(crawshaw): come up with a plan to handle animations. + } completion:^(id context) { + UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation]; + updateConfig((int)size.width, (int)size.height, orientation); + }]; +} + +- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect { + // Now that we have been asked to do the first draw, disable any + // future draw and hand control over to the Go paint.Event cycle. + self.glview.enableSetNeedsDisplay = NO; + startloop((GLintptr)self.context); +} + +#define TOUCH_TYPE_BEGIN 0 // touch.TypeBegin +#define TOUCH_TYPE_MOVE 1 // touch.TypeMove +#define TOUCH_TYPE_END 2 // touch.TypeEnd + +static void sendTouches(int change, NSSet* touches) { + CGFloat scale = [UIScreen mainScreen].scale; + for (UITouch* touch in touches) { + CGPoint p = [touch locationInView:touch.view]; + sendTouch((GoUintptr)touch, (GoUintptr)change, p.x*scale, p.y*scale); + } +} + +- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { + sendTouches(TOUCH_TYPE_BEGIN, touches); +} + +- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { + sendTouches(TOUCH_TYPE_MOVE, touches); +} + +- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { + sendTouches(TOUCH_TYPE_END, touches); +} + +- (void)touchesCanceled:(NSSet*)touches withEvent:(UIEvent*)event { + sendTouches(TOUCH_TYPE_END, touches); +} +@end + +void runApp(void) { + char* argv[] = {}; + @autoreleasepool { + UIApplicationMain(0, argv, nil, NSStringFromClass([GoAppAppDelegate class])); + } +} + +void makeCurrentContext(GLintptr context) { + EAGLContext* ctx = (EAGLContext*)context; + if (![EAGLContext setCurrentContext:ctx]) { + // TODO(crawshaw): determine how terrible this is. Exit? + NSLog(@"failed to set current context"); + } +} + +void swapBuffers(GLintptr context) { + __block EAGLContext* ctx = (EAGLContext*)context; + dispatch_sync(dispatch_get_main_queue(), ^{ + [EAGLContext setCurrentContext:ctx]; + [ctx presentRenderbuffer:GL_RENDERBUFFER]; + }); +} + +uint64_t threadID() { + uint64_t id; + if (pthread_threadid_np(pthread_self(), &id)) { + abort(); + } + return id; +} diff --git a/vendor/golang.org/x/mobile/app/doc.go b/vendor/golang.org/x/mobile/app/doc.go new file mode 100644 index 00000000..2fabcd9d --- /dev/null +++ b/vendor/golang.org/x/mobile/app/doc.go @@ -0,0 +1,88 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package app lets you write portable all-Go apps for Android and iOS. + +There are typically two ways to use Go on Android and iOS. The first +is to write a Go library and use `gomobile bind` to generate language +bindings for Java and Objective-C. Building a library does not +require the app package. The `gomobile bind` command produces output +that you can include in an Android Studio or Xcode project. For more +on language bindings, see https://golang.org/x/mobile/cmd/gobind. + +The second way is to write an app entirely in Go. The APIs are limited +to those that are portable between both Android and iOS, in particular +OpenGL, audio, and other Android NDK-like APIs. An all-Go app should +use this app package to initialize the app, manage its lifecycle, and +receive events. + +# Building apps + +Apps written entirely in Go have a main function, and can be built +with `gomobile build`, which directly produces runnable output for +Android and iOS. + +The gomobile tool can get installed with go get. For reference, see +https://golang.org/x/mobile/cmd/gomobile. + +For detailed instructions and documentation, see +https://golang.org/wiki/Mobile. + +# Event processing in Native Apps + +The Go runtime is initialized on Android when NativeActivity onCreate is +called, and on iOS when the process starts. In both cases, Go init functions +run before the app lifecycle has started. + +An app is expected to call the Main function in main.main. When the function +exits, the app exits. Inside the func passed to Main, call Filter on every +event received, and then switch on its type. Registered filters run when the +event is received, not when it is sent, so that filters run in the same +goroutine as other code that calls OpenGL. + + package main + + import ( + "log" + + "golang.org/x/mobile/app" + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/paint" + ) + + func main() { + app.Main(func(a app.App) { + for e := range a.Events() { + switch e := a.Filter(e).(type) { + case lifecycle.Event: + // ... + case paint.Event: + log.Print("Call OpenGL here.") + a.Publish() + } + } + }) + } + +An event is represented by the empty interface type interface{}. Any value can +be an event. Commonly used types include Event types defined by the following +packages: + - golang.org/x/mobile/event/lifecycle + - golang.org/x/mobile/event/mouse + - golang.org/x/mobile/event/paint + - golang.org/x/mobile/event/size + - golang.org/x/mobile/event/touch + +For example, touch.Event is the type that represents touch events. Other +packages may define their own events, and send them on an app's event channel. + +Other packages can also register event filters, e.g. to manage resources in +response to lifecycle events. Such packages should call: + + app.RegisterFilter(etc) + +in an init function inside that package. +*/ +package app diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn.go b/vendor/golang.org/x/mobile/app/internal/callfn/callfn.go new file mode 100644 index 00000000..ecc3d456 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/internal/callfn/callfn.go @@ -0,0 +1,16 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build android && (arm || 386 || amd64 || arm64) + +// Package callfn provides an android entry point. +// +// It is a separate package from app because it contains Go assembly, +// which does not compile in a package using cgo. +package callfn + +// CallFn calls a zero-argument function by its program counter. +// It is only intended for calling main.main. Using it for +// anything else will not end well. +func CallFn(fn uintptr) diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_386.s b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_386.s new file mode 100644 index 00000000..d2bb54f1 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_386.s @@ -0,0 +1,11 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" +#include "funcdata.h" + +TEXT ·CallFn(SB),$0-4 + MOVL fn+0(FP), AX + CALL AX + RET diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_amd64.s b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_amd64.s new file mode 100644 index 00000000..8769604a --- /dev/null +++ b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_amd64.s @@ -0,0 +1,11 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" +#include "funcdata.h" + +TEXT ·CallFn(SB),$0-8 + MOVQ fn+0(FP), AX + CALL AX + RET diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm.s b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm.s new file mode 100644 index 00000000..d71f748d --- /dev/null +++ b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm.s @@ -0,0 +1,11 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" +#include "funcdata.h" + +TEXT ·CallFn(SB),$0-4 + MOVW fn+0(FP), R0 + BL (R0) + RET diff --git a/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm64.s b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm64.s new file mode 100644 index 00000000..545ad500 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/internal/callfn/callfn_arm64.s @@ -0,0 +1,11 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" +#include "funcdata.h" + +TEXT ·CallFn(SB),$0-8 + MOVD fn+0(FP), R0 + BL (R0) + RET diff --git a/vendor/golang.org/x/mobile/app/shiny.go b/vendor/golang.org/x/mobile/app/shiny.go new file mode 100644 index 00000000..0b4e3e55 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/shiny.go @@ -0,0 +1,83 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build windows + +package app + +import ( + "log" + + "golang.org/x/exp/shiny/driver/gldriver" + "golang.org/x/exp/shiny/screen" + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/mouse" + "golang.org/x/mobile/event/touch" + "golang.org/x/mobile/gl" +) + +func main(f func(a App)) { + gldriver.Main(func(s screen.Screen) { + w, err := s.NewWindow(nil) + if err != nil { + log.Fatal(err) + } + defer w.Release() + + theApp.glctx = nil + theApp.worker = nil // handled by shiny + + go func() { + for range theApp.publish { + res := w.Publish() + theApp.publishResult <- PublishResult{ + BackBufferPreserved: res.BackBufferPreserved, + } + } + }() + + donec := make(chan struct{}) + go func() { + // close the donec channel in a defer statement + // so that we could still be able to return even + // if f panics. + defer close(donec) + + f(theApp) + }() + + for { + select { + case <-donec: + return + default: + theApp.Send(convertEvent(w.NextEvent())) + } + } + }) +} + +func convertEvent(e interface{}) interface{} { + switch e := e.(type) { + case lifecycle.Event: + if theApp.glctx == nil { + theApp.glctx = e.DrawContext.(gl.Context) + } + case mouse.Event: + te := touch.Event{ + X: e.X, + Y: e.Y, + } + switch e.Direction { + case mouse.DirNone: + te.Type = touch.TypeMove + case mouse.DirPress: + te.Type = touch.TypeBegin + case mouse.DirRelease: + te.Type = touch.TypeEnd + } + return te + } + return e +} diff --git a/vendor/golang.org/x/mobile/app/x11.c b/vendor/golang.org/x/mobile/app/x11.c new file mode 100644 index 00000000..755bb244 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/x11.c @@ -0,0 +1,175 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && !android +// +build linux,!android + +#include "_cgo_export.h" +#include +#include +#include +#include +#include +#include + +static Atom wm_delete_window; + +static Window +new_window(Display *x_dpy, EGLDisplay e_dpy, int w, int h, EGLContext *ctx, EGLSurface *surf) { + static const EGLint attribs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_NONE + }; + EGLConfig config; + EGLint num_configs; + if (!eglChooseConfig(e_dpy, attribs, &config, 1, &num_configs)) { + fprintf(stderr, "eglChooseConfig failed\n"); + exit(1); + } + EGLint vid; + if (!eglGetConfigAttrib(e_dpy, config, EGL_NATIVE_VISUAL_ID, &vid)) { + fprintf(stderr, "eglGetConfigAttrib failed\n"); + exit(1); + } + + XVisualInfo visTemplate; + visTemplate.visualid = vid; + int num_visuals; + XVisualInfo *visInfo = XGetVisualInfo(x_dpy, VisualIDMask, &visTemplate, &num_visuals); + if (!visInfo) { + fprintf(stderr, "XGetVisualInfo failed\n"); + exit(1); + } + + Window root = RootWindow(x_dpy, DefaultScreen(x_dpy)); + XSetWindowAttributes attr; + + attr.colormap = XCreateColormap(x_dpy, root, visInfo->visual, AllocNone); + if (!attr.colormap) { + fprintf(stderr, "XCreateColormap failed\n"); + exit(1); + } + + attr.event_mask = StructureNotifyMask | ExposureMask | + ButtonPressMask | ButtonReleaseMask | ButtonMotionMask; + Window win = XCreateWindow( + x_dpy, root, 0, 0, w, h, 0, visInfo->depth, InputOutput, + visInfo->visual, CWColormap | CWEventMask, &attr); + XFree(visInfo); + + XSizeHints sizehints; + sizehints.width = w; + sizehints.height = h; + sizehints.flags = USSize; + XSetNormalHints(x_dpy, win, &sizehints); + XSetStandardProperties(x_dpy, win, "App", "App", None, (char **)NULL, 0, &sizehints); + + static const EGLint ctx_attribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + *ctx = eglCreateContext(e_dpy, config, EGL_NO_CONTEXT, ctx_attribs); + if (!*ctx) { + fprintf(stderr, "eglCreateContext failed\n"); + exit(1); + } + *surf = eglCreateWindowSurface(e_dpy, config, win, NULL); + if (!*surf) { + fprintf(stderr, "eglCreateWindowSurface failed\n"); + exit(1); + } + return win; +} + +Display *x_dpy; +EGLDisplay e_dpy; +EGLContext e_ctx; +EGLSurface e_surf; +Window win; + +void +createWindow(void) { + x_dpy = XOpenDisplay(NULL); + if (!x_dpy) { + fprintf(stderr, "XOpenDisplay failed\n"); + exit(1); + } + e_dpy = eglGetDisplay(x_dpy); + if (!e_dpy) { + fprintf(stderr, "eglGetDisplay failed\n"); + exit(1); + } + EGLint e_major, e_minor; + if (!eglInitialize(e_dpy, &e_major, &e_minor)) { + fprintf(stderr, "eglInitialize failed\n"); + exit(1); + } + eglBindAPI(EGL_OPENGL_ES_API); + win = new_window(x_dpy, e_dpy, 600, 800, &e_ctx, &e_surf); + + wm_delete_window = XInternAtom(x_dpy, "WM_DELETE_WINDOW", True); + if (wm_delete_window != None) { + XSetWMProtocols(x_dpy, win, &wm_delete_window, 1); + } + + XMapWindow(x_dpy, win); + if (!eglMakeCurrent(e_dpy, e_surf, e_surf, e_ctx)) { + fprintf(stderr, "eglMakeCurrent failed\n"); + exit(1); + } + + // Window size and DPI should be initialized before starting app. + XEvent ev; + while (1) { + if (XCheckMaskEvent(x_dpy, StructureNotifyMask, &ev) == False) { + continue; + } + if (ev.type == ConfigureNotify) { + onResize(ev.xconfigure.width, ev.xconfigure.height); + break; + } + } +} + +void +processEvents(void) { + while (XPending(x_dpy)) { + XEvent ev; + XNextEvent(x_dpy, &ev); + switch (ev.type) { + case ButtonPress: + onTouchBegin((float)ev.xbutton.x, (float)ev.xbutton.y); + break; + case ButtonRelease: + onTouchEnd((float)ev.xbutton.x, (float)ev.xbutton.y); + break; + case MotionNotify: + onTouchMove((float)ev.xmotion.x, (float)ev.xmotion.y); + break; + case ConfigureNotify: + onResize(ev.xconfigure.width, ev.xconfigure.height); + break; + case ClientMessage: + if (wm_delete_window != None && (Atom)ev.xclient.data.l[0] == wm_delete_window) { + onStop(); + return; + } + break; + } + } +} + +void +swapBuffers(void) { + if (eglSwapBuffers(e_dpy, e_surf) == EGL_FALSE) { + fprintf(stderr, "eglSwapBuffer failed\n"); + exit(1); + } +} diff --git a/vendor/golang.org/x/mobile/app/x11.go b/vendor/golang.org/x/mobile/app/x11.go new file mode 100644 index 00000000..7e85e137 --- /dev/null +++ b/vendor/golang.org/x/mobile/app/x11.go @@ -0,0 +1,126 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build linux && !android + +package app + +/* +Simple on-screen app debugging for X11. Not an officially supported +development target for apps, as screens with mice are very different +than screens with touch panels. +*/ + +/* +#cgo LDFLAGS: -lEGL -lGLESv2 -lX11 + +void createWindow(void); +void processEvents(void); +void swapBuffers(void); +*/ +import "C" +import ( + "runtime" + "time" + + "golang.org/x/mobile/event/lifecycle" + "golang.org/x/mobile/event/paint" + "golang.org/x/mobile/event/size" + "golang.org/x/mobile/event/touch" + "golang.org/x/mobile/geom" +) + +func init() { + theApp.registerGLViewportFilter() +} + +func main(f func(App)) { + runtime.LockOSThread() + + workAvailable := theApp.worker.WorkAvailable() + + C.createWindow() + + // TODO: send lifecycle events when e.g. the X11 window is iconified or moved off-screen. + theApp.sendLifecycle(lifecycle.StageFocused) + + // TODO: translate X11 expose events to shiny paint events, instead of + // sending this synthetic paint event as a hack. + theApp.eventsIn <- paint.Event{} + + donec := make(chan struct{}) + go func() { + // close the donec channel in a defer statement + // so that we could still be able to return even + // if f panics. + defer close(donec) + + f(theApp) + }() + + // TODO: can we get the actual vsync signal? + ticker := time.NewTicker(time.Second / 60) + defer ticker.Stop() + var tc <-chan time.Time + + for { + select { + case <-donec: + return + case <-workAvailable: + theApp.worker.DoWork() + case <-theApp.publish: + C.swapBuffers() + tc = ticker.C + case <-tc: + tc = nil + theApp.publishResult <- PublishResult{} + } + C.processEvents() + } +} + +//export onResize +func onResize(w, h int) { + // TODO(nigeltao): don't assume 72 DPI. DisplayWidth and DisplayWidthMM + // is probably the best place to start looking. + pixelsPerPt := float32(1) + theApp.eventsIn <- size.Event{ + WidthPx: w, + HeightPx: h, + WidthPt: geom.Pt(w), + HeightPt: geom.Pt(h), + PixelsPerPt: pixelsPerPt, + } +} + +func sendTouch(t touch.Type, x, y float32) { + theApp.eventsIn <- touch.Event{ + X: x, + Y: y, + Sequence: 0, // TODO: button?? + Type: t, + } +} + +//export onTouchBegin +func onTouchBegin(x, y float32) { sendTouch(touch.TypeBegin, x, y) } + +//export onTouchMove +func onTouchMove(x, y float32) { sendTouch(touch.TypeMove, x, y) } + +//export onTouchEnd +func onTouchEnd(x, y float32) { sendTouch(touch.TypeEnd, x, y) } + +var stopped bool + +//export onStop +func onStop() { + if stopped { + return + } + stopped = true + theApp.sendLifecycle(lifecycle.StageDead) + theApp.eventsIn <- stopPumping{} +} diff --git a/vendor/golang.org/x/mobile/event/key/code_string.go b/vendor/golang.org/x/mobile/event/key/code_string.go new file mode 100644 index 00000000..6af78b30 --- /dev/null +++ b/vendor/golang.org/x/mobile/event/key/code_string.go @@ -0,0 +1,60 @@ +// Code generated by "stringer -type=Code"; DO NOT EDIT + +package key + +import "fmt" + +const ( + _Code_name_0 = "CodeUnknown" + _Code_name_1 = "CodeACodeBCodeCCodeDCodeECodeFCodeGCodeHCodeICodeJCodeKCodeLCodeMCodeNCodeOCodePCodeQCodeRCodeSCodeTCodeUCodeVCodeWCodeXCodeYCodeZCode1Code2Code3Code4Code5Code6Code7Code8Code9Code0CodeReturnEnterCodeEscapeCodeDeleteBackspaceCodeTabCodeSpacebarCodeHyphenMinusCodeEqualSignCodeLeftSquareBracketCodeRightSquareBracketCodeBackslash" + _Code_name_2 = "CodeSemicolonCodeApostropheCodeGraveAccentCodeCommaCodeFullStopCodeSlashCodeCapsLockCodeF1CodeF2CodeF3CodeF4CodeF5CodeF6CodeF7CodeF8CodeF9CodeF10CodeF11CodeF12" + _Code_name_3 = "CodePauseCodeInsertCodeHomeCodePageUpCodeDeleteForwardCodeEndCodePageDownCodeRightArrowCodeLeftArrowCodeDownArrowCodeUpArrowCodeKeypadNumLockCodeKeypadSlashCodeKeypadAsteriskCodeKeypadHyphenMinusCodeKeypadPlusSignCodeKeypadEnterCodeKeypad1CodeKeypad2CodeKeypad3CodeKeypad4CodeKeypad5CodeKeypad6CodeKeypad7CodeKeypad8CodeKeypad9CodeKeypad0CodeKeypadFullStop" + _Code_name_4 = "CodeKeypadEqualSignCodeF13CodeF14CodeF15CodeF16CodeF17CodeF18CodeF19CodeF20CodeF21CodeF22CodeF23CodeF24" + _Code_name_5 = "CodeHelp" + _Code_name_6 = "CodeMuteCodeVolumeUpCodeVolumeDown" + _Code_name_7 = "CodeLeftControlCodeLeftShiftCodeLeftAltCodeLeftGUICodeRightControlCodeRightShiftCodeRightAltCodeRightGUI" + _Code_name_8 = "CodeCompose" +) + +var ( + _Code_index_0 = [...]uint8{0, 11} + _Code_index_1 = [...]uint16{0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100, 105, 110, 115, 120, 125, 130, 135, 140, 145, 150, 155, 160, 165, 170, 175, 180, 195, 205, 224, 231, 243, 258, 271, 292, 314, 327} + _Code_index_2 = [...]uint8{0, 13, 27, 42, 51, 63, 72, 84, 90, 96, 102, 108, 114, 120, 126, 132, 138, 145, 152, 159} + _Code_index_3 = [...]uint16{0, 9, 19, 27, 37, 54, 61, 73, 87, 100, 113, 124, 141, 156, 174, 195, 213, 228, 239, 250, 261, 272, 283, 294, 305, 316, 327, 338, 356} + _Code_index_4 = [...]uint8{0, 19, 26, 33, 40, 47, 54, 61, 68, 75, 82, 89, 96, 103} + _Code_index_5 = [...]uint8{0, 8} + _Code_index_6 = [...]uint8{0, 8, 20, 34} + _Code_index_7 = [...]uint8{0, 15, 28, 39, 50, 66, 80, 92, 104} + _Code_index_8 = [...]uint8{0, 11} +) + +func (i Code) String() string { + switch { + case i == 0: + return _Code_name_0 + case 4 <= i && i <= 49: + i -= 4 + return _Code_name_1[_Code_index_1[i]:_Code_index_1[i+1]] + case 51 <= i && i <= 69: + i -= 51 + return _Code_name_2[_Code_index_2[i]:_Code_index_2[i+1]] + case 72 <= i && i <= 99: + i -= 72 + return _Code_name_3[_Code_index_3[i]:_Code_index_3[i+1]] + case 103 <= i && i <= 115: + i -= 103 + return _Code_name_4[_Code_index_4[i]:_Code_index_4[i+1]] + case i == 117: + return _Code_name_5 + case 127 <= i && i <= 129: + i -= 127 + return _Code_name_6[_Code_index_6[i]:_Code_index_6[i+1]] + case 224 <= i && i <= 231: + i -= 224 + return _Code_name_7[_Code_index_7[i]:_Code_index_7[i+1]] + case i == 65536: + return _Code_name_8 + default: + return fmt.Sprintf("Code(%d)", i) + } +} diff --git a/vendor/golang.org/x/mobile/event/key/key.go b/vendor/golang.org/x/mobile/event/key/key.go new file mode 100644 index 00000000..d70f1c34 --- /dev/null +++ b/vendor/golang.org/x/mobile/event/key/key.go @@ -0,0 +1,270 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:generate stringer -type=Code + +// Package key defines an event for physical keyboard keys. +// +// On-screen software keyboards do not send key events. +// +// See the golang.org/x/mobile/app package for details on the event model. +package key + +import ( + "fmt" + "strings" +) + +// Event is a key event. +type Event struct { + // Rune is the meaning of the key event as determined by the + // operating system. The mapping is determined by system-dependent + // current layout, modifiers, lock-states, etc. + // + // If non-negative, it is a Unicode codepoint: pressing the 'a' key + // generates different Runes 'a' or 'A' (but the same Code) depending on + // the state of the shift key. + // + // If -1, the key does not generate a Unicode codepoint. To distinguish + // them, look at Code. + Rune rune + + // Code is the identity of the physical key relative to a notional + // "standard" keyboard, independent of current layout, modifiers, + // lock-states, etc + // + // For standard key codes, its value matches USB HID key codes. + // Compare its value to uint32-typed constants in this package, such + // as CodeLeftShift and CodeEscape. + // + // Pressing the regular '2' key and number-pad '2' key (with Num-Lock) + // generate different Codes (but the same Rune). + Code Code + + // Modifiers is a bitmask representing a set of modifier keys: ModShift, + // ModAlt, etc. + Modifiers Modifiers + + // Direction is the direction of the key event: DirPress, DirRelease, + // or DirNone (for key repeats). + Direction Direction + + // TODO: add a Device ID, for multiple input devices? + // TODO: add a time.Time? +} + +func (e Event) String() string { + if e.Rune >= 0 { + return fmt.Sprintf("key.Event{%q (%v), %v, %v}", e.Rune, e.Code, e.Modifiers, e.Direction) + } + return fmt.Sprintf("key.Event{(%v), %v, %v}", e.Code, e.Modifiers, e.Direction) +} + +// Direction is the direction of the key event. +type Direction uint8 + +const ( + DirNone Direction = 0 + DirPress Direction = 1 + DirRelease Direction = 2 +) + +// Modifiers is a bitmask representing a set of modifier keys. +type Modifiers uint32 + +const ( + ModShift Modifiers = 1 << 0 + ModControl Modifiers = 1 << 1 + ModAlt Modifiers = 1 << 2 + ModMeta Modifiers = 1 << 3 // called "Command" on OS X +) + +// Code is the identity of a key relative to a notional "standard" keyboard. +type Code uint32 + +// Physical key codes. +// +// For standard key codes, its value matches USB HID key codes. +// TODO: add missing codes. +const ( + CodeUnknown Code = 0 + + CodeA Code = 4 + CodeB Code = 5 + CodeC Code = 6 + CodeD Code = 7 + CodeE Code = 8 + CodeF Code = 9 + CodeG Code = 10 + CodeH Code = 11 + CodeI Code = 12 + CodeJ Code = 13 + CodeK Code = 14 + CodeL Code = 15 + CodeM Code = 16 + CodeN Code = 17 + CodeO Code = 18 + CodeP Code = 19 + CodeQ Code = 20 + CodeR Code = 21 + CodeS Code = 22 + CodeT Code = 23 + CodeU Code = 24 + CodeV Code = 25 + CodeW Code = 26 + CodeX Code = 27 + CodeY Code = 28 + CodeZ Code = 29 + + Code1 Code = 30 + Code2 Code = 31 + Code3 Code = 32 + Code4 Code = 33 + Code5 Code = 34 + Code6 Code = 35 + Code7 Code = 36 + Code8 Code = 37 + Code9 Code = 38 + Code0 Code = 39 + + CodeReturnEnter Code = 40 + CodeEscape Code = 41 + CodeDeleteBackspace Code = 42 + CodeTab Code = 43 + CodeSpacebar Code = 44 + CodeHyphenMinus Code = 45 // - + CodeEqualSign Code = 46 // = + CodeLeftSquareBracket Code = 47 // [ + CodeRightSquareBracket Code = 48 // ] + CodeBackslash Code = 49 // \ + CodeSemicolon Code = 51 // ; + CodeApostrophe Code = 52 // ' + CodeGraveAccent Code = 53 // ` + CodeComma Code = 54 // , + CodeFullStop Code = 55 // . + CodeSlash Code = 56 // / + CodeCapsLock Code = 57 + + CodeF1 Code = 58 + CodeF2 Code = 59 + CodeF3 Code = 60 + CodeF4 Code = 61 + CodeF5 Code = 62 + CodeF6 Code = 63 + CodeF7 Code = 64 + CodeF8 Code = 65 + CodeF9 Code = 66 + CodeF10 Code = 67 + CodeF11 Code = 68 + CodeF12 Code = 69 + + CodePause Code = 72 + CodeInsert Code = 73 + CodeHome Code = 74 + CodePageUp Code = 75 + CodeDeleteForward Code = 76 + CodeEnd Code = 77 + CodePageDown Code = 78 + + CodeRightArrow Code = 79 + CodeLeftArrow Code = 80 + CodeDownArrow Code = 81 + CodeUpArrow Code = 82 + + CodeKeypadNumLock Code = 83 + CodeKeypadSlash Code = 84 // / + CodeKeypadAsterisk Code = 85 // * + CodeKeypadHyphenMinus Code = 86 // - + CodeKeypadPlusSign Code = 87 // + + CodeKeypadEnter Code = 88 + CodeKeypad1 Code = 89 + CodeKeypad2 Code = 90 + CodeKeypad3 Code = 91 + CodeKeypad4 Code = 92 + CodeKeypad5 Code = 93 + CodeKeypad6 Code = 94 + CodeKeypad7 Code = 95 + CodeKeypad8 Code = 96 + CodeKeypad9 Code = 97 + CodeKeypad0 Code = 98 + CodeKeypadFullStop Code = 99 // . + CodeKeypadEqualSign Code = 103 // = + + CodeF13 Code = 104 + CodeF14 Code = 105 + CodeF15 Code = 106 + CodeF16 Code = 107 + CodeF17 Code = 108 + CodeF18 Code = 109 + CodeF19 Code = 110 + CodeF20 Code = 111 + CodeF21 Code = 112 + CodeF22 Code = 113 + CodeF23 Code = 114 + CodeF24 Code = 115 + + CodeHelp Code = 117 + + CodeMute Code = 127 + CodeVolumeUp Code = 128 + CodeVolumeDown Code = 129 + + CodeLeftControl Code = 224 + CodeLeftShift Code = 225 + CodeLeftAlt Code = 226 + CodeLeftGUI Code = 227 + CodeRightControl Code = 228 + CodeRightShift Code = 229 + CodeRightAlt Code = 230 + CodeRightGUI Code = 231 + + // The following codes are not part of the standard USB HID Usage IDs for + // keyboards. See http://www.usb.org/developers/hidpage/Hut1_12v2.pdf + // + // Usage IDs are uint16s, so these non-standard values start at 0x10000. + + // CodeCompose is the Code for a compose key, sometimes called a multi key, + // used to input non-ASCII characters such as ñ being composed of n and ~. + // + // See https://en.wikipedia.org/wiki/Compose_key + CodeCompose Code = 0x10000 +) + +// TODO: Given we use runes outside the unicode space, should we provide a +// printing function? Related: it's a little unfortunate that printing a +// key.Event with %v gives not very readable output like: +// {100 7 key.Modifiers() Press} + +var mods = [...]struct { + m Modifiers + s string +}{ + {ModShift, "Shift"}, + {ModControl, "Control"}, + {ModAlt, "Alt"}, + {ModMeta, "Meta"}, +} + +func (m Modifiers) String() string { + var match []string + for _, mod := range mods { + if mod.m&m != 0 { + match = append(match, mod.s) + } + } + return "key.Modifiers(" + strings.Join(match, "|") + ")" +} + +func (d Direction) String() string { + switch d { + case DirNone: + return "None" + case DirPress: + return "Press" + case DirRelease: + return "Release" + default: + return fmt.Sprintf("key.Direction(%d)", d) + } +} diff --git a/vendor/golang.org/x/mobile/event/lifecycle/lifecycle.go b/vendor/golang.org/x/mobile/event/lifecycle/lifecycle.go new file mode 100644 index 00000000..58de2c41 --- /dev/null +++ b/vendor/golang.org/x/mobile/event/lifecycle/lifecycle.go @@ -0,0 +1,136 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package lifecycle defines an event for an app's lifecycle. +// +// The app lifecycle consists of moving back and forth between an ordered +// sequence of stages. For example, being at a stage greater than or equal to +// StageVisible means that the app is visible on the screen. +// +// A lifecycle event is a change from one stage to another, which crosses every +// intermediate stage. For example, changing from StageAlive to StageFocused +// implicitly crosses StageVisible. +// +// Crosses can be in a positive or negative direction. A positive crossing of +// StageFocused means that the app has gained the focus. A negative crossing +// means it has lost the focus. +// +// See the golang.org/x/mobile/app package for details on the event model. +package lifecycle + +import ( + "fmt" +) + +// Cross is whether a lifecycle stage was crossed. +type Cross uint32 + +func (c Cross) String() string { + switch c { + case CrossOn: + return "on" + case CrossOff: + return "off" + } + return "none" +} + +const ( + CrossNone Cross = 0 + CrossOn Cross = 1 + CrossOff Cross = 2 +) + +// Event is a lifecycle change from an old stage to a new stage. +type Event struct { + From, To Stage + + // DrawContext is the state used for painting, if any is valid. + // + // For OpenGL apps, a non-nil DrawContext is a gl.Context. + // + // TODO: make this an App method if we move away from an event channel? + DrawContext interface{} +} + +func (e Event) String() string { + return fmt.Sprintf("lifecycle.Event{From:%v, To:%v, DrawContext:%v}", e.From, e.To, e.DrawContext) +} + +// Crosses reports whether the transition from From to To crosses the stage s: +// - It returns CrossOn if it does, and the lifecycle change is positive. +// - It returns CrossOff if it does, and the lifecycle change is negative. +// - Otherwise, it returns CrossNone. +// +// See the documentation for Stage for more discussion of positive and negative +// crosses. +func (e Event) Crosses(s Stage) Cross { + switch { + case e.From < s && e.To >= s: + return CrossOn + case e.From >= s && e.To < s: + return CrossOff + } + return CrossNone +} + +// Stage is a stage in the app's lifecycle. The values are ordered, so that a +// lifecycle change from stage From to stage To implicitly crosses every stage +// in the range (min, max], exclusive on the low end and inclusive on the high +// end, where min is the minimum of From and To, and max is the maximum. +// +// The documentation for individual stages talk about positive and negative +// crosses. A positive lifecycle change is one where its From stage is less +// than its To stage. Similarly, a negative lifecycle change is one where From +// is greater than To. Thus, a positive lifecycle change crosses every stage in +// the range (From, To] in increasing order, and a negative lifecycle change +// crosses every stage in the range (To, From] in decreasing order. +type Stage uint32 + +// TODO: how does iOS map to these stages? What do cross-platform mobile +// abstractions do? + +const ( + // StageDead is the zero stage. No lifecycle change crosses this stage, + // but: + // - A positive change from this stage is the very first lifecycle change. + // - A negative change to this stage is the very last lifecycle change. + StageDead Stage = iota + + // StageAlive means that the app is alive. + // - A positive cross means that the app has been created. + // - A negative cross means that the app is being destroyed. + // Each cross, either from or to StageDead, will occur only once. + // On Android, these correspond to onCreate and onDestroy. + StageAlive + + // StageVisible means that the app window is visible. + // - A positive cross means that the app window has become visible. + // - A negative cross means that the app window has become invisible. + // On Android, these correspond to onStart and onStop. + // On Desktop, an app window can become invisible if e.g. it is minimized, + // unmapped, or not on a visible workspace. + StageVisible + + // StageFocused means that the app window has the focus. + // - A positive cross means that the app window has gained the focus. + // - A negative cross means that the app window has lost the focus. + // On Android, these correspond to onResume and onFreeze. + StageFocused +) + +func (s Stage) String() string { + switch s { + case StageDead: + return "StageDead" + case StageAlive: + return "StageAlive" + case StageVisible: + return "StageVisible" + case StageFocused: + return "StageFocused" + default: + return fmt.Sprintf("lifecycle.Stage(%d)", s) + } +} diff --git a/vendor/golang.org/x/mobile/event/mouse/mouse.go b/vendor/golang.org/x/mobile/event/mouse/mouse.go new file mode 100644 index 00000000..e98131d3 --- /dev/null +++ b/vendor/golang.org/x/mobile/event/mouse/mouse.go @@ -0,0 +1,90 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package mouse defines an event for mouse input. +// +// See the golang.org/x/mobile/app package for details on the event model. +package mouse + +import ( + "fmt" + + "golang.org/x/mobile/event/key" +) + +// Event is a mouse event. +type Event struct { + // X and Y are the mouse location, in pixels. + X, Y float32 + + // Button is the mouse button being pressed or released. Its value may be + // zero, for a mouse move or drag without any button change. + Button Button + + // TODO: have a field to hold what other buttons are down, for detecting + // drags or button-chords. + + // Modifiers is a bitmask representing a set of modifier keys: + // key.ModShift, key.ModAlt, etc. + Modifiers key.Modifiers + + // Direction is the direction of the mouse event: DirPress, DirRelease, + // or DirNone (for mouse moves or drags). + Direction Direction + + // TODO: add a Device ID, for multiple input devices? + // TODO: add a time.Time? +} + +// Button is a mouse button. +type Button int32 + +// IsWheel reports whether the button is for a scroll wheel. +func (b Button) IsWheel() bool { + return b < 0 +} + +// TODO: have a separate axis concept for wheel up/down? How does that relate +// to joystick events? + +const ( + ButtonNone Button = +0 + ButtonLeft Button = +1 + ButtonMiddle Button = +2 + ButtonRight Button = +3 + + ButtonWheelUp Button = -1 + ButtonWheelDown Button = -2 + ButtonWheelLeft Button = -3 + ButtonWheelRight Button = -4 +) + +// Direction is the direction of the mouse event. +type Direction uint8 + +const ( + DirNone Direction = 0 + DirPress Direction = 1 + DirRelease Direction = 2 + // DirStep is a simultaneous press and release, such as a single step of a + // mouse wheel. + // + // Its value equals DirPress | DirRelease. + DirStep Direction = 3 +) + +func (d Direction) String() string { + switch d { + case DirNone: + return "None" + case DirPress: + return "Press" + case DirRelease: + return "Release" + case DirStep: + return "Step" + default: + return fmt.Sprintf("mouse.Direction(%d)", d) + } +} diff --git a/vendor/golang.org/x/mobile/event/paint/paint.go b/vendor/golang.org/x/mobile/event/paint/paint.go new file mode 100644 index 00000000..179136c4 --- /dev/null +++ b/vendor/golang.org/x/mobile/event/paint/paint.go @@ -0,0 +1,24 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package paint defines an event for the app being ready to paint. +// +// See the golang.org/x/mobile/app package for details on the event model. +package paint + +// Event indicates that the app is ready to paint the next frame of the GUI. +// +// A frame is completed by calling the App's Publish method. +type Event struct { + // External is true for paint events sent by the screen driver. + // + // An external event may be sent at any time in response to an + // operating system event, for example the window opened, was + // resized, or the screen memory was lost. + // + // Programs actively drawing to the screen as fast as vsync allows + // should ignore external paint events to avoid a backlog of paint + // events building up. + External bool +} diff --git a/vendor/golang.org/x/mobile/event/size/size.go b/vendor/golang.org/x/mobile/event/size/size.go new file mode 100644 index 00000000..4c4070b4 --- /dev/null +++ b/vendor/golang.org/x/mobile/event/size/size.go @@ -0,0 +1,92 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package size defines an event for the dimensions, physical resolution and +// orientation of the app's window. +// +// See the golang.org/x/mobile/app package for details on the event model. +package size + +import ( + "image" + + "golang.org/x/mobile/geom" +) + +// Event holds the dimensions, physical resolution and orientation of the app's +// window. +type Event struct { + // WidthPx and HeightPx are the window's dimensions in pixels. + WidthPx, HeightPx int + + // WidthPt and HeightPt are the window's physical dimensions in points + // (1/72 of an inch). + // + // The values are based on PixelsPerPt and are therefore approximate, as + // per the comment on PixelsPerPt. + WidthPt, HeightPt geom.Pt + + // PixelsPerPt is the window's physical resolution. It is the number of + // pixels in a single geom.Pt, from the golang.org/x/mobile/geom package. + // + // There are a wide variety of pixel densities in existing phones and + // tablets, so apps should be written to expect various non-integer + // PixelsPerPt values. In general, work in geom.Pt. + // + // The value is approximate, in that the OS, drivers or hardware may report + // approximate or quantized values. An N x N pixel square should be roughly + // 1 square inch for N = int(PixelsPerPt * 72), although different square + // lengths (in pixels) might be closer to 1 inch in practice. Nonetheless, + // this PixelsPerPt value should be consistent with e.g. the ratio of + // WidthPx to WidthPt. + PixelsPerPt float32 + + // Orientation is the orientation of the device screen. + Orientation Orientation +} + +// Size returns the window's size in pixels, at the time this size event was +// sent. +func (e Event) Size() image.Point { + return image.Point{e.WidthPx, e.HeightPx} +} + +// Bounds returns the window's bounds in pixels, at the time this size event +// was sent. +// +// The top-left pixel is always (0, 0). The bottom-right pixel is given by the +// width and height. +func (e Event) Bounds() image.Rectangle { + return image.Rectangle{Max: image.Point{e.WidthPx, e.HeightPx}} +} + +// Orientation is the orientation of the device screen. +type Orientation int + +const ( + // OrientationUnknown means device orientation cannot be determined. + // + // Equivalent on Android to Configuration.ORIENTATION_UNKNOWN + // and on iOS to: + // UIDeviceOrientationUnknown + // UIDeviceOrientationFaceUp + // UIDeviceOrientationFaceDown + OrientationUnknown Orientation = iota + + // OrientationPortrait is a device oriented so it is tall and thin. + // + // Equivalent on Android to Configuration.ORIENTATION_PORTRAIT + // and on iOS to: + // UIDeviceOrientationPortrait + // UIDeviceOrientationPortraitUpsideDown + OrientationPortrait + + // OrientationLandscape is a device oriented so it is short and wide. + // + // Equivalent on Android to Configuration.ORIENTATION_LANDSCAPE + // and on iOS to: + // UIDeviceOrientationLandscapeLeft + // UIDeviceOrientationLandscapeRight + OrientationLandscape +) diff --git a/vendor/golang.org/x/mobile/event/touch/touch.go b/vendor/golang.org/x/mobile/event/touch/touch.go new file mode 100644 index 00000000..94c4853a --- /dev/null +++ b/vendor/golang.org/x/mobile/event/touch/touch.go @@ -0,0 +1,72 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package touch defines an event for touch input. +// +// See the golang.org/x/mobile/app package for details on the event model. +package touch + +// The best source on android input events is the NDK: include/android/input.h +// +// iOS event handling guide: +// https://developer.apple.com/library/ios/documentation/EventHandling/Conceptual/EventHandlingiPhoneOS + +import ( + "fmt" +) + +// Event is a touch event. +type Event struct { + // X and Y are the touch location, in pixels. + X, Y float32 + + // Sequence is the sequence number. The same number is shared by all events + // in a sequence. A sequence begins with a single TypeBegin, is followed by + // zero or more TypeMoves, and ends with a single TypeEnd. A Sequence + // distinguishes concurrent sequences but its value is subsequently reused. + Sequence Sequence + + // Type is the touch type. + Type Type +} + +// Sequence identifies a sequence of touch events. +type Sequence int64 + +// Type describes the type of a touch event. +type Type byte + +const ( + // TypeBegin is a user first touching the device. + // + // On Android, this is a AMOTION_EVENT_ACTION_DOWN. + // On iOS, this is a call to touchesBegan. + TypeBegin Type = iota + + // TypeMove is a user dragging across the device. + // + // A TypeMove is delivered between a TypeBegin and TypeEnd. + // + // On Android, this is a AMOTION_EVENT_ACTION_MOVE. + // On iOS, this is a call to touchesMoved. + TypeMove + + // TypeEnd is a user no longer touching the device. + // + // On Android, this is a AMOTION_EVENT_ACTION_UP. + // On iOS, this is a call to touchesEnded. + TypeEnd +) + +func (t Type) String() string { + switch t { + case TypeBegin: + return "begin" + case TypeMove: + return "move" + case TypeEnd: + return "end" + } + return fmt.Sprintf("touch.Type(%d)", t) +} diff --git a/vendor/golang.org/x/mobile/geom/geom.go b/vendor/golang.org/x/mobile/geom/geom.go new file mode 100644 index 00000000..6b739446 --- /dev/null +++ b/vendor/golang.org/x/mobile/geom/geom.go @@ -0,0 +1,102 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package geom defines a two-dimensional coordinate system. + +The coordinate system is based on an left-handed Cartesian plane. +That is, X increases to the right and Y increases down. For (x,y), + + (0,0) → (1,0) + ↓ ↘ + (0,1) (1,1) + +The display window places the origin (0, 0) in the upper-left corner of +the screen. Positions on the plane are measured in typographic points, +1/72 of an inch, which is represented by the Pt type. + +Any interface that draws to the screen using types from the geom package +scales the number of pixels to maintain a Pt as 1/72 of an inch. +*/ +package geom + +/* +Notes on the various underlying coordinate systems. + +Both Android and iOS (UIKit) use upper-left-origin coordinate systems +with for events, however they have different units. + +UIKit measures distance in points. A point is a single-pixel on a +pre-Retina display. UIKit maintains a scale factor that to turn points +into pixels. On current retina devices, the scale factor is 2.0. + +A UIKit point does not correspond to a fixed physical distance, as the +iPhone has a 163 DPI/PPI (326 PPI retina) display, and the iPad has a +132 PPI (264 retina) display. Points are 32-bit floats. + +Even though point is the official UIKit term, they are commonly called +pixels. Indeed, the units were equivalent until the retina display was +introduced. + +N.b. as a UIKit point is unrelated to a typographic point, it is not +related to this packages's Pt and Point types. + +More details about iOS drawing: + +https://developer.apple.com/library/ios/documentation/2ddrawing/conceptual/drawingprintingios/GraphicsDrawingOverview/GraphicsDrawingOverview.html + +Android uses pixels. Sub-pixel precision is possible, so pixels are +represented as 32-bit floats. The ACONFIGURATION_DENSITY enum provides +the screen DPI/PPI, which varies frequently between devices. + +It would be tempting to adopt the pixel, given the clear pixel/DPI split +in the core android events API. However, the plot thickens: + +http://developer.android.com/training/multiscreen/screendensities.html + +Android promotes the notion of a density-independent pixel in many of +their interfaces, often prefixed by "dp". 1dp is a real physical length, +as "independent" means it is assumed to be 1/160th of an inch and is +adjusted for the current screen. + +In addition, android has a scale-indepdendent pixel used for expressing +a user's preferred text size. The user text size preference is a useful +notion not yet expressed in the geom package. + +For the sake of clarity when working across platforms, the geom package +tries to put distance between it and the word pixel. +*/ + +import "fmt" + +// Pt is a length. +// +// The unit Pt is a typographical point, 1/72 of an inch (0.3527 mm). +// +// It can be converted to a length in current device pixels by +// multiplying with PixelsPerPt after app initialization is complete. +type Pt float32 + +// Px converts the length to current device pixels. +func (p Pt) Px(pixelsPerPt float32) float32 { return float32(p) * pixelsPerPt } + +// String returns a string representation of p like "3.2pt". +func (p Pt) String() string { return fmt.Sprintf("%.2fpt", p) } + +// Point is a point in a two-dimensional plane. +type Point struct { + X, Y Pt +} + +// String returns a string representation of p like "(1.2,3.4)". +func (p Point) String() string { return fmt.Sprintf("(%.2f,%.2f)", p.X, p.Y) } + +// A Rectangle is region of points. +// The top-left point is Min, and the bottom-right point is Max. +type Rectangle struct { + Min, Max Point +} + +// String returns a string representation of r like "(3,4)-(6,5)". +func (r Rectangle) String() string { return r.Min.String() + "-" + r.Max.String() } diff --git a/vendor/golang.org/x/mobile/gl/consts.go b/vendor/golang.org/x/mobile/gl/consts.go new file mode 100644 index 00000000..62d93aab --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/consts.go @@ -0,0 +1,657 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gl + +/* +Partially generated from the Khronos OpenGL API specification in XML +format, which is covered by the license: + + Copyright (c) 2013-2014 The Khronos Group Inc. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and/or associated documentation files (the + "Materials"), to deal in the Materials without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Materials, and to + permit persons to whom the Materials are furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Materials. + + THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY + CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. + +*/ + +const ( + POINTS = 0x0000 + LINES = 0x0001 + LINE_LOOP = 0x0002 + LINE_STRIP = 0x0003 + TRIANGLES = 0x0004 + TRIANGLE_STRIP = 0x0005 + TRIANGLE_FAN = 0x0006 + SRC_COLOR = 0x0300 + ONE_MINUS_SRC_COLOR = 0x0301 + SRC_ALPHA = 0x0302 + ONE_MINUS_SRC_ALPHA = 0x0303 + DST_ALPHA = 0x0304 + ONE_MINUS_DST_ALPHA = 0x0305 + DST_COLOR = 0x0306 + ONE_MINUS_DST_COLOR = 0x0307 + SRC_ALPHA_SATURATE = 0x0308 + FUNC_ADD = 0x8006 + BLEND_EQUATION = 0x8009 + BLEND_EQUATION_RGB = 0x8009 + BLEND_EQUATION_ALPHA = 0x883D + FUNC_SUBTRACT = 0x800A + FUNC_REVERSE_SUBTRACT = 0x800B + BLEND_DST_RGB = 0x80C8 + BLEND_SRC_RGB = 0x80C9 + BLEND_DST_ALPHA = 0x80CA + BLEND_SRC_ALPHA = 0x80CB + CONSTANT_COLOR = 0x8001 + ONE_MINUS_CONSTANT_COLOR = 0x8002 + CONSTANT_ALPHA = 0x8003 + ONE_MINUS_CONSTANT_ALPHA = 0x8004 + BLEND_COLOR = 0x8005 + ARRAY_BUFFER = 0x8892 + ELEMENT_ARRAY_BUFFER = 0x8893 + ARRAY_BUFFER_BINDING = 0x8894 + ELEMENT_ARRAY_BUFFER_BINDING = 0x8895 + STREAM_DRAW = 0x88E0 + STATIC_DRAW = 0x88E4 + DYNAMIC_DRAW = 0x88E8 + BUFFER_SIZE = 0x8764 + BUFFER_USAGE = 0x8765 + CURRENT_VERTEX_ATTRIB = 0x8626 + FRONT = 0x0404 + BACK = 0x0405 + FRONT_AND_BACK = 0x0408 + TEXTURE_2D = 0x0DE1 + CULL_FACE = 0x0B44 + BLEND = 0x0BE2 + DITHER = 0x0BD0 + STENCIL_TEST = 0x0B90 + DEPTH_TEST = 0x0B71 + SCISSOR_TEST = 0x0C11 + POLYGON_OFFSET_FILL = 0x8037 + SAMPLE_ALPHA_TO_COVERAGE = 0x809E + SAMPLE_COVERAGE = 0x80A0 + INVALID_ENUM = 0x0500 + INVALID_VALUE = 0x0501 + INVALID_OPERATION = 0x0502 + OUT_OF_MEMORY = 0x0505 + CW = 0x0900 + CCW = 0x0901 + LINE_WIDTH = 0x0B21 + ALIASED_POINT_SIZE_RANGE = 0x846D + ALIASED_LINE_WIDTH_RANGE = 0x846E + CULL_FACE_MODE = 0x0B45 + FRONT_FACE = 0x0B46 + DEPTH_RANGE = 0x0B70 + DEPTH_WRITEMASK = 0x0B72 + DEPTH_CLEAR_VALUE = 0x0B73 + DEPTH_FUNC = 0x0B74 + STENCIL_CLEAR_VALUE = 0x0B91 + STENCIL_FUNC = 0x0B92 + STENCIL_FAIL = 0x0B94 + STENCIL_PASS_DEPTH_FAIL = 0x0B95 + STENCIL_PASS_DEPTH_PASS = 0x0B96 + STENCIL_REF = 0x0B97 + STENCIL_VALUE_MASK = 0x0B93 + STENCIL_WRITEMASK = 0x0B98 + STENCIL_BACK_FUNC = 0x8800 + STENCIL_BACK_FAIL = 0x8801 + STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802 + STENCIL_BACK_PASS_DEPTH_PASS = 0x8803 + STENCIL_BACK_REF = 0x8CA3 + STENCIL_BACK_VALUE_MASK = 0x8CA4 + STENCIL_BACK_WRITEMASK = 0x8CA5 + VIEWPORT = 0x0BA2 + SCISSOR_BOX = 0x0C10 + COLOR_CLEAR_VALUE = 0x0C22 + COLOR_WRITEMASK = 0x0C23 + UNPACK_ALIGNMENT = 0x0CF5 + PACK_ALIGNMENT = 0x0D05 + MAX_TEXTURE_SIZE = 0x0D33 + MAX_VIEWPORT_DIMS = 0x0D3A + SUBPIXEL_BITS = 0x0D50 + RED_BITS = 0x0D52 + GREEN_BITS = 0x0D53 + BLUE_BITS = 0x0D54 + ALPHA_BITS = 0x0D55 + DEPTH_BITS = 0x0D56 + STENCIL_BITS = 0x0D57 + POLYGON_OFFSET_UNITS = 0x2A00 + POLYGON_OFFSET_FACTOR = 0x8038 + TEXTURE_BINDING_2D = 0x8069 + SAMPLE_BUFFERS = 0x80A8 + SAMPLES = 0x80A9 + SAMPLE_COVERAGE_VALUE = 0x80AA + SAMPLE_COVERAGE_INVERT = 0x80AB + NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2 + COMPRESSED_TEXTURE_FORMATS = 0x86A3 + DONT_CARE = 0x1100 + FASTEST = 0x1101 + NICEST = 0x1102 + GENERATE_MIPMAP_HINT = 0x8192 + BYTE = 0x1400 + UNSIGNED_BYTE = 0x1401 + SHORT = 0x1402 + UNSIGNED_SHORT = 0x1403 + INT = 0x1404 + UNSIGNED_INT = 0x1405 + FLOAT = 0x1406 + FIXED = 0x140C + DEPTH_COMPONENT = 0x1902 + ALPHA = 0x1906 + RGB = 0x1907 + RGBA = 0x1908 + LUMINANCE = 0x1909 + LUMINANCE_ALPHA = 0x190A + UNSIGNED_SHORT_4_4_4_4 = 0x8033 + UNSIGNED_SHORT_5_5_5_1 = 0x8034 + UNSIGNED_SHORT_5_6_5 = 0x8363 + MAX_VERTEX_ATTRIBS = 0x8869 + MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB + MAX_VARYING_VECTORS = 0x8DFC + MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D + MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C + MAX_TEXTURE_IMAGE_UNITS = 0x8872 + MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD + SHADER_TYPE = 0x8B4F + DELETE_STATUS = 0x8B80 + LINK_STATUS = 0x8B82 + VALIDATE_STATUS = 0x8B83 + ATTACHED_SHADERS = 0x8B85 + ACTIVE_UNIFORMS = 0x8B86 + ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87 + ACTIVE_ATTRIBUTES = 0x8B89 + ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A + SHADING_LANGUAGE_VERSION = 0x8B8C + CURRENT_PROGRAM = 0x8B8D + NEVER = 0x0200 + LESS = 0x0201 + EQUAL = 0x0202 + LEQUAL = 0x0203 + GREATER = 0x0204 + NOTEQUAL = 0x0205 + GEQUAL = 0x0206 + ALWAYS = 0x0207 + KEEP = 0x1E00 + REPLACE = 0x1E01 + INCR = 0x1E02 + DECR = 0x1E03 + INVERT = 0x150A + INCR_WRAP = 0x8507 + DECR_WRAP = 0x8508 + VENDOR = 0x1F00 + RENDERER = 0x1F01 + VERSION = 0x1F02 + EXTENSIONS = 0x1F03 + NEAREST = 0x2600 + LINEAR = 0x2601 + NEAREST_MIPMAP_NEAREST = 0x2700 + LINEAR_MIPMAP_NEAREST = 0x2701 + NEAREST_MIPMAP_LINEAR = 0x2702 + LINEAR_MIPMAP_LINEAR = 0x2703 + TEXTURE_MAG_FILTER = 0x2800 + TEXTURE_MIN_FILTER = 0x2801 + TEXTURE_WRAP_S = 0x2802 + TEXTURE_WRAP_T = 0x2803 + TEXTURE = 0x1702 + TEXTURE_CUBE_MAP = 0x8513 + TEXTURE_BINDING_CUBE_MAP = 0x8514 + TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515 + TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516 + TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517 + TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518 + TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519 + TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A + MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C + TEXTURE0 = 0x84C0 + TEXTURE1 = 0x84C1 + TEXTURE2 = 0x84C2 + TEXTURE3 = 0x84C3 + TEXTURE4 = 0x84C4 + TEXTURE5 = 0x84C5 + TEXTURE6 = 0x84C6 + TEXTURE7 = 0x84C7 + TEXTURE8 = 0x84C8 + TEXTURE9 = 0x84C9 + TEXTURE10 = 0x84CA + TEXTURE11 = 0x84CB + TEXTURE12 = 0x84CC + TEXTURE13 = 0x84CD + TEXTURE14 = 0x84CE + TEXTURE15 = 0x84CF + TEXTURE16 = 0x84D0 + TEXTURE17 = 0x84D1 + TEXTURE18 = 0x84D2 + TEXTURE19 = 0x84D3 + TEXTURE20 = 0x84D4 + TEXTURE21 = 0x84D5 + TEXTURE22 = 0x84D6 + TEXTURE23 = 0x84D7 + TEXTURE24 = 0x84D8 + TEXTURE25 = 0x84D9 + TEXTURE26 = 0x84DA + TEXTURE27 = 0x84DB + TEXTURE28 = 0x84DC + TEXTURE29 = 0x84DD + TEXTURE30 = 0x84DE + TEXTURE31 = 0x84DF + ACTIVE_TEXTURE = 0x84E0 + REPEAT = 0x2901 + CLAMP_TO_EDGE = 0x812F + MIRRORED_REPEAT = 0x8370 + VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622 + VERTEX_ATTRIB_ARRAY_SIZE = 0x8623 + VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624 + VERTEX_ATTRIB_ARRAY_TYPE = 0x8625 + VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A + VERTEX_ATTRIB_ARRAY_POINTER = 0x8645 + VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F + IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A + IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B + COMPILE_STATUS = 0x8B81 + INFO_LOG_LENGTH = 0x8B84 + SHADER_SOURCE_LENGTH = 0x8B88 + SHADER_COMPILER = 0x8DFA + SHADER_BINARY_FORMATS = 0x8DF8 + NUM_SHADER_BINARY_FORMATS = 0x8DF9 + LOW_FLOAT = 0x8DF0 + MEDIUM_FLOAT = 0x8DF1 + HIGH_FLOAT = 0x8DF2 + LOW_INT = 0x8DF3 + MEDIUM_INT = 0x8DF4 + HIGH_INT = 0x8DF5 + FRAMEBUFFER = 0x8D40 + RENDERBUFFER = 0x8D41 + RGBA4 = 0x8056 + RGB5_A1 = 0x8057 + RGB565 = 0x8D62 + DEPTH_COMPONENT16 = 0x81A5 + STENCIL_INDEX8 = 0x8D48 + RENDERBUFFER_WIDTH = 0x8D42 + RENDERBUFFER_HEIGHT = 0x8D43 + RENDERBUFFER_INTERNAL_FORMAT = 0x8D44 + RENDERBUFFER_RED_SIZE = 0x8D50 + RENDERBUFFER_GREEN_SIZE = 0x8D51 + RENDERBUFFER_BLUE_SIZE = 0x8D52 + RENDERBUFFER_ALPHA_SIZE = 0x8D53 + RENDERBUFFER_DEPTH_SIZE = 0x8D54 + RENDERBUFFER_STENCIL_SIZE = 0x8D55 + FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0 + FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1 + FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2 + FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3 + COLOR_ATTACHMENT0 = 0x8CE0 + DEPTH_ATTACHMENT = 0x8D00 + STENCIL_ATTACHMENT = 0x8D20 + FRAMEBUFFER_COMPLETE = 0x8CD5 + FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6 + FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7 + FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9 + FRAMEBUFFER_UNSUPPORTED = 0x8CDD + FRAMEBUFFER_BINDING = 0x8CA6 + RENDERBUFFER_BINDING = 0x8CA7 + MAX_RENDERBUFFER_SIZE = 0x84E8 + INVALID_FRAMEBUFFER_OPERATION = 0x0506 +) + +const ( + DEPTH_BUFFER_BIT = 0x00000100 + STENCIL_BUFFER_BIT = 0x00000400 + COLOR_BUFFER_BIT = 0x00004000 +) + +const ( + FLOAT_VEC2 = 0x8B50 + FLOAT_VEC3 = 0x8B51 + FLOAT_VEC4 = 0x8B52 + INT_VEC2 = 0x8B53 + INT_VEC3 = 0x8B54 + INT_VEC4 = 0x8B55 + BOOL = 0x8B56 + BOOL_VEC2 = 0x8B57 + BOOL_VEC3 = 0x8B58 + BOOL_VEC4 = 0x8B59 + FLOAT_MAT2 = 0x8B5A + FLOAT_MAT3 = 0x8B5B + FLOAT_MAT4 = 0x8B5C + SAMPLER_2D = 0x8B5E + SAMPLER_CUBE = 0x8B60 +) + +const ( + FRAGMENT_SHADER = 0x8B30 + VERTEX_SHADER = 0x8B31 +) + +const ( + FALSE = 0 + TRUE = 1 + ZERO = 0 + ONE = 1 + NO_ERROR = 0 + NONE = 0 +) + +// GL ES 3.0 constants. +const ( + ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH = 0x8A35 + ACTIVE_UNIFORM_BLOCKS = 0x8A36 + ALREADY_SIGNALED = 0x911A + ANY_SAMPLES_PASSED = 0x8C2F + ANY_SAMPLES_PASSED_CONSERVATIVE = 0x8D6A + BLUE = 0x1905 + BUFFER_ACCESS_FLAGS = 0x911F + BUFFER_MAP_LENGTH = 0x9120 + BUFFER_MAP_OFFSET = 0x9121 + BUFFER_MAPPED = 0x88BC + BUFFER_MAP_POINTER = 0x88BD + COLOR = 0x1800 + COLOR_ATTACHMENT10 = 0x8CEA + COLOR_ATTACHMENT1 = 0x8CE1 + COLOR_ATTACHMENT11 = 0x8CEB + COLOR_ATTACHMENT12 = 0x8CEC + COLOR_ATTACHMENT13 = 0x8CED + COLOR_ATTACHMENT14 = 0x8CEE + COLOR_ATTACHMENT15 = 0x8CEF + COLOR_ATTACHMENT2 = 0x8CE2 + COLOR_ATTACHMENT3 = 0x8CE3 + COLOR_ATTACHMENT4 = 0x8CE4 + COLOR_ATTACHMENT5 = 0x8CE5 + COLOR_ATTACHMENT6 = 0x8CE6 + COLOR_ATTACHMENT7 = 0x8CE7 + COLOR_ATTACHMENT8 = 0x8CE8 + COLOR_ATTACHMENT9 = 0x8CE9 + COMPARE_REF_TO_TEXTURE = 0x884E + COMPRESSED_R11_EAC = 0x9270 + COMPRESSED_RG11_EAC = 0x9272 + COMPRESSED_RGB8_ETC2 = 0x9274 + COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9276 + COMPRESSED_RGBA8_ETC2_EAC = 0x9278 + COMPRESSED_SIGNED_R11_EAC = 0x9271 + COMPRESSED_SIGNED_RG11_EAC = 0x9273 + COMPRESSED_SRGB8_ALPHA8_ETC2_EAC = 0x9279 + COMPRESSED_SRGB8_ETC2 = 0x9275 + COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 = 0x9277 + CONDITION_SATISFIED = 0x911C + COPY_READ_BUFFER = 0x8F36 + COPY_READ_BUFFER_BINDING = 0x8F36 + COPY_WRITE_BUFFER = 0x8F37 + COPY_WRITE_BUFFER_BINDING = 0x8F37 + CURRENT_QUERY = 0x8865 + DEPTH = 0x1801 + DEPTH24_STENCIL8 = 0x88F0 + DEPTH32F_STENCIL8 = 0x8CAD + DEPTH_COMPONENT24 = 0x81A6 + DEPTH_COMPONENT32F = 0x8CAC + DEPTH_STENCIL = 0x84F9 + DEPTH_STENCIL_ATTACHMENT = 0x821A + DRAW_BUFFER0 = 0x8825 + DRAW_BUFFER10 = 0x882F + DRAW_BUFFER1 = 0x8826 + DRAW_BUFFER11 = 0x8830 + DRAW_BUFFER12 = 0x8831 + DRAW_BUFFER13 = 0x8832 + DRAW_BUFFER14 = 0x8833 + DRAW_BUFFER15 = 0x8834 + DRAW_BUFFER2 = 0x8827 + DRAW_BUFFER3 = 0x8828 + DRAW_BUFFER4 = 0x8829 + DRAW_BUFFER5 = 0x882A + DRAW_BUFFER6 = 0x882B + DRAW_BUFFER7 = 0x882C + DRAW_BUFFER8 = 0x882D + DRAW_BUFFER9 = 0x882E + DRAW_FRAMEBUFFER = 0x8CA9 + DRAW_FRAMEBUFFER_BINDING = 0x8CA6 + DYNAMIC_COPY = 0x88EA + DYNAMIC_READ = 0x88E9 + FLOAT_32_UNSIGNED_INT_24_8_REV = 0x8DAD + FLOAT_MAT2x3 = 0x8B65 + FLOAT_MAT2x4 = 0x8B66 + FLOAT_MAT3x2 = 0x8B67 + FLOAT_MAT3x4 = 0x8B68 + FLOAT_MAT4x2 = 0x8B69 + FLOAT_MAT4x3 = 0x8B6A + FRAGMENT_SHADER_DERIVATIVE_HINT = 0x8B8B + FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE = 0x8215 + FRAMEBUFFER_ATTACHMENT_BLUE_SIZE = 0x8214 + FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210 + FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE = 0x8211 + FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE = 0x8216 + FRAMEBUFFER_ATTACHMENT_GREEN_SIZE = 0x8213 + FRAMEBUFFER_ATTACHMENT_RED_SIZE = 0x8212 + FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE = 0x8217 + FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER = 0x8CD4 + FRAMEBUFFER_DEFAULT = 0x8218 + FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = 0x8D56 + FRAMEBUFFER_UNDEFINED = 0x8219 + GREEN = 0x1904 + HALF_FLOAT = 0x140B + INT_2_10_10_10_REV = 0x8D9F + INTERLEAVED_ATTRIBS = 0x8C8C + INT_SAMPLER_2D = 0x8DCA + INT_SAMPLER_2D_ARRAY = 0x8DCF + INT_SAMPLER_3D = 0x8DCB + INT_SAMPLER_CUBE = 0x8DCC + INVALID_INDEX = 0xFFFFFFFF + MAJOR_VERSION = 0x821B + MAP_FLUSH_EXPLICIT_BIT = 0x0010 + MAP_INVALIDATE_BUFFER_BIT = 0x0008 + MAP_INVALIDATE_RANGE_BIT = 0x0004 + MAP_READ_BIT = 0x0001 + MAP_UNSYNCHRONIZED_BIT = 0x0020 + MAP_WRITE_BIT = 0x0002 + MAX = 0x8008 + MAX_3D_TEXTURE_SIZE = 0x8073 + MAX_ARRAY_TEXTURE_LAYERS = 0x88FF + MAX_COLOR_ATTACHMENTS = 0x8CDF + MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS = 0x8A33 + MAX_COMBINED_UNIFORM_BLOCKS = 0x8A2E + MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS = 0x8A31 + MAX_DRAW_BUFFERS = 0x8824 + MAX_ELEMENT_INDEX = 0x8D6B + MAX_ELEMENTS_INDICES = 0x80E9 + MAX_ELEMENTS_VERTICES = 0x80E8 + MAX_FRAGMENT_INPUT_COMPONENTS = 0x9125 + MAX_FRAGMENT_UNIFORM_BLOCKS = 0x8A2D + MAX_FRAGMENT_UNIFORM_COMPONENTS = 0x8B49 + MAX_PROGRAM_TEXEL_OFFSET = 0x8905 + MAX_SAMPLES = 0x8D57 + MAX_SERVER_WAIT_TIMEOUT = 0x9111 + MAX_TEXTURE_LOD_BIAS = 0x84FD + MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS = 0x8C8A + MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = 0x8C8B + MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS = 0x8C80 + MAX_UNIFORM_BLOCK_SIZE = 0x8A30 + MAX_UNIFORM_BUFFER_BINDINGS = 0x8A2F + MAX_VARYING_COMPONENTS = 0x8B4B + MAX_VERTEX_OUTPUT_COMPONENTS = 0x9122 + MAX_VERTEX_UNIFORM_BLOCKS = 0x8A2B + MAX_VERTEX_UNIFORM_COMPONENTS = 0x8B4A + MIN = 0x8007 + MINOR_VERSION = 0x821C + MIN_PROGRAM_TEXEL_OFFSET = 0x8904 + NUM_EXTENSIONS = 0x821D + NUM_PROGRAM_BINARY_FORMATS = 0x87FE + NUM_SAMPLE_COUNTS = 0x9380 + OBJECT_TYPE = 0x9112 + PACK_ROW_LENGTH = 0x0D02 + PACK_SKIP_PIXELS = 0x0D04 + PACK_SKIP_ROWS = 0x0D03 + PIXEL_PACK_BUFFER = 0x88EB + PIXEL_PACK_BUFFER_BINDING = 0x88ED + PIXEL_UNPACK_BUFFER = 0x88EC + PIXEL_UNPACK_BUFFER_BINDING = 0x88EF + PRIMITIVE_RESTART_FIXED_INDEX = 0x8D69 + PROGRAM_BINARY_FORMATS = 0x87FF + PROGRAM_BINARY_LENGTH = 0x8741 + PROGRAM_BINARY_RETRIEVABLE_HINT = 0x8257 + QUERY_RESULT = 0x8866 + QUERY_RESULT_AVAILABLE = 0x8867 + R11F_G11F_B10F = 0x8C3A + R16F = 0x822D + R16I = 0x8233 + R16UI = 0x8234 + R32F = 0x822E + R32I = 0x8235 + R32UI = 0x8236 + R8 = 0x8229 + R8I = 0x8231 + R8_SNORM = 0x8F94 + R8UI = 0x8232 + RASTERIZER_DISCARD = 0x8C89 + READ_BUFFER = 0x0C02 + READ_FRAMEBUFFER = 0x8CA8 + READ_FRAMEBUFFER_BINDING = 0x8CAA + RED = 0x1903 + RED_INTEGER = 0x8D94 + RENDERBUFFER_SAMPLES = 0x8CAB + RG = 0x8227 + RG16F = 0x822F + RG16I = 0x8239 + RG16UI = 0x823A + RG32F = 0x8230 + RG32I = 0x823B + RG32UI = 0x823C + RG8 = 0x822B + RG8I = 0x8237 + RG8_SNORM = 0x8F95 + RG8UI = 0x8238 + RGB10_A2 = 0x8059 + RGB10_A2UI = 0x906F + RGB16F = 0x881B + RGB16I = 0x8D89 + RGB16UI = 0x8D77 + RGB32F = 0x8815 + RGB32I = 0x8D83 + RGB32UI = 0x8D71 + RGB8 = 0x8051 + RGB8I = 0x8D8F + RGB8_SNORM = 0x8F96 + RGB8UI = 0x8D7D + RGB9_E5 = 0x8C3D + RGBA16F = 0x881A + RGBA16I = 0x8D88 + RGBA16UI = 0x8D76 + RGBA32F = 0x8814 + RGBA32I = 0x8D82 + RGBA32UI = 0x8D70 + RGBA8 = 0x8058 + RGBA8I = 0x8D8E + RGBA8_SNORM = 0x8F97 + RGBA8UI = 0x8D7C + RGBA_INTEGER = 0x8D99 + RGB_INTEGER = 0x8D98 + RG_INTEGER = 0x8228 + SAMPLER_2D_ARRAY = 0x8DC1 + SAMPLER_2D_ARRAY_SHADOW = 0x8DC4 + SAMPLER_2D_SHADOW = 0x8B62 + SAMPLER_3D = 0x8B5F + SAMPLER_BINDING = 0x8919 + SAMPLER_CUBE_SHADOW = 0x8DC5 + SEPARATE_ATTRIBS = 0x8C8D + SIGNALED = 0x9119 + SIGNED_NORMALIZED = 0x8F9C + SRGB = 0x8C40 + SRGB8 = 0x8C41 + SRGB8_ALPHA8 = 0x8C43 + STATIC_COPY = 0x88E6 + STATIC_READ = 0x88E5 + STENCIL = 0x1802 + STREAM_COPY = 0x88E2 + STREAM_READ = 0x88E1 + SYNC_CONDITION = 0x9113 + SYNC_FENCE = 0x9116 + SYNC_FLAGS = 0x9115 + SYNC_FLUSH_COMMANDS_BIT = 0x00000001 + SYNC_GPU_COMMANDS_COMPLETE = 0x9117 + SYNC_STATUS = 0x9114 + TEXTURE_2D_ARRAY = 0x8C1A + TEXTURE_3D = 0x806F + TEXTURE_BASE_LEVEL = 0x813C + TEXTURE_BINDING_2D_ARRAY = 0x8C1D + TEXTURE_BINDING_3D = 0x806A + TEXTURE_COMPARE_FUNC = 0x884D + TEXTURE_COMPARE_MODE = 0x884C + TEXTURE_IMMUTABLE_FORMAT = 0x912F + TEXTURE_IMMUTABLE_LEVELS = 0x82DF + TEXTURE_MAX_LEVEL = 0x813D + TEXTURE_MAX_LOD = 0x813B + TEXTURE_MIN_LOD = 0x813A + TEXTURE_SWIZZLE_A = 0x8E45 + TEXTURE_SWIZZLE_B = 0x8E44 + TEXTURE_SWIZZLE_G = 0x8E43 + TEXTURE_SWIZZLE_R = 0x8E42 + TEXTURE_WRAP_R = 0x8072 + TIMEOUT_EXPIRED = 0x911B + TIMEOUT_IGNORED = 0xFFFFFFFFFFFFFFFF + TRANSFORM_FEEDBACK = 0x8E22 + TRANSFORM_FEEDBACK_ACTIVE = 0x8E24 + TRANSFORM_FEEDBACK_BINDING = 0x8E25 + TRANSFORM_FEEDBACK_BUFFER = 0x8C8E + TRANSFORM_FEEDBACK_BUFFER_BINDING = 0x8C8F + TRANSFORM_FEEDBACK_BUFFER_MODE = 0x8C7F + TRANSFORM_FEEDBACK_BUFFER_SIZE = 0x8C85 + TRANSFORM_FEEDBACK_BUFFER_START = 0x8C84 + TRANSFORM_FEEDBACK_PAUSED = 0x8E23 + TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN = 0x8C88 + TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH = 0x8C76 + TRANSFORM_FEEDBACK_VARYINGS = 0x8C83 + UNIFORM_ARRAY_STRIDE = 0x8A3C + UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES = 0x8A43 + UNIFORM_BLOCK_ACTIVE_UNIFORMS = 0x8A42 + UNIFORM_BLOCK_BINDING = 0x8A3F + UNIFORM_BLOCK_DATA_SIZE = 0x8A40 + UNIFORM_BLOCK_INDEX = 0x8A3A + UNIFORM_BLOCK_NAME_LENGTH = 0x8A41 + UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER = 0x8A46 + UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER = 0x8A44 + UNIFORM_BUFFER = 0x8A11 + UNIFORM_BUFFER_BINDING = 0x8A28 + UNIFORM_BUFFER_OFFSET_ALIGNMENT = 0x8A34 + UNIFORM_BUFFER_SIZE = 0x8A2A + UNIFORM_BUFFER_START = 0x8A29 + UNIFORM_IS_ROW_MAJOR = 0x8A3E + UNIFORM_MATRIX_STRIDE = 0x8A3D + UNIFORM_NAME_LENGTH = 0x8A39 + UNIFORM_OFFSET = 0x8A3B + UNIFORM_SIZE = 0x8A38 + UNIFORM_TYPE = 0x8A37 + UNPACK_IMAGE_HEIGHT = 0x806E + UNPACK_ROW_LENGTH = 0x0CF2 + UNPACK_SKIP_IMAGES = 0x806D + UNPACK_SKIP_PIXELS = 0x0CF4 + UNPACK_SKIP_ROWS = 0x0CF3 + UNSIGNALED = 0x9118 + UNSIGNED_INT_10F_11F_11F_REV = 0x8C3B + UNSIGNED_INT_2_10_10_10_REV = 0x8368 + UNSIGNED_INT_24_8 = 0x84FA + UNSIGNED_INT_5_9_9_9_REV = 0x8C3E + UNSIGNED_INT_SAMPLER_2D = 0x8DD2 + UNSIGNED_INT_SAMPLER_2D_ARRAY = 0x8DD7 + UNSIGNED_INT_SAMPLER_3D = 0x8DD3 + UNSIGNED_INT_SAMPLER_CUBE = 0x8DD4 + UNSIGNED_INT_VEC2 = 0x8DC6 + UNSIGNED_INT_VEC3 = 0x8DC7 + UNSIGNED_INT_VEC4 = 0x8DC8 + UNSIGNED_NORMALIZED = 0x8C17 + VERTEX_ARRAY_BINDING = 0x85B5 + VERTEX_ATTRIB_ARRAY_DIVISOR = 0x88FE + VERTEX_ATTRIB_ARRAY_INTEGER = 0x88FD + WAIT_FAILED = 0x911D +) diff --git a/vendor/golang.org/x/mobile/gl/dll_windows.go b/vendor/golang.org/x/mobile/gl/dll_windows.go new file mode 100644 index 00000000..b7a0d90e --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/dll_windows.go @@ -0,0 +1,242 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gl + +import ( + "archive/tar" + "compress/gzip" + "debug/pe" + "fmt" + "io" + "log" + "net/http" + "os" + "path/filepath" + "runtime" +) + +var debug = log.New(io.Discard, "gl: ", log.LstdFlags) + +func downloadDLLs() (path string, err error) { + url := "https://dl.google.com/go/mobile/angle-bd3f8780b-" + runtime.GOARCH + ".tgz" + debug.Printf("downloading %s", url) + resp, err := http.Get(url) + if err != nil { + return "", fmt.Errorf("gl: %v", err) + } + defer func() { + err2 := resp.Body.Close() + if err == nil && err2 != nil { + err = fmt.Errorf("gl: error reading body from %v: %v", url, err2) + } + }() + if resp.StatusCode != http.StatusOK { + err := fmt.Errorf("gl: error fetching %v, status: %v", url, resp.Status) + return "", err + } + + r, err := gzip.NewReader(resp.Body) + if err != nil { + return "", fmt.Errorf("gl: error reading gzip from %v: %v", url, err) + } + tr := tar.NewReader(r) + var bytesGLESv2, bytesEGL, bytesD3DCompiler []byte + for { + header, err := tr.Next() + if err == io.EOF { + break + } + if err != nil { + return "", fmt.Errorf("gl: error reading tar from %v: %v", url, err) + } + switch header.Name { + case "angle-" + runtime.GOARCH + "/libglesv2.dll": + bytesGLESv2, err = io.ReadAll(tr) + case "angle-" + runtime.GOARCH + "/libegl.dll": + bytesEGL, err = io.ReadAll(tr) + case "angle-" + runtime.GOARCH + "/d3dcompiler_47.dll": + bytesD3DCompiler, err = io.ReadAll(tr) + default: // skip + } + if err != nil { + return "", fmt.Errorf("gl: error reading %v from %v: %v", header.Name, url, err) + } + } + if len(bytesGLESv2) == 0 || len(bytesEGL) == 0 || len(bytesD3DCompiler) == 0 { + return "", fmt.Errorf("gl: did not find all DLLs in %v", url) + } + + writeDLLs := func(path string) error { + if err := os.WriteFile(filepath.Join(path, "libglesv2.dll"), bytesGLESv2, 0755); err != nil { + return fmt.Errorf("gl: cannot install ANGLE: %v", err) + } + if err := os.WriteFile(filepath.Join(path, "libegl.dll"), bytesEGL, 0755); err != nil { + return fmt.Errorf("gl: cannot install ANGLE: %v", err) + } + if err := os.WriteFile(filepath.Join(path, "d3dcompiler_47.dll"), bytesD3DCompiler, 0755); err != nil { + return fmt.Errorf("gl: cannot install ANGLE: %v", err) + } + return nil + } + + // First, we attempt to install these DLLs in LOCALAPPDATA/Shiny. + // + // Traditionally we would use the system32 directory, but it is + // no longer writable by normal programs. + os.MkdirAll(appdataPath(), 0775) + if err := writeDLLs(appdataPath()); err == nil { + return appdataPath(), nil + } + debug.Printf("DLLs could not be written to %s", appdataPath()) + + // Second, install in GOPATH/pkg if it exists. + gopath := os.Getenv("GOPATH") + gopathpkg := filepath.Join(gopath, "pkg") + if _, err := os.Stat(gopathpkg); err == nil && gopath != "" { + if err := writeDLLs(gopathpkg); err == nil { + return gopathpkg, nil + } + } + debug.Printf("DLLs could not be written to GOPATH") + + // Third, pick a temporary directory. + tmp := os.TempDir() + if err := writeDLLs(tmp); err != nil { + return "", fmt.Errorf("gl: unable to install ANGLE DLLs: %v", err) + } + return tmp, nil +} + +func appdataPath() string { + return filepath.Join(os.Getenv("LOCALAPPDATA"), "GoGL", runtime.GOARCH) +} + +func containsDLLs(dir string) bool { + compatible := func(name string) bool { + file, err := pe.Open(filepath.Join(dir, name)) + if err != nil { + return false + } + defer file.Close() + + switch file.Machine { + case pe.IMAGE_FILE_MACHINE_AMD64: + return "amd64" == runtime.GOARCH + case pe.IMAGE_FILE_MACHINE_ARM: + return "arm" == runtime.GOARCH + case pe.IMAGE_FILE_MACHINE_I386: + return "386" == runtime.GOARCH + } + return false + } + + return compatible("libglesv2.dll") && compatible("libegl.dll") && compatible("d3dcompiler_47.dll") +} + +func chromePath() string { + // dlls are stored in: + // //libglesv2.dll + + var installdirs = []string{ + // Chrome User + filepath.Join(os.Getenv("LOCALAPPDATA"), "Google", "Chrome", "Application"), + // Chrome System + filepath.Join(os.Getenv("ProgramFiles(x86)"), "Google", "Chrome", "Application"), + // Chromium + filepath.Join(os.Getenv("LOCALAPPDATA"), "Chromium", "Application"), + // Chrome Canary + filepath.Join(os.Getenv("LOCALAPPDATA"), "Google", "Chrome SxS", "Application"), + } + + for _, installdir := range installdirs { + versiondirs, err := os.ReadDir(installdir) + if err != nil { + continue + } + + for _, versiondir := range versiondirs { + if !versiondir.IsDir() { + continue + } + + versionpath := filepath.Join(installdir, versiondir.Name()) + if containsDLLs(versionpath) { + return versionpath + } + } + } + + return "" +} + +func findDLLs() (err error) { + load := func(path string) (bool, error) { + if path != "" { + // don't try to start when one of the files is missing + if !containsDLLs(path) { + return false, nil + } + + LibD3DCompiler.Name = filepath.Join(path, filepath.Base(LibD3DCompiler.Name)) + LibGLESv2.Name = filepath.Join(path, filepath.Base(LibGLESv2.Name)) + LibEGL.Name = filepath.Join(path, filepath.Base(LibEGL.Name)) + } + + if err := LibGLESv2.Load(); err == nil { + if err := LibEGL.Load(); err != nil { + return false, fmt.Errorf("gl: loaded libglesv2 but not libegl: %v", err) + } + if err := LibD3DCompiler.Load(); err != nil { + return false, fmt.Errorf("gl: loaded libglesv2, libegl but not d3dcompiler: %v", err) + } + if path == "" { + debug.Printf("DLLs found") + } else { + debug.Printf("DLLs found in: %q", path) + } + return true, nil + } + + return false, nil + } + + // Look in the system directory. + if ok, err := load(""); ok || err != nil { + return err + } + + // Look in the AppData directory. + if ok, err := load(appdataPath()); ok || err != nil { + return err + } + + // Look for a Chrome installation + if dir := chromePath(); dir != "" { + if ok, err := load(dir); ok || err != nil { + return err + } + } + + // Look in GOPATH/pkg. + if ok, err := load(filepath.Join(os.Getenv("GOPATH"), "pkg")); ok || err != nil { + return err + } + + // Look in temporary directory. + if ok, err := load(os.TempDir()); ok || err != nil { + return err + } + + // Download the DLL binary. + path, err := downloadDLLs() + if err != nil { + return err + } + debug.Printf("DLLs written to %s", path) + if ok, err := load(path); !ok || err != nil { + return fmt.Errorf("gl: unable to load ANGLE after installation: %v", err) + } + return nil +} diff --git a/vendor/golang.org/x/mobile/gl/doc.go b/vendor/golang.org/x/mobile/gl/doc.go new file mode 100644 index 00000000..408c35a6 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/doc.go @@ -0,0 +1,66 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +/* +Package gl implements Go bindings for OpenGL ES 2.0 and ES 3.0. + +The GL functions are defined on a Context object that is responsible for +tracking a GL context. Typically a windowing system package (such as +golang.org/x/exp/shiny/screen) will call NewContext and provide +a gl.Context for a user application. + +If the gl package is compiled on a platform capable of supporting ES 3.0, +the gl.Context object also implements gl.Context3. + +The bindings are deliberately minimal, staying as close the C API as +possible. The semantics of each function maps onto functions +described in the Khronos documentation: + +https://www.khronos.org/opengles/sdk/docs/man/ + +One notable departure from the C API is the introduction of types +to represent common uses of GLint: Texture, Surface, Buffer, etc. + +# Debug Logging + +A tracing version of the OpenGL bindings is behind the `gldebug` build +tag. It acts as a simplified version of apitrace. Build your Go binary +with + + -tags gldebug + +and each call to a GL function will log its input, output, and any +error messages. For example, + + I/GoLog (27668): gl.GenBuffers(1) [Buffer(70001)] + I/GoLog (27668): gl.BindBuffer(ARRAY_BUFFER, Buffer(70001)) + I/GoLog (27668): gl.BufferData(ARRAY_BUFFER, 36, len(36), STATIC_DRAW) + I/GoLog (27668): gl.BindBuffer(ARRAY_BUFFER, Buffer(70001)) + I/GoLog (27668): gl.VertexAttribPointer(Attrib(0), 6, FLOAT, false, 0, 0) error: [INVALID_VALUE] + +The gldebug tracing has very high overhead, so make sure to remove +the build tag before deploying any binaries. +*/ +package gl + +/* +Implementation details. + +All GL function calls fill out a C.struct_fnargs and drop it on the work +queue. The Start function drains the work queue and hands over a batch +of calls to C.process which runs them. This allows multiple GL calls to +be executed in a single cgo call. + +A GL call is marked as blocking if it returns a value, or if it takes a +Go pointer. In this case the call will not return until C.process sends a +value on the retvalue channel. + +This implementation ensures any goroutine can make GL calls, but it does +not make the GL interface safe for simultaneous use by multiple goroutines. +For the purpose of analyzing this code for race conditions, picture two +separate goroutines: one blocked on gl.Start, and another making calls to +the gl package exported functions. +*/ + +//go:generate go run gendebug.go -o gldebug.go diff --git a/vendor/golang.org/x/mobile/gl/fn.go b/vendor/golang.org/x/mobile/gl/fn.go new file mode 100644 index 00000000..c34e5166 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/fn.go @@ -0,0 +1,210 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gl + +import "unsafe" + +type call struct { + args fnargs + parg unsafe.Pointer + blocking bool +} + +type fnargs struct { + fn glfn + + a0 uintptr + a1 uintptr + a2 uintptr + a3 uintptr + a4 uintptr + a5 uintptr + a6 uintptr + a7 uintptr + a8 uintptr + a9 uintptr +} + +type glfn int + +const ( + glfnUNDEFINED glfn = iota + glfnActiveTexture + glfnAttachShader + glfnBindAttribLocation + glfnBindBuffer + glfnBindFramebuffer + glfnBindRenderbuffer + glfnBindTexture + glfnBindVertexArray + glfnBlendColor + glfnBlendEquation + glfnBlendEquationSeparate + glfnBlendFunc + glfnBlendFuncSeparate + glfnBufferData + glfnBufferSubData + glfnCheckFramebufferStatus + glfnClear + glfnClearColor + glfnClearDepthf + glfnClearStencil + glfnColorMask + glfnCompileShader + glfnCompressedTexImage2D + glfnCompressedTexSubImage2D + glfnCopyTexImage2D + glfnCopyTexSubImage2D + glfnCreateProgram + glfnCreateShader + glfnCullFace + glfnDeleteBuffer + glfnDeleteFramebuffer + glfnDeleteProgram + glfnDeleteRenderbuffer + glfnDeleteShader + glfnDeleteTexture + glfnDeleteVertexArray + glfnDepthFunc + glfnDepthRangef + glfnDepthMask + glfnDetachShader + glfnDisable + glfnDisableVertexAttribArray + glfnDrawArrays + glfnDrawElements + glfnEnable + glfnEnableVertexAttribArray + glfnFinish + glfnFlush + glfnFramebufferRenderbuffer + glfnFramebufferTexture2D + glfnFrontFace + glfnGenBuffer + glfnGenFramebuffer + glfnGenRenderbuffer + glfnGenTexture + glfnGenVertexArray + glfnGenerateMipmap + glfnGetActiveAttrib + glfnGetActiveUniform + glfnGetAttachedShaders + glfnGetAttribLocation + glfnGetBooleanv + glfnGetBufferParameteri + glfnGetError + glfnGetFloatv + glfnGetFramebufferAttachmentParameteriv + glfnGetIntegerv + glfnGetProgramInfoLog + glfnGetProgramiv + glfnGetRenderbufferParameteriv + glfnGetShaderInfoLog + glfnGetShaderPrecisionFormat + glfnGetShaderSource + glfnGetShaderiv + glfnGetString + glfnGetTexParameterfv + glfnGetTexParameteriv + glfnGetUniformLocation + glfnGetUniformfv + glfnGetUniformiv + glfnGetVertexAttribfv + glfnGetVertexAttribiv + glfnHint + glfnIsBuffer + glfnIsEnabled + glfnIsFramebuffer + glfnIsProgram + glfnIsRenderbuffer + glfnIsShader + glfnIsTexture + glfnLineWidth + glfnLinkProgram + glfnPixelStorei + glfnPolygonOffset + glfnReadPixels + glfnReleaseShaderCompiler + glfnRenderbufferStorage + glfnSampleCoverage + glfnScissor + glfnShaderSource + glfnStencilFunc + glfnStencilFuncSeparate + glfnStencilMask + glfnStencilMaskSeparate + glfnStencilOp + glfnStencilOpSeparate + glfnTexImage2D + glfnTexParameterf + glfnTexParameterfv + glfnTexParameteri + glfnTexParameteriv + glfnTexSubImage2D + glfnUniform1f + glfnUniform1fv + glfnUniform1i + glfnUniform1iv + glfnUniform2f + glfnUniform2fv + glfnUniform2i + glfnUniform2iv + glfnUniform3f + glfnUniform3fv + glfnUniform3i + glfnUniform3iv + glfnUniform4f + glfnUniform4fv + glfnUniform4i + glfnUniform4iv + glfnUniformMatrix2fv + glfnUniformMatrix3fv + glfnUniformMatrix4fv + glfnUseProgram + glfnValidateProgram + glfnVertexAttrib1f + glfnVertexAttrib1fv + glfnVertexAttrib2f + glfnVertexAttrib2fv + glfnVertexAttrib3f + glfnVertexAttrib3fv + glfnVertexAttrib4f + glfnVertexAttrib4fv + glfnVertexAttribPointer + glfnViewport + + // ES 3.0 functions + glfnUniformMatrix2x3fv + glfnUniformMatrix3x2fv + glfnUniformMatrix2x4fv + glfnUniformMatrix4x2fv + glfnUniformMatrix3x4fv + glfnUniformMatrix4x3fv + glfnBlitFramebuffer + glfnUniform1ui + glfnUniform2ui + glfnUniform3ui + glfnUniform4ui + glfnUniform1uiv + glfnUniform2uiv + glfnUniform3uiv + glfnUniform4uiv +) + +func goString(buf []byte) string { + for i, b := range buf { + if b == 0 { + return string(buf[:i]) + } + } + panic("buf is not NUL-terminated") +} + +func glBoolean(b bool) uintptr { + if b { + return TRUE + } + return FALSE +} diff --git a/vendor/golang.org/x/mobile/gl/gl.go b/vendor/golang.org/x/mobile/gl/gl.go new file mode 100644 index 00000000..2272c59d --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/gl.go @@ -0,0 +1,1851 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin || linux || openbsd || windows) && !gldebug + +package gl + +// TODO(crawshaw): should functions on specific types become methods? E.g. +// func (t Texture) Bind(target Enum) +// this seems natural in Go, but moves us slightly +// further away from the underlying OpenGL spec. + +import ( + "math" + "unsafe" +) + +func (ctx *context) ActiveTexture(texture Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnActiveTexture, + a0: texture.c(), + }, + }) +} + +func (ctx *context) AttachShader(p Program, s Shader) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnAttachShader, + a0: p.c(), + a1: s.c(), + }, + }) +} + +func (ctx *context) BindAttribLocation(p Program, a Attrib, name string) { + s, free := ctx.cString(name) + defer free() + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBindAttribLocation, + a0: p.c(), + a1: a.c(), + a2: s, + }, + blocking: true, + }) +} + +func (ctx *context) BindBuffer(target Enum, b Buffer) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBindBuffer, + a0: target.c(), + a1: b.c(), + }, + }) +} + +func (ctx *context) BindFramebuffer(target Enum, fb Framebuffer) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBindFramebuffer, + a0: target.c(), + a1: fb.c(), + }, + }) +} + +func (ctx *context) BindRenderbuffer(target Enum, rb Renderbuffer) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBindRenderbuffer, + a0: target.c(), + a1: rb.c(), + }, + }) +} + +func (ctx *context) BindTexture(target Enum, t Texture) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBindTexture, + a0: target.c(), + a1: t.c(), + }, + }) +} + +func (ctx *context) BindVertexArray(va VertexArray) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBindVertexArray, + a0: va.c(), + }, + }) +} + +func (ctx *context) BlendColor(red, green, blue, alpha float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBlendColor, + a0: uintptr(math.Float32bits(red)), + a1: uintptr(math.Float32bits(green)), + a2: uintptr(math.Float32bits(blue)), + a3: uintptr(math.Float32bits(alpha)), + }, + }) +} + +func (ctx *context) BlendEquation(mode Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBlendEquation, + a0: mode.c(), + }, + }) +} + +func (ctx *context) BlendEquationSeparate(modeRGB, modeAlpha Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBlendEquationSeparate, + a0: modeRGB.c(), + a1: modeAlpha.c(), + }, + }) +} + +func (ctx *context) BlendFunc(sfactor, dfactor Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBlendFunc, + a0: sfactor.c(), + a1: dfactor.c(), + }, + }) +} + +func (ctx *context) BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBlendFuncSeparate, + a0: sfactorRGB.c(), + a1: dfactorRGB.c(), + a2: sfactorAlpha.c(), + a3: dfactorAlpha.c(), + }, + }) +} + +func (ctx *context) BufferData(target Enum, src []byte, usage Enum) { + parg := unsafe.Pointer(nil) + if len(src) > 0 { + parg = unsafe.Pointer(&src[0]) + } + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBufferData, + a0: target.c(), + a1: uintptr(len(src)), + a2: usage.c(), + }, + parg: parg, + blocking: true, + }) +} + +func (ctx *context) BufferInit(target Enum, size int, usage Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBufferData, + a0: target.c(), + a1: uintptr(size), + a2: usage.c(), + }, + parg: unsafe.Pointer(nil), + }) +} + +func (ctx *context) BufferSubData(target Enum, offset int, data []byte) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBufferSubData, + a0: target.c(), + a1: uintptr(offset), + a2: uintptr(len(data)), + }, + parg: unsafe.Pointer(&data[0]), + blocking: true, + }) +} + +func (ctx *context) CheckFramebufferStatus(target Enum) Enum { + return Enum(ctx.enqueue(call{ + args: fnargs{ + fn: glfnCheckFramebufferStatus, + a0: target.c(), + }, + blocking: true, + })) +} + +func (ctx *context) Clear(mask Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnClear, + a0: uintptr(mask), + }, + }) +} + +func (ctx *context) ClearColor(red, green, blue, alpha float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnClearColor, + a0: uintptr(math.Float32bits(red)), + a1: uintptr(math.Float32bits(green)), + a2: uintptr(math.Float32bits(blue)), + a3: uintptr(math.Float32bits(alpha)), + }, + }) +} + +func (ctx *context) ClearDepthf(d float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnClearDepthf, + a0: uintptr(math.Float32bits(d)), + }, + }) +} + +func (ctx *context) ClearStencil(s int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnClearStencil, + a0: uintptr(s), + }, + }) +} + +func (ctx *context) ColorMask(red, green, blue, alpha bool) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnColorMask, + a0: glBoolean(red), + a1: glBoolean(green), + a2: glBoolean(blue), + a3: glBoolean(alpha), + }, + }) +} + +func (ctx *context) CompileShader(s Shader) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnCompileShader, + a0: s.c(), + }, + }) +} + +func (ctx *context) CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnCompressedTexImage2D, + a0: target.c(), + a1: uintptr(level), + a2: internalformat.c(), + a3: uintptr(width), + a4: uintptr(height), + a5: uintptr(border), + a6: uintptr(len(data)), + }, + parg: unsafe.Pointer(&data[0]), + blocking: true, + }) +} + +func (ctx *context) CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnCompressedTexSubImage2D, + a0: target.c(), + a1: uintptr(level), + a2: uintptr(xoffset), + a3: uintptr(yoffset), + a4: uintptr(width), + a5: uintptr(height), + a6: format.c(), + a7: uintptr(len(data)), + }, + parg: unsafe.Pointer(&data[0]), + blocking: true, + }) +} + +func (ctx *context) CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnCopyTexImage2D, + a0: target.c(), + a1: uintptr(level), + a2: internalformat.c(), + a3: uintptr(x), + a4: uintptr(y), + a5: uintptr(width), + a6: uintptr(height), + a7: uintptr(border), + }, + }) +} + +func (ctx *context) CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnCopyTexSubImage2D, + a0: target.c(), + a1: uintptr(level), + a2: uintptr(xoffset), + a3: uintptr(yoffset), + a4: uintptr(x), + a5: uintptr(y), + a6: uintptr(width), + a7: uintptr(height), + }, + }) +} + +func (ctx *context) CreateBuffer() Buffer { + return Buffer{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenBuffer, + }, + blocking: true, + }))} +} + +func (ctx *context) CreateFramebuffer() Framebuffer { + return Framebuffer{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenFramebuffer, + }, + blocking: true, + }))} +} + +func (ctx *context) CreateProgram() Program { + return Program{ + Init: true, + Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnCreateProgram, + }, + blocking: true, + }, + ))} +} + +func (ctx *context) CreateRenderbuffer() Renderbuffer { + return Renderbuffer{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenRenderbuffer, + }, + blocking: true, + }))} +} + +func (ctx *context) CreateShader(ty Enum) Shader { + return Shader{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnCreateShader, + a0: uintptr(ty), + }, + blocking: true, + }))} +} + +func (ctx *context) CreateTexture() Texture { + return Texture{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenTexture, + }, + blocking: true, + }))} +} + +func (ctx *context) CreateVertexArray() VertexArray { + return VertexArray{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenVertexArray, + }, + blocking: true, + }))} +} + +func (ctx *context) CullFace(mode Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnCullFace, + a0: mode.c(), + }, + }) +} + +func (ctx *context) DeleteBuffer(v Buffer) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDeleteBuffer, + a0: v.c(), + }, + }) +} + +func (ctx *context) DeleteFramebuffer(v Framebuffer) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDeleteFramebuffer, + a0: v.c(), + }, + }) +} + +func (ctx *context) DeleteProgram(p Program) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDeleteProgram, + a0: p.c(), + }, + }) +} + +func (ctx *context) DeleteRenderbuffer(v Renderbuffer) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDeleteRenderbuffer, + a0: v.c(), + }, + }) +} + +func (ctx *context) DeleteShader(s Shader) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDeleteShader, + a0: s.c(), + }, + }) +} + +func (ctx *context) DeleteTexture(v Texture) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDeleteTexture, + a0: v.c(), + }, + }) +} + +func (ctx *context) DeleteVertexArray(v VertexArray) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDeleteVertexArray, + a0: v.c(), + }, + }) +} + +func (ctx *context) DepthFunc(fn Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDepthFunc, + a0: fn.c(), + }, + }) +} + +func (ctx *context) DepthMask(flag bool) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDepthMask, + a0: glBoolean(flag), + }, + }) +} + +func (ctx *context) DepthRangef(n, f float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDepthRangef, + a0: uintptr(math.Float32bits(n)), + a1: uintptr(math.Float32bits(f)), + }, + }) +} + +func (ctx *context) DetachShader(p Program, s Shader) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDetachShader, + a0: p.c(), + a1: s.c(), + }, + }) +} + +func (ctx *context) Disable(cap Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDisable, + a0: cap.c(), + }, + }) +} + +func (ctx *context) DisableVertexAttribArray(a Attrib) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDisableVertexAttribArray, + a0: a.c(), + }, + }) +} + +func (ctx *context) DrawArrays(mode Enum, first, count int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDrawArrays, + a0: mode.c(), + a1: uintptr(first), + a2: uintptr(count), + }, + }) +} + +func (ctx *context) DrawElements(mode Enum, count int, ty Enum, offset int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnDrawElements, + a0: mode.c(), + a1: uintptr(count), + a2: ty.c(), + a3: uintptr(offset), + }, + }) +} + +func (ctx *context) Enable(cap Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnEnable, + a0: cap.c(), + }, + }) +} + +func (ctx *context) EnableVertexAttribArray(a Attrib) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnEnableVertexAttribArray, + a0: a.c(), + }, + }) +} + +func (ctx *context) Finish() { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnFinish, + }, + blocking: true, + }) +} + +func (ctx *context) Flush() { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnFlush, + }, + blocking: true, + }) +} + +func (ctx *context) FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnFramebufferRenderbuffer, + a0: target.c(), + a1: attachment.c(), + a2: rbTarget.c(), + a3: rb.c(), + }, + }) +} + +func (ctx *context) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnFramebufferTexture2D, + a0: target.c(), + a1: attachment.c(), + a2: texTarget.c(), + a3: t.c(), + a4: uintptr(level), + }, + }) +} + +func (ctx *context) FrontFace(mode Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnFrontFace, + a0: mode.c(), + }, + }) +} + +func (ctx *context) GenerateMipmap(target Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenerateMipmap, + a0: target.c(), + }, + }) +} + +func (ctx *context) GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) { + bufSize := ctx.GetProgrami(p, ACTIVE_ATTRIBUTE_MAX_LENGTH) + buf := make([]byte, bufSize) + var cType int + + cSize := ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetActiveAttrib, + a0: p.c(), + a1: uintptr(index), + a2: uintptr(bufSize), + a3: uintptr(unsafe.Pointer(&cType)), // TODO(crawshaw): not safe for a moving collector + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + + return goString(buf), int(cSize), Enum(cType) +} + +func (ctx *context) GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) { + bufSize := ctx.GetProgrami(p, ACTIVE_UNIFORM_MAX_LENGTH) + buf := make([]byte, bufSize+8) // extra space for cType + var cType int + + cSize := ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetActiveUniform, + a0: p.c(), + a1: uintptr(index), + a2: uintptr(bufSize), + a3: uintptr(unsafe.Pointer(&cType)), // TODO(crawshaw): not safe for a moving collector + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + + return goString(buf), int(cSize), Enum(cType) +} + +func (ctx *context) GetAttachedShaders(p Program) []Shader { + shadersLen := ctx.GetProgrami(p, ATTACHED_SHADERS) + if shadersLen == 0 { + return nil + } + buf := make([]uint32, shadersLen) + + n := int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetAttachedShaders, + a0: p.c(), + a1: uintptr(shadersLen), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + })) + + buf = buf[:int(n)] + shaders := make([]Shader, len(buf)) + for i, s := range buf { + shaders[i] = Shader{Value: uint32(s)} + } + return shaders +} + +func (ctx *context) GetAttribLocation(p Program, name string) Attrib { + s, free := ctx.cString(name) + defer free() + return Attrib{Value: uint(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetAttribLocation, + a0: p.c(), + a1: s, + }, + blocking: true, + }))} +} + +func (ctx *context) GetBooleanv(dst []bool, pname Enum) { + buf := make([]int32, len(dst)) + + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetBooleanv, + a0: pname.c(), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + + for i, v := range buf { + dst[i] = v != 0 + } +} + +func (ctx *context) GetFloatv(dst []float32, pname Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetFloatv, + a0: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetIntegerv(dst []int32, pname Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetIntegerv, + a0: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetInteger(pname Enum) int { + var v [1]int32 + ctx.GetIntegerv(v[:], pname) + return int(v[0]) +} + +func (ctx *context) GetBufferParameteri(target, value Enum) int { + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetBufferParameteri, + a0: target.c(), + a1: value.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetError() Enum { + return Enum(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetError, + }, + blocking: true, + })) +} + +func (ctx *context) GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int { + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetFramebufferAttachmentParameteriv, + a0: target.c(), + a1: attachment.c(), + a2: pname.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetProgrami(p Program, pname Enum) int { + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetProgramiv, + a0: p.c(), + a1: pname.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetProgramInfoLog(p Program) string { + infoLen := ctx.GetProgrami(p, INFO_LOG_LENGTH) + if infoLen == 0 { + return "" + } + buf := make([]byte, infoLen) + + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetProgramInfoLog, + a0: p.c(), + a1: uintptr(infoLen), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + + return goString(buf) +} + +func (ctx *context) GetRenderbufferParameteri(target, pname Enum) int { + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetRenderbufferParameteriv, + a0: target.c(), + a1: pname.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetShaderi(s Shader, pname Enum) int { + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetShaderiv, + a0: s.c(), + a1: pname.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetShaderInfoLog(s Shader) string { + infoLen := ctx.GetShaderi(s, INFO_LOG_LENGTH) + if infoLen == 0 { + return "" + } + buf := make([]byte, infoLen) + + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetShaderInfoLog, + a0: s.c(), + a1: uintptr(infoLen), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + + return goString(buf) +} + +func (ctx *context) GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) { + var rangeAndPrec [3]int32 + + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetShaderPrecisionFormat, + a0: shadertype.c(), + a1: precisiontype.c(), + }, + parg: unsafe.Pointer(&rangeAndPrec[0]), + blocking: true, + }) + + return int(rangeAndPrec[0]), int(rangeAndPrec[1]), int(rangeAndPrec[2]) +} + +func (ctx *context) GetShaderSource(s Shader) string { + sourceLen := ctx.GetShaderi(s, SHADER_SOURCE_LENGTH) + if sourceLen == 0 { + return "" + } + buf := make([]byte, sourceLen) + + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetShaderSource, + a0: s.c(), + a1: uintptr(sourceLen), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + + return goString(buf) +} + +func (ctx *context) GetString(pname Enum) string { + ret := ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetString, + a0: pname.c(), + }, + blocking: true, + }) + retp := unsafe.Pointer(ret) + buf := (*[1 << 24]byte)(retp)[:] + return goString(buf) +} + +func (ctx *context) GetTexParameterfv(dst []float32, target, pname Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetTexParameterfv, + a0: target.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetTexParameteriv(dst []int32, target, pname Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetTexParameteriv, + a0: target.c(), + a1: pname.c(), + }, + blocking: true, + }) +} + +func (ctx *context) GetUniformfv(dst []float32, src Uniform, p Program) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetUniformfv, + a0: p.c(), + a1: src.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetUniformiv(dst []int32, src Uniform, p Program) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetUniformiv, + a0: p.c(), + a1: src.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetUniformLocation(p Program, name string) Uniform { + s, free := ctx.cString(name) + defer free() + return Uniform{Value: int32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetUniformLocation, + a0: p.c(), + a1: s, + }, + blocking: true, + }))} +} + +func (ctx *context) GetVertexAttribf(src Attrib, pname Enum) float32 { + var params [1]float32 + ctx.GetVertexAttribfv(params[:], src, pname) + return params[0] +} + +func (ctx *context) GetVertexAttribfv(dst []float32, src Attrib, pname Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetVertexAttribfv, + a0: src.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetVertexAttribi(src Attrib, pname Enum) int32 { + var params [1]int32 + ctx.GetVertexAttribiv(params[:], src, pname) + return params[0] +} + +func (ctx *context) GetVertexAttribiv(dst []int32, src Attrib, pname Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetVertexAttribiv, + a0: src.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) Hint(target, mode Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnHint, + a0: target.c(), + a1: mode.c(), + }, + }) +} + +func (ctx *context) IsBuffer(b Buffer) bool { + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsBuffer, + a0: b.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsEnabled(cap Enum) bool { + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsEnabled, + a0: cap.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsFramebuffer(fb Framebuffer) bool { + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsFramebuffer, + a0: fb.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsProgram(p Program) bool { + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsProgram, + a0: p.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsRenderbuffer(rb Renderbuffer) bool { + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsRenderbuffer, + a0: rb.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsShader(s Shader) bool { + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsShader, + a0: s.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsTexture(t Texture) bool { + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsTexture, + a0: t.c(), + }, + blocking: true, + }) +} + +func (ctx *context) LineWidth(width float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnLineWidth, + a0: uintptr(math.Float32bits(width)), + }, + }) +} + +func (ctx *context) LinkProgram(p Program) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnLinkProgram, + a0: p.c(), + }, + }) +} + +func (ctx *context) PixelStorei(pname Enum, param int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnPixelStorei, + a0: pname.c(), + a1: uintptr(param), + }, + }) +} + +func (ctx *context) PolygonOffset(factor, units float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnPolygonOffset, + a0: uintptr(math.Float32bits(factor)), + a1: uintptr(math.Float32bits(units)), + }, + }) +} + +func (ctx *context) ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnReadPixels, + // TODO(crawshaw): support PIXEL_PACK_BUFFER in GLES3, uses offset. + a0: uintptr(x), + a1: uintptr(y), + a2: uintptr(width), + a3: uintptr(height), + a4: format.c(), + a5: ty.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) ReleaseShaderCompiler() { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnReleaseShaderCompiler, + }, + }) +} + +func (ctx *context) RenderbufferStorage(target, internalFormat Enum, width, height int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnRenderbufferStorage, + a0: target.c(), + a1: internalFormat.c(), + a2: uintptr(width), + a3: uintptr(height), + }, + }) +} + +func (ctx *context) SampleCoverage(value float32, invert bool) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnSampleCoverage, + a0: uintptr(math.Float32bits(value)), + a1: glBoolean(invert), + }, + }) +} + +func (ctx *context) Scissor(x, y, width, height int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnScissor, + a0: uintptr(x), + a1: uintptr(y), + a2: uintptr(width), + a3: uintptr(height), + }, + }) +} + +func (ctx *context) ShaderSource(s Shader, src string) { + strp, free := ctx.cStringPtr(src) + defer free() + ctx.enqueue(call{ + args: fnargs{ + fn: glfnShaderSource, + a0: s.c(), + a1: 1, + a2: strp, + }, + blocking: true, + }) +} + +func (ctx *context) StencilFunc(fn Enum, ref int, mask uint32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnStencilFunc, + a0: fn.c(), + a1: uintptr(ref), + a2: uintptr(mask), + }, + }) +} + +func (ctx *context) StencilFuncSeparate(face, fn Enum, ref int, mask uint32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnStencilFuncSeparate, + a0: face.c(), + a1: fn.c(), + a2: uintptr(ref), + a3: uintptr(mask), + }, + }) +} + +func (ctx *context) StencilMask(mask uint32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnStencilMask, + a0: uintptr(mask), + }, + }) +} + +func (ctx *context) StencilMaskSeparate(face Enum, mask uint32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnStencilMaskSeparate, + a0: face.c(), + a1: uintptr(mask), + }, + }) +} + +func (ctx *context) StencilOp(fail, zfail, zpass Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnStencilOp, + a0: fail.c(), + a1: zfail.c(), + a2: zpass.c(), + }, + }) +} + +func (ctx *context) StencilOpSeparate(face, sfail, dpfail, dppass Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnStencilOpSeparate, + a0: face.c(), + a1: sfail.c(), + a2: dpfail.c(), + a3: dppass.c(), + }, + }) +} + +func (ctx *context) TexImage2D(target Enum, level int, internalFormat int, width, height int, format Enum, ty Enum, data []byte) { + // It is common to pass TexImage2D a nil data, indicating that a + // bound GL buffer is being used as the source. In that case, it + // is not necessary to block. + parg := unsafe.Pointer(nil) + if len(data) > 0 { + parg = unsafe.Pointer(&data[0]) + } + + ctx.enqueue(call{ + args: fnargs{ + fn: glfnTexImage2D, + // TODO(crawshaw): GLES3 offset for PIXEL_UNPACK_BUFFER and PIXEL_PACK_BUFFER. + a0: target.c(), + a1: uintptr(level), + a2: uintptr(internalFormat), + a3: uintptr(width), + a4: uintptr(height), + a5: format.c(), + a6: ty.c(), + }, + parg: parg, + blocking: parg != nil, + }) +} + +func (ctx *context) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { + // It is common to pass TexSubImage2D a nil data, indicating that a + // bound GL buffer is being used as the source. In that case, it + // is not necessary to block. + parg := unsafe.Pointer(nil) + if len(data) > 0 { + parg = unsafe.Pointer(&data[0]) + } + + ctx.enqueue(call{ + args: fnargs{ + fn: glfnTexSubImage2D, + // TODO(crawshaw): GLES3 offset for PIXEL_UNPACK_BUFFER and PIXEL_PACK_BUFFER. + a0: target.c(), + a1: uintptr(level), + a2: uintptr(x), + a3: uintptr(y), + a4: uintptr(width), + a5: uintptr(height), + a6: format.c(), + a7: ty.c(), + }, + parg: parg, + blocking: parg != nil, + }) +} + +func (ctx *context) TexParameterf(target, pname Enum, param float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnTexParameterf, + a0: target.c(), + a1: pname.c(), + a2: uintptr(math.Float32bits(param)), + }, + }) +} + +func (ctx *context) TexParameterfv(target, pname Enum, params []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnTexParameterfv, + a0: target.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(¶ms[0]), + blocking: true, + }) +} + +func (ctx *context) TexParameteri(target, pname Enum, param int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnTexParameteri, + a0: target.c(), + a1: pname.c(), + a2: uintptr(param), + }, + }) +} + +func (ctx *context) TexParameteriv(target, pname Enum, params []int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnTexParameteriv, + a0: target.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(¶ms[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform1f(dst Uniform, v float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform1f, + a0: dst.c(), + a1: uintptr(math.Float32bits(v)), + }, + }) +} + +func (ctx *context) Uniform1fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform1fv, + a0: dst.c(), + a1: uintptr(len(src)), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform1i(dst Uniform, v int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform1i, + a0: dst.c(), + a1: uintptr(v), + }, + }) +} + +func (ctx *context) Uniform1iv(dst Uniform, src []int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform1iv, + a0: dst.c(), + a1: uintptr(len(src)), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform2f(dst Uniform, v0, v1 float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform2f, + a0: dst.c(), + a1: uintptr(math.Float32bits(v0)), + a2: uintptr(math.Float32bits(v1)), + }, + }) +} + +func (ctx *context) Uniform2fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform2fv, + a0: dst.c(), + a1: uintptr(len(src) / 2), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform2i(dst Uniform, v0, v1 int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform2i, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + }, + }) +} + +func (ctx *context) Uniform2iv(dst Uniform, src []int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform2iv, + a0: dst.c(), + a1: uintptr(len(src) / 2), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform3f(dst Uniform, v0, v1, v2 float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform3f, + a0: dst.c(), + a1: uintptr(math.Float32bits(v0)), + a2: uintptr(math.Float32bits(v1)), + a3: uintptr(math.Float32bits(v2)), + }, + }) +} + +func (ctx *context) Uniform3fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform3fv, + a0: dst.c(), + a1: uintptr(len(src) / 3), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform3i(dst Uniform, v0, v1, v2 int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform3i, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + a3: uintptr(v2), + }, + }) +} + +func (ctx *context) Uniform3iv(dst Uniform, src []int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform3iv, + a0: dst.c(), + a1: uintptr(len(src) / 3), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform4f, + a0: dst.c(), + a1: uintptr(math.Float32bits(v0)), + a2: uintptr(math.Float32bits(v1)), + a3: uintptr(math.Float32bits(v2)), + a4: uintptr(math.Float32bits(v3)), + }, + }) +} + +func (ctx *context) Uniform4fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform4fv, + a0: dst.c(), + a1: uintptr(len(src) / 4), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform4i(dst Uniform, v0, v1, v2, v3 int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform4i, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + a3: uintptr(v2), + a4: uintptr(v3), + }, + }) +} + +func (ctx *context) Uniform4iv(dst Uniform, src []int32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform4iv, + a0: dst.c(), + a1: uintptr(len(src) / 4), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) UniformMatrix2fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix2fv, + // OpenGL ES 2 does not support transpose. + a0: dst.c(), + a1: uintptr(len(src) / 4), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) UniformMatrix3fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix3fv, + a0: dst.c(), + a1: uintptr(len(src) / 9), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) UniformMatrix4fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix4fv, + a0: dst.c(), + a1: uintptr(len(src) / 16), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) UseProgram(p Program) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUseProgram, + a0: p.c(), + }, + }) +} + +func (ctx *context) ValidateProgram(p Program) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnValidateProgram, + a0: p.c(), + }, + }) +} + +func (ctx *context) VertexAttrib1f(dst Attrib, x float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttrib1f, + a0: dst.c(), + a1: uintptr(math.Float32bits(x)), + }, + }) +} + +func (ctx *context) VertexAttrib1fv(dst Attrib, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttrib1fv, + a0: dst.c(), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) VertexAttrib2f(dst Attrib, x, y float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttrib2f, + a0: dst.c(), + a1: uintptr(math.Float32bits(x)), + a2: uintptr(math.Float32bits(y)), + }, + }) +} + +func (ctx *context) VertexAttrib2fv(dst Attrib, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttrib2fv, + a0: dst.c(), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) VertexAttrib3f(dst Attrib, x, y, z float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttrib3f, + a0: dst.c(), + a1: uintptr(math.Float32bits(x)), + a2: uintptr(math.Float32bits(y)), + a3: uintptr(math.Float32bits(z)), + }, + }) +} + +func (ctx *context) VertexAttrib3fv(dst Attrib, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttrib3fv, + a0: dst.c(), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) VertexAttrib4f(dst Attrib, x, y, z, w float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttrib4f, + a0: dst.c(), + a1: uintptr(math.Float32bits(x)), + a2: uintptr(math.Float32bits(y)), + a3: uintptr(math.Float32bits(z)), + a4: uintptr(math.Float32bits(w)), + }, + }) +} + +func (ctx *context) VertexAttrib4fv(dst Attrib, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttrib4fv, + a0: dst.c(), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnVertexAttribPointer, + a0: dst.c(), + a1: uintptr(size), + a2: ty.c(), + a3: glBoolean(normalized), + a4: uintptr(stride), + a5: uintptr(offset), + }, + }) +} + +func (ctx *context) Viewport(x, y, width, height int) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnViewport, + a0: uintptr(x), + a1: uintptr(y), + a2: uintptr(width), + a3: uintptr(height), + }, + }) +} + +func (ctx context3) UniformMatrix2x3fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix2x3fv, + a0: dst.c(), + a1: uintptr(len(src) / 6), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix3x2fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix3x2fv, + a0: dst.c(), + a1: uintptr(len(src) / 6), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix2x4fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix2x4fv, + a0: dst.c(), + a1: uintptr(len(src) / 8), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix4x2fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix4x2fv, + a0: dst.c(), + a1: uintptr(len(src) / 8), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix3x4fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix3x4fv, + a0: dst.c(), + a1: uintptr(len(src) / 12), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix4x3fv(dst Uniform, src []float32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniformMatrix4x3fv, + a0: dst.c(), + a1: uintptr(len(src) / 12), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnBlitFramebuffer, + a0: uintptr(srcX0), + a1: uintptr(srcY0), + a2: uintptr(srcX1), + a3: uintptr(srcY1), + a4: uintptr(dstX0), + a5: uintptr(dstY0), + a6: uintptr(dstX1), + a7: uintptr(dstY1), + a8: uintptr(mask), + a9: filter.c(), + }, + }) +} + +func (ctx context3) Uniform1ui(dst Uniform, v uint32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform1ui, + a0: dst.c(), + a1: uintptr(v), + }, + }) +} + +func (ctx context3) Uniform2ui(dst Uniform, v0, v1 uint32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform2ui, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + }, + }) +} + +func (ctx context3) Uniform3ui(dst Uniform, v0, v1, v2 uint) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform3ui, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + a3: uintptr(v2), + }, + }) +} + +func (ctx context3) Uniform4ui(dst Uniform, v0, v1, v2, v3 uint32) { + ctx.enqueue(call{ + args: fnargs{ + fn: glfnUniform4ui, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + a3: uintptr(v2), + a4: uintptr(v3), + }, + }) +} diff --git a/vendor/golang.org/x/mobile/gl/gldebug.go b/vendor/golang.org/x/mobile/gl/gldebug.go new file mode 100644 index 00000000..b3aca42e --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/gldebug.go @@ -0,0 +1,3672 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Code generated from gl.go using go generate. DO NOT EDIT. +// See doc.go for details. + +//go:build (darwin || linux || openbsd || windows) && gldebug + +package gl + +import ( + "fmt" + "log" + "math" + "sync/atomic" + "unsafe" +) + +func (ctx *context) errDrain() string { + var errs []Enum + for { + e := ctx.GetError() + if e == 0 { + break + } + errs = append(errs, e) + } + if len(errs) > 0 { + return fmt.Sprintf(" error: %v", errs) + } + return "" +} + +func (ctx *context) enqueueDebug(c call) uintptr { + numCalls := atomic.AddInt32(&ctx.debug, 1) + if numCalls > 1 { + panic("concurrent calls made to the same GL context") + } + defer func() { + if atomic.AddInt32(&ctx.debug, -1) > 0 { + select {} // block so you see us in the panic + } + }() + + return ctx.enqueue(c) +} + +func (v Enum) String() string { + switch v { + case 0x0: + return "0" + case 0x1: + return "1" + case 0x2: + return "2" + case 0x3: + return "LINE_STRIP" + case 0x4: + return "4" + case 0x5: + return "TRIANGLE_STRIP" + case 0x6: + return "TRIANGLE_FAN" + case 0x300: + return "SRC_COLOR" + case 0x301: + return "ONE_MINUS_SRC_COLOR" + case 0x302: + return "SRC_ALPHA" + case 0x303: + return "ONE_MINUS_SRC_ALPHA" + case 0x304: + return "DST_ALPHA" + case 0x305: + return "ONE_MINUS_DST_ALPHA" + case 0x306: + return "DST_COLOR" + case 0x307: + return "ONE_MINUS_DST_COLOR" + case 0x308: + return "SRC_ALPHA_SATURATE" + case 0x8006: + return "FUNC_ADD" + case 0x8009: + return "32777" + case 0x883d: + return "BLEND_EQUATION_ALPHA" + case 0x800a: + return "FUNC_SUBTRACT" + case 0x800b: + return "FUNC_REVERSE_SUBTRACT" + case 0x80c8: + return "BLEND_DST_RGB" + case 0x80c9: + return "BLEND_SRC_RGB" + case 0x80ca: + return "BLEND_DST_ALPHA" + case 0x80cb: + return "BLEND_SRC_ALPHA" + case 0x8001: + return "CONSTANT_COLOR" + case 0x8002: + return "ONE_MINUS_CONSTANT_COLOR" + case 0x8003: + return "CONSTANT_ALPHA" + case 0x8004: + return "ONE_MINUS_CONSTANT_ALPHA" + case 0x8005: + return "BLEND_COLOR" + case 0x8892: + return "ARRAY_BUFFER" + case 0x8893: + return "ELEMENT_ARRAY_BUFFER" + case 0x8894: + return "ARRAY_BUFFER_BINDING" + case 0x8895: + return "ELEMENT_ARRAY_BUFFER_BINDING" + case 0x88e0: + return "STREAM_DRAW" + case 0x88e4: + return "STATIC_DRAW" + case 0x88e8: + return "DYNAMIC_DRAW" + case 0x8764: + return "BUFFER_SIZE" + case 0x8765: + return "BUFFER_USAGE" + case 0x8626: + return "CURRENT_VERTEX_ATTRIB" + case 0x404: + return "FRONT" + case 0x405: + return "BACK" + case 0x408: + return "FRONT_AND_BACK" + case 0xde1: + return "TEXTURE_2D" + case 0xb44: + return "CULL_FACE" + case 0xbe2: + return "BLEND" + case 0xbd0: + return "DITHER" + case 0xb90: + return "STENCIL_TEST" + case 0xb71: + return "DEPTH_TEST" + case 0xc11: + return "SCISSOR_TEST" + case 0x8037: + return "POLYGON_OFFSET_FILL" + case 0x809e: + return "SAMPLE_ALPHA_TO_COVERAGE" + case 0x80a0: + return "SAMPLE_COVERAGE" + case 0x500: + return "INVALID_ENUM" + case 0x501: + return "INVALID_VALUE" + case 0x502: + return "INVALID_OPERATION" + case 0x505: + return "OUT_OF_MEMORY" + case 0x900: + return "CW" + case 0x901: + return "CCW" + case 0xb21: + return "LINE_WIDTH" + case 0x846d: + return "ALIASED_POINT_SIZE_RANGE" + case 0x846e: + return "ALIASED_LINE_WIDTH_RANGE" + case 0xb45: + return "CULL_FACE_MODE" + case 0xb46: + return "FRONT_FACE" + case 0xb70: + return "DEPTH_RANGE" + case 0xb72: + return "DEPTH_WRITEMASK" + case 0xb73: + return "DEPTH_CLEAR_VALUE" + case 0xb74: + return "DEPTH_FUNC" + case 0xb91: + return "STENCIL_CLEAR_VALUE" + case 0xb92: + return "STENCIL_FUNC" + case 0xb94: + return "STENCIL_FAIL" + case 0xb95: + return "STENCIL_PASS_DEPTH_FAIL" + case 0xb96: + return "STENCIL_PASS_DEPTH_PASS" + case 0xb97: + return "STENCIL_REF" + case 0xb93: + return "STENCIL_VALUE_MASK" + case 0xb98: + return "STENCIL_WRITEMASK" + case 0x8800: + return "STENCIL_BACK_FUNC" + case 0x8801: + return "STENCIL_BACK_FAIL" + case 0x8802: + return "STENCIL_BACK_PASS_DEPTH_FAIL" + case 0x8803: + return "STENCIL_BACK_PASS_DEPTH_PASS" + case 0x8ca3: + return "STENCIL_BACK_REF" + case 0x8ca4: + return "STENCIL_BACK_VALUE_MASK" + case 0x8ca5: + return "STENCIL_BACK_WRITEMASK" + case 0xba2: + return "VIEWPORT" + case 0xc10: + return "SCISSOR_BOX" + case 0xc22: + return "COLOR_CLEAR_VALUE" + case 0xc23: + return "COLOR_WRITEMASK" + case 0xcf5: + return "UNPACK_ALIGNMENT" + case 0xd05: + return "PACK_ALIGNMENT" + case 0xd33: + return "MAX_TEXTURE_SIZE" + case 0xd3a: + return "MAX_VIEWPORT_DIMS" + case 0xd50: + return "SUBPIXEL_BITS" + case 0xd52: + return "RED_BITS" + case 0xd53: + return "GREEN_BITS" + case 0xd54: + return "BLUE_BITS" + case 0xd55: + return "ALPHA_BITS" + case 0xd56: + return "DEPTH_BITS" + case 0xd57: + return "STENCIL_BITS" + case 0x2a00: + return "POLYGON_OFFSET_UNITS" + case 0x8038: + return "POLYGON_OFFSET_FACTOR" + case 0x8069: + return "TEXTURE_BINDING_2D" + case 0x80a8: + return "SAMPLE_BUFFERS" + case 0x80a9: + return "SAMPLES" + case 0x80aa: + return "SAMPLE_COVERAGE_VALUE" + case 0x80ab: + return "SAMPLE_COVERAGE_INVERT" + case 0x86a2: + return "NUM_COMPRESSED_TEXTURE_FORMATS" + case 0x86a3: + return "COMPRESSED_TEXTURE_FORMATS" + case 0x1100: + return "DONT_CARE" + case 0x1101: + return "FASTEST" + case 0x1102: + return "NICEST" + case 0x8192: + return "GENERATE_MIPMAP_HINT" + case 0x1400: + return "BYTE" + case 0x1401: + return "UNSIGNED_BYTE" + case 0x1402: + return "SHORT" + case 0x1403: + return "UNSIGNED_SHORT" + case 0x1404: + return "INT" + case 0x1405: + return "UNSIGNED_INT" + case 0x1406: + return "FLOAT" + case 0x140c: + return "FIXED" + case 0x1902: + return "DEPTH_COMPONENT" + case 0x1906: + return "ALPHA" + case 0x1907: + return "RGB" + case 0x1908: + return "RGBA" + case 0x1909: + return "LUMINANCE" + case 0x190a: + return "LUMINANCE_ALPHA" + case 0x8033: + return "UNSIGNED_SHORT_4_4_4_4" + case 0x8034: + return "UNSIGNED_SHORT_5_5_5_1" + case 0x8363: + return "UNSIGNED_SHORT_5_6_5" + case 0x8869: + return "MAX_VERTEX_ATTRIBS" + case 0x8dfb: + return "MAX_VERTEX_UNIFORM_VECTORS" + case 0x8dfc: + return "MAX_VARYING_VECTORS" + case 0x8b4d: + return "MAX_COMBINED_TEXTURE_IMAGE_UNITS" + case 0x8b4c: + return "MAX_VERTEX_TEXTURE_IMAGE_UNITS" + case 0x8872: + return "MAX_TEXTURE_IMAGE_UNITS" + case 0x8dfd: + return "MAX_FRAGMENT_UNIFORM_VECTORS" + case 0x8b4f: + return "SHADER_TYPE" + case 0x8b80: + return "DELETE_STATUS" + case 0x8b82: + return "LINK_STATUS" + case 0x8b83: + return "VALIDATE_STATUS" + case 0x8b85: + return "ATTACHED_SHADERS" + case 0x8b86: + return "ACTIVE_UNIFORMS" + case 0x8b87: + return "ACTIVE_UNIFORM_MAX_LENGTH" + case 0x8b89: + return "ACTIVE_ATTRIBUTES" + case 0x8b8a: + return "ACTIVE_ATTRIBUTE_MAX_LENGTH" + case 0x8b8c: + return "SHADING_LANGUAGE_VERSION" + case 0x8b8d: + return "CURRENT_PROGRAM" + case 0x200: + return "NEVER" + case 0x201: + return "LESS" + case 0x202: + return "EQUAL" + case 0x203: + return "LEQUAL" + case 0x204: + return "GREATER" + case 0x205: + return "NOTEQUAL" + case 0x206: + return "GEQUAL" + case 0x207: + return "ALWAYS" + case 0x1e00: + return "KEEP" + case 0x1e01: + return "REPLACE" + case 0x1e02: + return "INCR" + case 0x1e03: + return "DECR" + case 0x150a: + return "INVERT" + case 0x8507: + return "INCR_WRAP" + case 0x8508: + return "DECR_WRAP" + case 0x1f00: + return "VENDOR" + case 0x1f01: + return "RENDERER" + case 0x1f02: + return "VERSION" + case 0x1f03: + return "EXTENSIONS" + case 0x2600: + return "NEAREST" + case 0x2601: + return "LINEAR" + case 0x2700: + return "NEAREST_MIPMAP_NEAREST" + case 0x2701: + return "LINEAR_MIPMAP_NEAREST" + case 0x2702: + return "NEAREST_MIPMAP_LINEAR" + case 0x2703: + return "LINEAR_MIPMAP_LINEAR" + case 0x2800: + return "TEXTURE_MAG_FILTER" + case 0x2801: + return "TEXTURE_MIN_FILTER" + case 0x2802: + return "TEXTURE_WRAP_S" + case 0x2803: + return "TEXTURE_WRAP_T" + case 0x1702: + return "TEXTURE" + case 0x8513: + return "TEXTURE_CUBE_MAP" + case 0x8514: + return "TEXTURE_BINDING_CUBE_MAP" + case 0x8515: + return "TEXTURE_CUBE_MAP_POSITIVE_X" + case 0x8516: + return "TEXTURE_CUBE_MAP_NEGATIVE_X" + case 0x8517: + return "TEXTURE_CUBE_MAP_POSITIVE_Y" + case 0x8518: + return "TEXTURE_CUBE_MAP_NEGATIVE_Y" + case 0x8519: + return "TEXTURE_CUBE_MAP_POSITIVE_Z" + case 0x851a: + return "TEXTURE_CUBE_MAP_NEGATIVE_Z" + case 0x851c: + return "MAX_CUBE_MAP_TEXTURE_SIZE" + case 0x84c0: + return "TEXTURE0" + case 0x84c1: + return "TEXTURE1" + case 0x84c2: + return "TEXTURE2" + case 0x84c3: + return "TEXTURE3" + case 0x84c4: + return "TEXTURE4" + case 0x84c5: + return "TEXTURE5" + case 0x84c6: + return "TEXTURE6" + case 0x84c7: + return "TEXTURE7" + case 0x84c8: + return "TEXTURE8" + case 0x84c9: + return "TEXTURE9" + case 0x84ca: + return "TEXTURE10" + case 0x84cb: + return "TEXTURE11" + case 0x84cc: + return "TEXTURE12" + case 0x84cd: + return "TEXTURE13" + case 0x84ce: + return "TEXTURE14" + case 0x84cf: + return "TEXTURE15" + case 0x84d0: + return "TEXTURE16" + case 0x84d1: + return "TEXTURE17" + case 0x84d2: + return "TEXTURE18" + case 0x84d3: + return "TEXTURE19" + case 0x84d4: + return "TEXTURE20" + case 0x84d5: + return "TEXTURE21" + case 0x84d6: + return "TEXTURE22" + case 0x84d7: + return "TEXTURE23" + case 0x84d8: + return "TEXTURE24" + case 0x84d9: + return "TEXTURE25" + case 0x84da: + return "TEXTURE26" + case 0x84db: + return "TEXTURE27" + case 0x84dc: + return "TEXTURE28" + case 0x84dd: + return "TEXTURE29" + case 0x84de: + return "TEXTURE30" + case 0x84df: + return "TEXTURE31" + case 0x84e0: + return "ACTIVE_TEXTURE" + case 0x2901: + return "REPEAT" + case 0x812f: + return "CLAMP_TO_EDGE" + case 0x8370: + return "MIRRORED_REPEAT" + case 0x8622: + return "VERTEX_ATTRIB_ARRAY_ENABLED" + case 0x8623: + return "VERTEX_ATTRIB_ARRAY_SIZE" + case 0x8624: + return "VERTEX_ATTRIB_ARRAY_STRIDE" + case 0x8625: + return "VERTEX_ATTRIB_ARRAY_TYPE" + case 0x886a: + return "VERTEX_ATTRIB_ARRAY_NORMALIZED" + case 0x8645: + return "VERTEX_ATTRIB_ARRAY_POINTER" + case 0x889f: + return "VERTEX_ATTRIB_ARRAY_BUFFER_BINDING" + case 0x8b9a: + return "IMPLEMENTATION_COLOR_READ_TYPE" + case 0x8b9b: + return "IMPLEMENTATION_COLOR_READ_FORMAT" + case 0x8b81: + return "COMPILE_STATUS" + case 0x8b84: + return "INFO_LOG_LENGTH" + case 0x8b88: + return "SHADER_SOURCE_LENGTH" + case 0x8dfa: + return "SHADER_COMPILER" + case 0x8df8: + return "SHADER_BINARY_FORMATS" + case 0x8df9: + return "NUM_SHADER_BINARY_FORMATS" + case 0x8df0: + return "LOW_FLOAT" + case 0x8df1: + return "MEDIUM_FLOAT" + case 0x8df2: + return "HIGH_FLOAT" + case 0x8df3: + return "LOW_INT" + case 0x8df4: + return "MEDIUM_INT" + case 0x8df5: + return "HIGH_INT" + case 0x8d40: + return "FRAMEBUFFER" + case 0x8d41: + return "RENDERBUFFER" + case 0x8056: + return "RGBA4" + case 0x8057: + return "RGB5_A1" + case 0x8d62: + return "RGB565" + case 0x81a5: + return "DEPTH_COMPONENT16" + case 0x8d48: + return "STENCIL_INDEX8" + case 0x8d42: + return "RENDERBUFFER_WIDTH" + case 0x8d43: + return "RENDERBUFFER_HEIGHT" + case 0x8d44: + return "RENDERBUFFER_INTERNAL_FORMAT" + case 0x8d50: + return "RENDERBUFFER_RED_SIZE" + case 0x8d51: + return "RENDERBUFFER_GREEN_SIZE" + case 0x8d52: + return "RENDERBUFFER_BLUE_SIZE" + case 0x8d53: + return "RENDERBUFFER_ALPHA_SIZE" + case 0x8d54: + return "RENDERBUFFER_DEPTH_SIZE" + case 0x8d55: + return "RENDERBUFFER_STENCIL_SIZE" + case 0x8cd0: + return "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE" + case 0x8cd1: + return "FRAMEBUFFER_ATTACHMENT_OBJECT_NAME" + case 0x8cd2: + return "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL" + case 0x8cd3: + return "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE" + case 0x8ce0: + return "COLOR_ATTACHMENT0" + case 0x8d00: + return "DEPTH_ATTACHMENT" + case 0x8d20: + return "STENCIL_ATTACHMENT" + case 0x8cd5: + return "FRAMEBUFFER_COMPLETE" + case 0x8cd6: + return "FRAMEBUFFER_INCOMPLETE_ATTACHMENT" + case 0x8cd7: + return "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT" + case 0x8cd9: + return "FRAMEBUFFER_INCOMPLETE_DIMENSIONS" + case 0x8cdd: + return "FRAMEBUFFER_UNSUPPORTED" + case 0x8ca6: + return "36006" + case 0x8ca7: + return "RENDERBUFFER_BINDING" + case 0x84e8: + return "MAX_RENDERBUFFER_SIZE" + case 0x506: + return "INVALID_FRAMEBUFFER_OPERATION" + case 0x100: + return "DEPTH_BUFFER_BIT" + case 0x400: + return "STENCIL_BUFFER_BIT" + case 0x4000: + return "COLOR_BUFFER_BIT" + case 0x8b50: + return "FLOAT_VEC2" + case 0x8b51: + return "FLOAT_VEC3" + case 0x8b52: + return "FLOAT_VEC4" + case 0x8b53: + return "INT_VEC2" + case 0x8b54: + return "INT_VEC3" + case 0x8b55: + return "INT_VEC4" + case 0x8b56: + return "BOOL" + case 0x8b57: + return "BOOL_VEC2" + case 0x8b58: + return "BOOL_VEC3" + case 0x8b59: + return "BOOL_VEC4" + case 0x8b5a: + return "FLOAT_MAT2" + case 0x8b5b: + return "FLOAT_MAT3" + case 0x8b5c: + return "FLOAT_MAT4" + case 0x8b5e: + return "SAMPLER_2D" + case 0x8b60: + return "SAMPLER_CUBE" + case 0x8b30: + return "FRAGMENT_SHADER" + case 0x8b31: + return "VERTEX_SHADER" + case 0x8a35: + return "ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH" + case 0x8a36: + return "ACTIVE_UNIFORM_BLOCKS" + case 0x911a: + return "ALREADY_SIGNALED" + case 0x8c2f: + return "ANY_SAMPLES_PASSED" + case 0x8d6a: + return "ANY_SAMPLES_PASSED_CONSERVATIVE" + case 0x1905: + return "BLUE" + case 0x911f: + return "BUFFER_ACCESS_FLAGS" + case 0x9120: + return "BUFFER_MAP_LENGTH" + case 0x9121: + return "BUFFER_MAP_OFFSET" + case 0x88bc: + return "BUFFER_MAPPED" + case 0x88bd: + return "BUFFER_MAP_POINTER" + case 0x1800: + return "COLOR" + case 0x8cea: + return "COLOR_ATTACHMENT10" + case 0x8ce1: + return "COLOR_ATTACHMENT1" + case 0x8ceb: + return "COLOR_ATTACHMENT11" + case 0x8cec: + return "COLOR_ATTACHMENT12" + case 0x8ced: + return "COLOR_ATTACHMENT13" + case 0x8cee: + return "COLOR_ATTACHMENT14" + case 0x8cef: + return "COLOR_ATTACHMENT15" + case 0x8ce2: + return "COLOR_ATTACHMENT2" + case 0x8ce3: + return "COLOR_ATTACHMENT3" + case 0x8ce4: + return "COLOR_ATTACHMENT4" + case 0x8ce5: + return "COLOR_ATTACHMENT5" + case 0x8ce6: + return "COLOR_ATTACHMENT6" + case 0x8ce7: + return "COLOR_ATTACHMENT7" + case 0x8ce8: + return "COLOR_ATTACHMENT8" + case 0x8ce9: + return "COLOR_ATTACHMENT9" + case 0x884e: + return "COMPARE_REF_TO_TEXTURE" + case 0x9270: + return "COMPRESSED_R11_EAC" + case 0x9272: + return "COMPRESSED_RG11_EAC" + case 0x9274: + return "COMPRESSED_RGB8_ETC2" + case 0x9276: + return "COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2" + case 0x9278: + return "COMPRESSED_RGBA8_ETC2_EAC" + case 0x9271: + return "COMPRESSED_SIGNED_R11_EAC" + case 0x9273: + return "COMPRESSED_SIGNED_RG11_EAC" + case 0x9279: + return "COMPRESSED_SRGB8_ALPHA8_ETC2_EAC" + case 0x9275: + return "COMPRESSED_SRGB8_ETC2" + case 0x9277: + return "COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2" + case 0x911c: + return "CONDITION_SATISFIED" + case 0x8f36: + return "36662" + case 0x8f37: + return "36663" + case 0x8865: + return "CURRENT_QUERY" + case 0x1801: + return "DEPTH" + case 0x88f0: + return "DEPTH24_STENCIL8" + case 0x8cad: + return "DEPTH32F_STENCIL8" + case 0x81a6: + return "DEPTH_COMPONENT24" + case 0x8cac: + return "DEPTH_COMPONENT32F" + case 0x84f9: + return "DEPTH_STENCIL" + case 0x821a: + return "DEPTH_STENCIL_ATTACHMENT" + case 0x8825: + return "DRAW_BUFFER0" + case 0x882f: + return "DRAW_BUFFER10" + case 0x8826: + return "DRAW_BUFFER1" + case 0x8830: + return "DRAW_BUFFER11" + case 0x8831: + return "DRAW_BUFFER12" + case 0x8832: + return "DRAW_BUFFER13" + case 0x8833: + return "DRAW_BUFFER14" + case 0x8834: + return "DRAW_BUFFER15" + case 0x8827: + return "DRAW_BUFFER2" + case 0x8828: + return "DRAW_BUFFER3" + case 0x8829: + return "DRAW_BUFFER4" + case 0x882a: + return "DRAW_BUFFER5" + case 0x882b: + return "DRAW_BUFFER6" + case 0x882c: + return "DRAW_BUFFER7" + case 0x882d: + return "DRAW_BUFFER8" + case 0x882e: + return "DRAW_BUFFER9" + case 0x8ca9: + return "DRAW_FRAMEBUFFER" + case 0x88ea: + return "DYNAMIC_COPY" + case 0x88e9: + return "DYNAMIC_READ" + case 0x8dad: + return "FLOAT_32_UNSIGNED_INT_24_8_REV" + case 0x8b65: + return "FLOAT_MAT2x3" + case 0x8b66: + return "FLOAT_MAT2x4" + case 0x8b67: + return "FLOAT_MAT3x2" + case 0x8b68: + return "FLOAT_MAT3x4" + case 0x8b69: + return "FLOAT_MAT4x2" + case 0x8b6a: + return "FLOAT_MAT4x3" + case 0x8b8b: + return "FRAGMENT_SHADER_DERIVATIVE_HINT" + case 0x8215: + return "FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE" + case 0x8214: + return "FRAMEBUFFER_ATTACHMENT_BLUE_SIZE" + case 0x8210: + return "FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING" + case 0x8211: + return "FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE" + case 0x8216: + return "FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE" + case 0x8213: + return "FRAMEBUFFER_ATTACHMENT_GREEN_SIZE" + case 0x8212: + return "FRAMEBUFFER_ATTACHMENT_RED_SIZE" + case 0x8217: + return "FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE" + case 0x8cd4: + return "FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER" + case 0x8218: + return "FRAMEBUFFER_DEFAULT" + case 0x8d56: + return "FRAMEBUFFER_INCOMPLETE_MULTISAMPLE" + case 0x8219: + return "FRAMEBUFFER_UNDEFINED" + case 0x1904: + return "GREEN" + case 0x140b: + return "HALF_FLOAT" + case 0x8d9f: + return "INT_2_10_10_10_REV" + case 0x8c8c: + return "INTERLEAVED_ATTRIBS" + case 0x8dca: + return "INT_SAMPLER_2D" + case 0x8dcf: + return "INT_SAMPLER_2D_ARRAY" + case 0x8dcb: + return "INT_SAMPLER_3D" + case 0x8dcc: + return "INT_SAMPLER_CUBE" + case 0xffffffff: + return "INVALID_INDEX" + case 0x821b: + return "MAJOR_VERSION" + case 0x10: + return "MAP_FLUSH_EXPLICIT_BIT" + case 0x8: + return "MAP_INVALIDATE_BUFFER_BIT" + case 0x20: + return "MAP_UNSYNCHRONIZED_BIT" + case 0x8008: + return "MAX" + case 0x8073: + return "MAX_3D_TEXTURE_SIZE" + case 0x88ff: + return "MAX_ARRAY_TEXTURE_LAYERS" + case 0x8cdf: + return "MAX_COLOR_ATTACHMENTS" + case 0x8a33: + return "MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS" + case 0x8a2e: + return "MAX_COMBINED_UNIFORM_BLOCKS" + case 0x8a31: + return "MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS" + case 0x8824: + return "MAX_DRAW_BUFFERS" + case 0x8d6b: + return "MAX_ELEMENT_INDEX" + case 0x80e9: + return "MAX_ELEMENTS_INDICES" + case 0x80e8: + return "MAX_ELEMENTS_VERTICES" + case 0x9125: + return "MAX_FRAGMENT_INPUT_COMPONENTS" + case 0x8a2d: + return "MAX_FRAGMENT_UNIFORM_BLOCKS" + case 0x8b49: + return "MAX_FRAGMENT_UNIFORM_COMPONENTS" + case 0x8905: + return "MAX_PROGRAM_TEXEL_OFFSET" + case 0x8d57: + return "MAX_SAMPLES" + case 0x9111: + return "MAX_SERVER_WAIT_TIMEOUT" + case 0x84fd: + return "MAX_TEXTURE_LOD_BIAS" + case 0x8c8a: + return "MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS" + case 0x8c8b: + return "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS" + case 0x8c80: + return "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS" + case 0x8a30: + return "MAX_UNIFORM_BLOCK_SIZE" + case 0x8a2f: + return "MAX_UNIFORM_BUFFER_BINDINGS" + case 0x8b4b: + return "MAX_VARYING_COMPONENTS" + case 0x9122: + return "MAX_VERTEX_OUTPUT_COMPONENTS" + case 0x8a2b: + return "MAX_VERTEX_UNIFORM_BLOCKS" + case 0x8b4a: + return "MAX_VERTEX_UNIFORM_COMPONENTS" + case 0x8007: + return "MIN" + case 0x821c: + return "MINOR_VERSION" + case 0x8904: + return "MIN_PROGRAM_TEXEL_OFFSET" + case 0x821d: + return "NUM_EXTENSIONS" + case 0x87fe: + return "NUM_PROGRAM_BINARY_FORMATS" + case 0x9380: + return "NUM_SAMPLE_COUNTS" + case 0x9112: + return "OBJECT_TYPE" + case 0xd02: + return "PACK_ROW_LENGTH" + case 0xd04: + return "PACK_SKIP_PIXELS" + case 0xd03: + return "PACK_SKIP_ROWS" + case 0x88eb: + return "PIXEL_PACK_BUFFER" + case 0x88ed: + return "PIXEL_PACK_BUFFER_BINDING" + case 0x88ec: + return "PIXEL_UNPACK_BUFFER" + case 0x88ef: + return "PIXEL_UNPACK_BUFFER_BINDING" + case 0x8d69: + return "PRIMITIVE_RESTART_FIXED_INDEX" + case 0x87ff: + return "PROGRAM_BINARY_FORMATS" + case 0x8741: + return "PROGRAM_BINARY_LENGTH" + case 0x8257: + return "PROGRAM_BINARY_RETRIEVABLE_HINT" + case 0x8866: + return "QUERY_RESULT" + case 0x8867: + return "QUERY_RESULT_AVAILABLE" + case 0x8c3a: + return "R11F_G11F_B10F" + case 0x822d: + return "R16F" + case 0x8233: + return "R16I" + case 0x8234: + return "R16UI" + case 0x822e: + return "R32F" + case 0x8235: + return "R32I" + case 0x8236: + return "R32UI" + case 0x8229: + return "R8" + case 0x8231: + return "R8I" + case 0x8f94: + return "R8_SNORM" + case 0x8232: + return "R8UI" + case 0x8c89: + return "RASTERIZER_DISCARD" + case 0xc02: + return "READ_BUFFER" + case 0x8ca8: + return "READ_FRAMEBUFFER" + case 0x8caa: + return "READ_FRAMEBUFFER_BINDING" + case 0x1903: + return "RED" + case 0x8d94: + return "RED_INTEGER" + case 0x8cab: + return "RENDERBUFFER_SAMPLES" + case 0x8227: + return "RG" + case 0x822f: + return "RG16F" + case 0x8239: + return "RG16I" + case 0x823a: + return "RG16UI" + case 0x8230: + return "RG32F" + case 0x823b: + return "RG32I" + case 0x823c: + return "RG32UI" + case 0x822b: + return "RG8" + case 0x8237: + return "RG8I" + case 0x8f95: + return "RG8_SNORM" + case 0x8238: + return "RG8UI" + case 0x8059: + return "RGB10_A2" + case 0x906f: + return "RGB10_A2UI" + case 0x881b: + return "RGB16F" + case 0x8d89: + return "RGB16I" + case 0x8d77: + return "RGB16UI" + case 0x8815: + return "RGB32F" + case 0x8d83: + return "RGB32I" + case 0x8d71: + return "RGB32UI" + case 0x8051: + return "RGB8" + case 0x8d8f: + return "RGB8I" + case 0x8f96: + return "RGB8_SNORM" + case 0x8d7d: + return "RGB8UI" + case 0x8c3d: + return "RGB9_E5" + case 0x881a: + return "RGBA16F" + case 0x8d88: + return "RGBA16I" + case 0x8d76: + return "RGBA16UI" + case 0x8814: + return "RGBA32F" + case 0x8d82: + return "RGBA32I" + case 0x8d70: + return "RGBA32UI" + case 0x8058: + return "RGBA8" + case 0x8d8e: + return "RGBA8I" + case 0x8f97: + return "RGBA8_SNORM" + case 0x8d7c: + return "RGBA8UI" + case 0x8d99: + return "RGBA_INTEGER" + case 0x8d98: + return "RGB_INTEGER" + case 0x8228: + return "RG_INTEGER" + case 0x8dc1: + return "SAMPLER_2D_ARRAY" + case 0x8dc4: + return "SAMPLER_2D_ARRAY_SHADOW" + case 0x8b62: + return "SAMPLER_2D_SHADOW" + case 0x8b5f: + return "SAMPLER_3D" + case 0x8919: + return "SAMPLER_BINDING" + case 0x8dc5: + return "SAMPLER_CUBE_SHADOW" + case 0x8c8d: + return "SEPARATE_ATTRIBS" + case 0x9119: + return "SIGNALED" + case 0x8f9c: + return "SIGNED_NORMALIZED" + case 0x8c40: + return "SRGB" + case 0x8c41: + return "SRGB8" + case 0x8c43: + return "SRGB8_ALPHA8" + case 0x88e6: + return "STATIC_COPY" + case 0x88e5: + return "STATIC_READ" + case 0x1802: + return "STENCIL" + case 0x88e2: + return "STREAM_COPY" + case 0x88e1: + return "STREAM_READ" + case 0x9113: + return "SYNC_CONDITION" + case 0x9116: + return "SYNC_FENCE" + case 0x9115: + return "SYNC_FLAGS" + case 0x9117: + return "SYNC_GPU_COMMANDS_COMPLETE" + case 0x9114: + return "SYNC_STATUS" + case 0x8c1a: + return "TEXTURE_2D_ARRAY" + case 0x806f: + return "TEXTURE_3D" + case 0x813c: + return "TEXTURE_BASE_LEVEL" + case 0x8c1d: + return "TEXTURE_BINDING_2D_ARRAY" + case 0x806a: + return "TEXTURE_BINDING_3D" + case 0x884d: + return "TEXTURE_COMPARE_FUNC" + case 0x884c: + return "TEXTURE_COMPARE_MODE" + case 0x912f: + return "TEXTURE_IMMUTABLE_FORMAT" + case 0x82df: + return "TEXTURE_IMMUTABLE_LEVELS" + case 0x813d: + return "TEXTURE_MAX_LEVEL" + case 0x813b: + return "TEXTURE_MAX_LOD" + case 0x813a: + return "TEXTURE_MIN_LOD" + case 0x8e45: + return "TEXTURE_SWIZZLE_A" + case 0x8e44: + return "TEXTURE_SWIZZLE_B" + case 0x8e43: + return "TEXTURE_SWIZZLE_G" + case 0x8e42: + return "TEXTURE_SWIZZLE_R" + case 0x8072: + return "TEXTURE_WRAP_R" + case 0x911b: + return "TIMEOUT_EXPIRED" + case 0x8e22: + return "TRANSFORM_FEEDBACK" + case 0x8e24: + return "TRANSFORM_FEEDBACK_ACTIVE" + case 0x8e25: + return "TRANSFORM_FEEDBACK_BINDING" + case 0x8c8e: + return "TRANSFORM_FEEDBACK_BUFFER" + case 0x8c8f: + return "TRANSFORM_FEEDBACK_BUFFER_BINDING" + case 0x8c7f: + return "TRANSFORM_FEEDBACK_BUFFER_MODE" + case 0x8c85: + return "TRANSFORM_FEEDBACK_BUFFER_SIZE" + case 0x8c84: + return "TRANSFORM_FEEDBACK_BUFFER_START" + case 0x8e23: + return "TRANSFORM_FEEDBACK_PAUSED" + case 0x8c88: + return "TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN" + case 0x8c76: + return "TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH" + case 0x8c83: + return "TRANSFORM_FEEDBACK_VARYINGS" + case 0x8a3c: + return "UNIFORM_ARRAY_STRIDE" + case 0x8a43: + return "UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES" + case 0x8a42: + return "UNIFORM_BLOCK_ACTIVE_UNIFORMS" + case 0x8a3f: + return "UNIFORM_BLOCK_BINDING" + case 0x8a40: + return "UNIFORM_BLOCK_DATA_SIZE" + case 0x8a3a: + return "UNIFORM_BLOCK_INDEX" + case 0x8a41: + return "UNIFORM_BLOCK_NAME_LENGTH" + case 0x8a46: + return "UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER" + case 0x8a44: + return "UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER" + case 0x8a11: + return "UNIFORM_BUFFER" + case 0x8a28: + return "UNIFORM_BUFFER_BINDING" + case 0x8a34: + return "UNIFORM_BUFFER_OFFSET_ALIGNMENT" + case 0x8a2a: + return "UNIFORM_BUFFER_SIZE" + case 0x8a29: + return "UNIFORM_BUFFER_START" + case 0x8a3e: + return "UNIFORM_IS_ROW_MAJOR" + case 0x8a3d: + return "UNIFORM_MATRIX_STRIDE" + case 0x8a39: + return "UNIFORM_NAME_LENGTH" + case 0x8a3b: + return "UNIFORM_OFFSET" + case 0x8a38: + return "UNIFORM_SIZE" + case 0x8a37: + return "UNIFORM_TYPE" + case 0x806e: + return "UNPACK_IMAGE_HEIGHT" + case 0xcf2: + return "UNPACK_ROW_LENGTH" + case 0x806d: + return "UNPACK_SKIP_IMAGES" + case 0xcf4: + return "UNPACK_SKIP_PIXELS" + case 0xcf3: + return "UNPACK_SKIP_ROWS" + case 0x9118: + return "UNSIGNALED" + case 0x8c3b: + return "UNSIGNED_INT_10F_11F_11F_REV" + case 0x8368: + return "UNSIGNED_INT_2_10_10_10_REV" + case 0x84fa: + return "UNSIGNED_INT_24_8" + case 0x8c3e: + return "UNSIGNED_INT_5_9_9_9_REV" + case 0x8dd2: + return "UNSIGNED_INT_SAMPLER_2D" + case 0x8dd7: + return "UNSIGNED_INT_SAMPLER_2D_ARRAY" + case 0x8dd3: + return "UNSIGNED_INT_SAMPLER_3D" + case 0x8dd4: + return "UNSIGNED_INT_SAMPLER_CUBE" + case 0x8dc6: + return "UNSIGNED_INT_VEC2" + case 0x8dc7: + return "UNSIGNED_INT_VEC3" + case 0x8dc8: + return "UNSIGNED_INT_VEC4" + case 0x8c17: + return "UNSIGNED_NORMALIZED" + case 0x85b5: + return "VERTEX_ARRAY_BINDING" + case 0x88fe: + return "VERTEX_ATTRIB_ARRAY_DIVISOR" + case 0x88fd: + return "VERTEX_ATTRIB_ARRAY_INTEGER" + case 0x911d: + return "WAIT_FAILED" + default: + return fmt.Sprintf("gl.Enum(0x%x)", uint32(v)) + } +} + +func (ctx *context) ActiveTexture(texture Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ActiveTexture(%v) %v", texture, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnActiveTexture, + a0: texture.c(), + }, + blocking: true}) +} + +func (ctx *context) AttachShader(p Program, s Shader) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.AttachShader(%v, %v) %v", p, s, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnAttachShader, + a0: p.c(), + a1: s.c(), + }, + blocking: true}) +} + +func (ctx *context) BindAttribLocation(p Program, a Attrib, name string) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BindAttribLocation(%v, %v, %v) %v", p, a, name, errstr) + }() + s, free := ctx.cString(name) + defer free() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBindAttribLocation, + a0: p.c(), + a1: a.c(), + a2: s, + }, + blocking: true, + }) +} + +func (ctx *context) BindBuffer(target Enum, b Buffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BindBuffer(%v, %v) %v", target, b, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBindBuffer, + a0: target.c(), + a1: b.c(), + }, + blocking: true}) +} + +func (ctx *context) BindFramebuffer(target Enum, fb Framebuffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BindFramebuffer(%v, %v) %v", target, fb, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBindFramebuffer, + a0: target.c(), + a1: fb.c(), + }, + blocking: true}) +} + +func (ctx *context) BindRenderbuffer(target Enum, rb Renderbuffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BindRenderbuffer(%v, %v) %v", target, rb, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBindRenderbuffer, + a0: target.c(), + a1: rb.c(), + }, + blocking: true}) +} + +func (ctx *context) BindTexture(target Enum, t Texture) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BindTexture(%v, %v) %v", target, t, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBindTexture, + a0: target.c(), + a1: t.c(), + }, + blocking: true}) +} + +func (ctx *context) BindVertexArray(va VertexArray) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BindVertexArray(%v) %v", va, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBindVertexArray, + a0: va.c(), + }, + blocking: true}) +} + +func (ctx *context) BlendColor(red, green, blue, alpha float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BlendColor(%v, %v, %v, %v) %v", red, green, blue, alpha, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBlendColor, + a0: uintptr(math.Float32bits(red)), + a1: uintptr(math.Float32bits(green)), + a2: uintptr(math.Float32bits(blue)), + a3: uintptr(math.Float32bits(alpha)), + }, + blocking: true}) +} + +func (ctx *context) BlendEquation(mode Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BlendEquation(%v) %v", mode, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBlendEquation, + a0: mode.c(), + }, + blocking: true}) +} + +func (ctx *context) BlendEquationSeparate(modeRGB, modeAlpha Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BlendEquationSeparate(%v, %v) %v", modeRGB, modeAlpha, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBlendEquationSeparate, + a0: modeRGB.c(), + a1: modeAlpha.c(), + }, + blocking: true}) +} + +func (ctx *context) BlendFunc(sfactor, dfactor Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BlendFunc(%v, %v) %v", sfactor, dfactor, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBlendFunc, + a0: sfactor.c(), + a1: dfactor.c(), + }, + blocking: true}) +} + +func (ctx *context) BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BlendFuncSeparate(%v, %v, %v, %v) %v", sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBlendFuncSeparate, + a0: sfactorRGB.c(), + a1: dfactorRGB.c(), + a2: sfactorAlpha.c(), + a3: dfactorAlpha.c(), + }, + blocking: true}) +} + +func (ctx *context) BufferData(target Enum, src []byte, usage Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BufferData(%v, len(%d), %v) %v", target, len(src), usage, errstr) + }() + parg := unsafe.Pointer(nil) + if len(src) > 0 { + parg = unsafe.Pointer(&src[0]) + } + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBufferData, + a0: target.c(), + a1: uintptr(len(src)), + a2: usage.c(), + }, + parg: parg, + blocking: true, + }) +} + +func (ctx *context) BufferInit(target Enum, size int, usage Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BufferInit(%v, %v, %v) %v", target, size, usage, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBufferData, + a0: target.c(), + a1: uintptr(size), + a2: usage.c(), + }, + parg: unsafe.Pointer(nil), + blocking: true}) +} + +func (ctx *context) BufferSubData(target Enum, offset int, data []byte) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BufferSubData(%v, %v, len(%d)) %v", target, offset, len(data), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBufferSubData, + a0: target.c(), + a1: uintptr(offset), + a2: uintptr(len(data)), + }, + parg: unsafe.Pointer(&data[0]), + blocking: true, + }) +} + +func (ctx *context) CheckFramebufferStatus(target Enum) (r0 Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CheckFramebufferStatus(%v) %v%v", target, r0, errstr) + }() + return Enum(ctx.enqueue(call{ + args: fnargs{ + fn: glfnCheckFramebufferStatus, + a0: target.c(), + }, + blocking: true, + })) +} + +func (ctx *context) Clear(mask Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Clear(%v) %v", mask, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnClear, + a0: uintptr(mask), + }, + blocking: true}) +} + +func (ctx *context) ClearColor(red, green, blue, alpha float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ClearColor(%v, %v, %v, %v) %v", red, green, blue, alpha, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnClearColor, + a0: uintptr(math.Float32bits(red)), + a1: uintptr(math.Float32bits(green)), + a2: uintptr(math.Float32bits(blue)), + a3: uintptr(math.Float32bits(alpha)), + }, + blocking: true}) +} + +func (ctx *context) ClearDepthf(d float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ClearDepthf(%v) %v", d, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnClearDepthf, + a0: uintptr(math.Float32bits(d)), + }, + blocking: true}) +} + +func (ctx *context) ClearStencil(s int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ClearStencil(%v) %v", s, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnClearStencil, + a0: uintptr(s), + }, + blocking: true}) +} + +func (ctx *context) ColorMask(red, green, blue, alpha bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ColorMask(%v, %v, %v, %v) %v", red, green, blue, alpha, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnColorMask, + a0: glBoolean(red), + a1: glBoolean(green), + a2: glBoolean(blue), + a3: glBoolean(alpha), + }, + blocking: true}) +} + +func (ctx *context) CompileShader(s Shader) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CompileShader(%v) %v", s, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnCompileShader, + a0: s.c(), + }, + blocking: true}) +} + +func (ctx *context) CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CompressedTexImage2D(%v, %v, %v, %v, %v, %v, len(%d)) %v", target, level, internalformat, width, height, border, len(data), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnCompressedTexImage2D, + a0: target.c(), + a1: uintptr(level), + a2: internalformat.c(), + a3: uintptr(width), + a4: uintptr(height), + a5: uintptr(border), + a6: uintptr(len(data)), + }, + parg: unsafe.Pointer(&data[0]), + blocking: true, + }) +} + +func (ctx *context) CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CompressedTexSubImage2D(%v, %v, %v, %v, %v, %v, %v, len(%d)) %v", target, level, xoffset, yoffset, width, height, format, len(data), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnCompressedTexSubImage2D, + a0: target.c(), + a1: uintptr(level), + a2: uintptr(xoffset), + a3: uintptr(yoffset), + a4: uintptr(width), + a5: uintptr(height), + a6: format.c(), + a7: uintptr(len(data)), + }, + parg: unsafe.Pointer(&data[0]), + blocking: true, + }) +} + +func (ctx *context) CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CopyTexImage2D(%v, %v, %v, %v, %v, %v, %v, %v) %v", target, level, internalformat, x, y, width, height, border, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnCopyTexImage2D, + a0: target.c(), + a1: uintptr(level), + a2: internalformat.c(), + a3: uintptr(x), + a4: uintptr(y), + a5: uintptr(width), + a6: uintptr(height), + a7: uintptr(border), + }, + blocking: true}) +} + +func (ctx *context) CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CopyTexSubImage2D(%v, %v, %v, %v, %v, %v, %v, %v) %v", target, level, xoffset, yoffset, x, y, width, height, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnCopyTexSubImage2D, + a0: target.c(), + a1: uintptr(level), + a2: uintptr(xoffset), + a3: uintptr(yoffset), + a4: uintptr(x), + a5: uintptr(y), + a6: uintptr(width), + a7: uintptr(height), + }, + blocking: true}) +} + +func (ctx *context) CreateBuffer() (r0 Buffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CreateBuffer() %v%v", r0, errstr) + }() + return Buffer{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenBuffer, + }, + blocking: true, + }))} +} + +func (ctx *context) CreateFramebuffer() (r0 Framebuffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CreateFramebuffer() %v%v", r0, errstr) + }() + return Framebuffer{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenFramebuffer, + }, + blocking: true, + }))} +} + +func (ctx *context) CreateProgram() (r0 Program) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CreateProgram() %v%v", r0, errstr) + }() + return Program{ + Init: true, + Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnCreateProgram, + }, + blocking: true, + }, + ))} +} + +func (ctx *context) CreateRenderbuffer() (r0 Renderbuffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CreateRenderbuffer() %v%v", r0, errstr) + }() + return Renderbuffer{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenRenderbuffer, + }, + blocking: true, + }))} +} + +func (ctx *context) CreateShader(ty Enum) (r0 Shader) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CreateShader(%v) %v%v", ty, r0, errstr) + }() + return Shader{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnCreateShader, + a0: uintptr(ty), + }, + blocking: true, + }))} +} + +func (ctx *context) CreateTexture() (r0 Texture) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CreateTexture() %v%v", r0, errstr) + }() + return Texture{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenTexture, + }, + blocking: true, + }))} +} + +func (ctx *context) CreateVertexArray() (r0 VertexArray) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CreateVertexArray() %v%v", r0, errstr) + }() + return VertexArray{Value: uint32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGenVertexArray, + }, + blocking: true, + }))} +} + +func (ctx *context) CullFace(mode Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.CullFace(%v) %v", mode, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnCullFace, + a0: mode.c(), + }, + blocking: true}) +} + +func (ctx *context) DeleteBuffer(v Buffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DeleteBuffer(%v) %v", v, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDeleteBuffer, + a0: v.c(), + }, + blocking: true}) +} + +func (ctx *context) DeleteFramebuffer(v Framebuffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DeleteFramebuffer(%v) %v", v, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDeleteFramebuffer, + a0: v.c(), + }, + blocking: true}) +} + +func (ctx *context) DeleteProgram(p Program) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DeleteProgram(%v) %v", p, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDeleteProgram, + a0: p.c(), + }, + blocking: true}) +} + +func (ctx *context) DeleteRenderbuffer(v Renderbuffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DeleteRenderbuffer(%v) %v", v, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDeleteRenderbuffer, + a0: v.c(), + }, + blocking: true}) +} + +func (ctx *context) DeleteShader(s Shader) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DeleteShader(%v) %v", s, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDeleteShader, + a0: s.c(), + }, + blocking: true}) +} + +func (ctx *context) DeleteTexture(v Texture) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DeleteTexture(%v) %v", v, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDeleteTexture, + a0: v.c(), + }, + blocking: true}) +} + +func (ctx *context) DeleteVertexArray(v VertexArray) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DeleteVertexArray(%v) %v", v, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDeleteVertexArray, + a0: v.c(), + }, + blocking: true}) +} + +func (ctx *context) DepthFunc(fn Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DepthFunc(%v) %v", fn, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDepthFunc, + a0: fn.c(), + }, + blocking: true}) +} + +func (ctx *context) DepthMask(flag bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DepthMask(%v) %v", flag, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDepthMask, + a0: glBoolean(flag), + }, + blocking: true}) +} + +func (ctx *context) DepthRangef(n, f float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DepthRangef(%v, %v) %v", n, f, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDepthRangef, + a0: uintptr(math.Float32bits(n)), + a1: uintptr(math.Float32bits(f)), + }, + blocking: true}) +} + +func (ctx *context) DetachShader(p Program, s Shader) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DetachShader(%v, %v) %v", p, s, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDetachShader, + a0: p.c(), + a1: s.c(), + }, + blocking: true}) +} + +func (ctx *context) Disable(cap Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Disable(%v) %v", cap, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDisable, + a0: cap.c(), + }, + blocking: true}) +} + +func (ctx *context) DisableVertexAttribArray(a Attrib) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DisableVertexAttribArray(%v) %v", a, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDisableVertexAttribArray, + a0: a.c(), + }, + blocking: true}) +} + +func (ctx *context) DrawArrays(mode Enum, first, count int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DrawArrays(%v, %v, %v) %v", mode, first, count, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDrawArrays, + a0: mode.c(), + a1: uintptr(first), + a2: uintptr(count), + }, + blocking: true}) +} + +func (ctx *context) DrawElements(mode Enum, count int, ty Enum, offset int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.DrawElements(%v, %v, %v, %v) %v", mode, count, ty, offset, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnDrawElements, + a0: mode.c(), + a1: uintptr(count), + a2: ty.c(), + a3: uintptr(offset), + }, + blocking: true}) +} + +func (ctx *context) Enable(cap Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Enable(%v) %v", cap, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnEnable, + a0: cap.c(), + }, + blocking: true}) +} + +func (ctx *context) EnableVertexAttribArray(a Attrib) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.EnableVertexAttribArray(%v) %v", a, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnEnableVertexAttribArray, + a0: a.c(), + }, + blocking: true}) +} + +func (ctx *context) Finish() { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Finish() %v", errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnFinish, + }, + blocking: true, + }) +} + +func (ctx *context) Flush() { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Flush() %v", errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnFlush, + }, + blocking: true, + }) +} + +func (ctx *context) FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.FramebufferRenderbuffer(%v, %v, %v, %v) %v", target, attachment, rbTarget, rb, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnFramebufferRenderbuffer, + a0: target.c(), + a1: attachment.c(), + a2: rbTarget.c(), + a3: rb.c(), + }, + blocking: true}) +} + +func (ctx *context) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.FramebufferTexture2D(%v, %v, %v, %v, %v) %v", target, attachment, texTarget, t, level, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnFramebufferTexture2D, + a0: target.c(), + a1: attachment.c(), + a2: texTarget.c(), + a3: t.c(), + a4: uintptr(level), + }, + blocking: true}) +} + +func (ctx *context) FrontFace(mode Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.FrontFace(%v) %v", mode, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnFrontFace, + a0: mode.c(), + }, + blocking: true}) +} + +func (ctx *context) GenerateMipmap(target Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GenerateMipmap(%v) %v", target, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGenerateMipmap, + a0: target.c(), + }, + blocking: true}) +} + +func (ctx *context) GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetActiveAttrib(%v, %v) (%v, %v, %v) %v", p, index, name, size, ty, errstr) + }() + bufSize := ctx.GetProgrami(p, ACTIVE_ATTRIBUTE_MAX_LENGTH) + buf := make([]byte, bufSize) + var cType int + cSize := ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetActiveAttrib, + a0: p.c(), + a1: uintptr(index), + a2: uintptr(bufSize), + a3: uintptr(unsafe.Pointer(&cType)), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + return goString(buf), int(cSize), Enum(cType) +} + +func (ctx *context) GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetActiveUniform(%v, %v) (%v, %v, %v) %v", p, index, name, size, ty, errstr) + }() + bufSize := ctx.GetProgrami(p, ACTIVE_UNIFORM_MAX_LENGTH) + buf := make([]byte, bufSize+8) + var cType int + cSize := ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetActiveUniform, + a0: p.c(), + a1: uintptr(index), + a2: uintptr(bufSize), + a3: uintptr(unsafe.Pointer(&cType)), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + return goString(buf), int(cSize), Enum(cType) +} + +func (ctx *context) GetAttachedShaders(p Program) (r0 []Shader) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetAttachedShaders(%v) %v%v", p, r0, errstr) + }() + shadersLen := ctx.GetProgrami(p, ATTACHED_SHADERS) + if shadersLen == 0 { + return nil + } + buf := make([]uint32, shadersLen) + n := int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetAttachedShaders, + a0: p.c(), + a1: uintptr(shadersLen), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + })) + buf = buf[:int(n)] + shaders := make([]Shader, len(buf)) + for i, s := range buf { + shaders[i] = Shader{Value: uint32(s)} + } + return shaders +} + +func (ctx *context) GetAttribLocation(p Program, name string) (r0 Attrib) { + defer func() { + errstr := ctx.errDrain() + r0.name = name + log.Printf("gl.GetAttribLocation(%v, %v) %v%v", p, name, r0, errstr) + }() + s, free := ctx.cString(name) + defer free() + return Attrib{Value: uint(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetAttribLocation, + a0: p.c(), + a1: s, + }, + blocking: true, + }))} +} + +func (ctx *context) GetBooleanv(dst []bool, pname Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetBooleanv(%v, %v) %v", dst, pname, errstr) + }() + buf := make([]int32, len(dst)) + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetBooleanv, + a0: pname.c(), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + for i, v := range buf { + dst[i] = v != 0 + } +} + +func (ctx *context) GetFloatv(dst []float32, pname Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetFloatv(len(%d), %v) %v", len(dst), pname, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetFloatv, + a0: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetIntegerv(dst []int32, pname Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetIntegerv(%v, %v) %v", dst, pname, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetIntegerv, + a0: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetInteger(pname Enum) (r0 int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetInteger(%v) %v%v", pname, r0, errstr) + }() + var v [1]int32 + ctx.GetIntegerv(v[:], pname) + return int(v[0]) +} + +func (ctx *context) GetBufferParameteri(target, value Enum) (r0 int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetBufferParameteri(%v, %v) %v%v", target, value, r0, errstr) + }() + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetBufferParameteri, + a0: target.c(), + a1: value.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetError() (r0 Enum) { + return Enum(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetError, + }, + blocking: true, + })) +} + +func (ctx *context) GetFramebufferAttachmentParameteri(target, attachment, pname Enum) (r0 int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetFramebufferAttachmentParameteri(%v, %v, %v) %v%v", target, attachment, pname, r0, errstr) + }() + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetFramebufferAttachmentParameteriv, + a0: target.c(), + a1: attachment.c(), + a2: pname.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetProgrami(p Program, pname Enum) (r0 int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetProgrami(%v, %v) %v%v", p, pname, r0, errstr) + }() + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetProgramiv, + a0: p.c(), + a1: pname.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetProgramInfoLog(p Program) (r0 string) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetProgramInfoLog(%v) %v%v", p, r0, errstr) + }() + infoLen := ctx.GetProgrami(p, INFO_LOG_LENGTH) + if infoLen == 0 { + return "" + } + buf := make([]byte, infoLen) + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetProgramInfoLog, + a0: p.c(), + a1: uintptr(infoLen), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + return goString(buf) +} + +func (ctx *context) GetRenderbufferParameteri(target, pname Enum) (r0 int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetRenderbufferParameteri(%v, %v) %v%v", target, pname, r0, errstr) + }() + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetRenderbufferParameteriv, + a0: target.c(), + a1: pname.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetShaderi(s Shader, pname Enum) (r0 int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetShaderi(%v, %v) %v%v", s, pname, r0, errstr) + }() + return int(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetShaderiv, + a0: s.c(), + a1: pname.c(), + }, + blocking: true, + })) +} + +func (ctx *context) GetShaderInfoLog(s Shader) (r0 string) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetShaderInfoLog(%v) %v%v", s, r0, errstr) + }() + infoLen := ctx.GetShaderi(s, INFO_LOG_LENGTH) + if infoLen == 0 { + return "" + } + buf := make([]byte, infoLen) + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetShaderInfoLog, + a0: s.c(), + a1: uintptr(infoLen), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + return goString(buf) +} + +func (ctx *context) GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetShaderPrecisionFormat(%v, %v) (%v, %v, %v) %v", shadertype, precisiontype, rangeLow, rangeHigh, precision, errstr) + }() + var rangeAndPrec [3]int32 + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetShaderPrecisionFormat, + a0: shadertype.c(), + a1: precisiontype.c(), + }, + parg: unsafe.Pointer(&rangeAndPrec[0]), + blocking: true, + }) + return int(rangeAndPrec[0]), int(rangeAndPrec[1]), int(rangeAndPrec[2]) +} + +func (ctx *context) GetShaderSource(s Shader) (r0 string) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetShaderSource(%v) %v%v", s, r0, errstr) + }() + sourceLen := ctx.GetShaderi(s, SHADER_SOURCE_LENGTH) + if sourceLen == 0 { + return "" + } + buf := make([]byte, sourceLen) + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetShaderSource, + a0: s.c(), + a1: uintptr(sourceLen), + }, + parg: unsafe.Pointer(&buf[0]), + blocking: true, + }) + return goString(buf) +} + +func (ctx *context) GetString(pname Enum) (r0 string) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetString(%v) %v%v", pname, r0, errstr) + }() + ret := ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetString, + a0: pname.c(), + }, + blocking: true, + }) + retp := unsafe.Pointer(ret) + buf := (*[1 << 24]byte)(retp)[:] + return goString(buf) +} + +func (ctx *context) GetTexParameterfv(dst []float32, target, pname Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetTexParameterfv(len(%d), %v, %v) %v", len(dst), target, pname, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetTexParameterfv, + a0: target.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetTexParameteriv(dst []int32, target, pname Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetTexParameteriv(%v, %v, %v) %v", dst, target, pname, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetTexParameteriv, + a0: target.c(), + a1: pname.c(), + }, + blocking: true, + }) +} + +func (ctx *context) GetUniformfv(dst []float32, src Uniform, p Program) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetUniformfv(len(%d), %v, %v) %v", len(dst), src, p, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetUniformfv, + a0: p.c(), + a1: src.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetUniformiv(dst []int32, src Uniform, p Program) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetUniformiv(%v, %v, %v) %v", dst, src, p, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetUniformiv, + a0: p.c(), + a1: src.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetUniformLocation(p Program, name string) (r0 Uniform) { + defer func() { + errstr := ctx.errDrain() + r0.name = name + log.Printf("gl.GetUniformLocation(%v, %v) %v%v", p, name, r0, errstr) + }() + s, free := ctx.cString(name) + defer free() + return Uniform{Value: int32(ctx.enqueue(call{ + args: fnargs{ + fn: glfnGetUniformLocation, + a0: p.c(), + a1: s, + }, + blocking: true, + }))} +} + +func (ctx *context) GetVertexAttribf(src Attrib, pname Enum) (r0 float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetVertexAttribf(%v, %v) %v%v", src, pname, r0, errstr) + }() + var params [1]float32 + ctx.GetVertexAttribfv(params[:], src, pname) + return params[0] +} + +func (ctx *context) GetVertexAttribfv(dst []float32, src Attrib, pname Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetVertexAttribfv(len(%d), %v, %v) %v", len(dst), src, pname, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetVertexAttribfv, + a0: src.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) GetVertexAttribi(src Attrib, pname Enum) (r0 int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetVertexAttribi(%v, %v) %v%v", src, pname, r0, errstr) + }() + var params [1]int32 + ctx.GetVertexAttribiv(params[:], src, pname) + return params[0] +} + +func (ctx *context) GetVertexAttribiv(dst []int32, src Attrib, pname Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.GetVertexAttribiv(%v, %v, %v) %v", dst, src, pname, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnGetVertexAttribiv, + a0: src.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) Hint(target, mode Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Hint(%v, %v) %v", target, mode, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnHint, + a0: target.c(), + a1: mode.c(), + }, + blocking: true}) +} + +func (ctx *context) IsBuffer(b Buffer) (r0 bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.IsBuffer(%v) %v%v", b, r0, errstr) + }() + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsBuffer, + a0: b.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsEnabled(cap Enum) (r0 bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.IsEnabled(%v) %v%v", cap, r0, errstr) + }() + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsEnabled, + a0: cap.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsFramebuffer(fb Framebuffer) (r0 bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.IsFramebuffer(%v) %v%v", fb, r0, errstr) + }() + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsFramebuffer, + a0: fb.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsProgram(p Program) (r0 bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.IsProgram(%v) %v%v", p, r0, errstr) + }() + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsProgram, + a0: p.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsRenderbuffer(rb Renderbuffer) (r0 bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.IsRenderbuffer(%v) %v%v", rb, r0, errstr) + }() + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsRenderbuffer, + a0: rb.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsShader(s Shader) (r0 bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.IsShader(%v) %v%v", s, r0, errstr) + }() + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsShader, + a0: s.c(), + }, + blocking: true, + }) +} + +func (ctx *context) IsTexture(t Texture) (r0 bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.IsTexture(%v) %v%v", t, r0, errstr) + }() + return 0 != ctx.enqueue(call{ + args: fnargs{ + fn: glfnIsTexture, + a0: t.c(), + }, + blocking: true, + }) +} + +func (ctx *context) LineWidth(width float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.LineWidth(%v) %v", width, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnLineWidth, + a0: uintptr(math.Float32bits(width)), + }, + blocking: true}) +} + +func (ctx *context) LinkProgram(p Program) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.LinkProgram(%v) %v", p, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnLinkProgram, + a0: p.c(), + }, + blocking: true}) +} + +func (ctx *context) PixelStorei(pname Enum, param int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.PixelStorei(%v, %v) %v", pname, param, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnPixelStorei, + a0: pname.c(), + a1: uintptr(param), + }, + blocking: true}) +} + +func (ctx *context) PolygonOffset(factor, units float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.PolygonOffset(%v, %v) %v", factor, units, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnPolygonOffset, + a0: uintptr(math.Float32bits(factor)), + a1: uintptr(math.Float32bits(units)), + }, + blocking: true}) +} + +func (ctx *context) ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ReadPixels(len(%d), %v, %v, %v, %v, %v, %v) %v", len(dst), x, y, width, height, format, ty, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnReadPixels, + + a0: uintptr(x), + a1: uintptr(y), + a2: uintptr(width), + a3: uintptr(height), + a4: format.c(), + a5: ty.c(), + }, + parg: unsafe.Pointer(&dst[0]), + blocking: true, + }) +} + +func (ctx *context) ReleaseShaderCompiler() { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ReleaseShaderCompiler() %v", errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnReleaseShaderCompiler, + }, + blocking: true}) +} + +func (ctx *context) RenderbufferStorage(target, internalFormat Enum, width, height int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.RenderbufferStorage(%v, %v, %v, %v) %v", target, internalFormat, width, height, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnRenderbufferStorage, + a0: target.c(), + a1: internalFormat.c(), + a2: uintptr(width), + a3: uintptr(height), + }, + blocking: true}) +} + +func (ctx *context) SampleCoverage(value float32, invert bool) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.SampleCoverage(%v, %v) %v", value, invert, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnSampleCoverage, + a0: uintptr(math.Float32bits(value)), + a1: glBoolean(invert), + }, + blocking: true}) +} + +func (ctx *context) Scissor(x, y, width, height int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Scissor(%v, %v, %v, %v) %v", x, y, width, height, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnScissor, + a0: uintptr(x), + a1: uintptr(y), + a2: uintptr(width), + a3: uintptr(height), + }, + blocking: true}) +} + +func (ctx *context) ShaderSource(s Shader, src string) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ShaderSource(%v, %v) %v", s, src, errstr) + }() + strp, free := ctx.cStringPtr(src) + defer free() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnShaderSource, + a0: s.c(), + a1: 1, + a2: strp, + }, + blocking: true, + }) +} + +func (ctx *context) StencilFunc(fn Enum, ref int, mask uint32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.StencilFunc(%v, %v, %v) %v", fn, ref, mask, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnStencilFunc, + a0: fn.c(), + a1: uintptr(ref), + a2: uintptr(mask), + }, + blocking: true}) +} + +func (ctx *context) StencilFuncSeparate(face, fn Enum, ref int, mask uint32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.StencilFuncSeparate(%v, %v, %v, %v) %v", face, fn, ref, mask, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnStencilFuncSeparate, + a0: face.c(), + a1: fn.c(), + a2: uintptr(ref), + a3: uintptr(mask), + }, + blocking: true}) +} + +func (ctx *context) StencilMask(mask uint32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.StencilMask(%v) %v", mask, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnStencilMask, + a0: uintptr(mask), + }, + blocking: true}) +} + +func (ctx *context) StencilMaskSeparate(face Enum, mask uint32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.StencilMaskSeparate(%v, %v) %v", face, mask, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnStencilMaskSeparate, + a0: face.c(), + a1: uintptr(mask), + }, + blocking: true}) +} + +func (ctx *context) StencilOp(fail, zfail, zpass Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.StencilOp(%v, %v, %v) %v", fail, zfail, zpass, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnStencilOp, + a0: fail.c(), + a1: zfail.c(), + a2: zpass.c(), + }, + blocking: true}) +} + +func (ctx *context) StencilOpSeparate(face, sfail, dpfail, dppass Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.StencilOpSeparate(%v, %v, %v, %v) %v", face, sfail, dpfail, dppass, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnStencilOpSeparate, + a0: face.c(), + a1: sfail.c(), + a2: dpfail.c(), + a3: dppass.c(), + }, + blocking: true}) +} + +func (ctx *context) TexImage2D(target Enum, level int, internalFormat int, width, height int, format Enum, ty Enum, data []byte) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.TexImage2D(%v, %v, %v, %v, %v, %v, %v, len(%d)) %v", target, level, internalFormat, width, height, format, ty, len(data), errstr) + }() + parg := unsafe.Pointer(nil) + if len(data) > 0 { + parg = unsafe.Pointer(&data[0]) + } + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnTexImage2D, + + a0: target.c(), + a1: uintptr(level), + a2: uintptr(internalFormat), + a3: uintptr(width), + a4: uintptr(height), + a5: format.c(), + a6: ty.c(), + }, + parg: parg, + blocking: true, + }) +} + +func (ctx *context) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.TexSubImage2D(%v, %v, %v, %v, %v, %v, %v, %v, len(%d)) %v", target, level, x, y, width, height, format, ty, len(data), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnTexSubImage2D, + + a0: target.c(), + a1: uintptr(level), + a2: uintptr(x), + a3: uintptr(y), + a4: uintptr(width), + a5: uintptr(height), + a6: format.c(), + a7: ty.c(), + }, + parg: unsafe.Pointer(&data[0]), + blocking: true, + }) +} + +func (ctx *context) TexParameterf(target, pname Enum, param float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.TexParameterf(%v, %v, %v) %v", target, pname, param, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnTexParameterf, + a0: target.c(), + a1: pname.c(), + a2: uintptr(math.Float32bits(param)), + }, + blocking: true}) +} + +func (ctx *context) TexParameterfv(target, pname Enum, params []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.TexParameterfv(%v, %v, len(%d)) %v", target, pname, len(params), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnTexParameterfv, + a0: target.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(¶ms[0]), + blocking: true, + }) +} + +func (ctx *context) TexParameteri(target, pname Enum, param int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.TexParameteri(%v, %v, %v) %v", target, pname, param, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnTexParameteri, + a0: target.c(), + a1: pname.c(), + a2: uintptr(param), + }, + blocking: true}) +} + +func (ctx *context) TexParameteriv(target, pname Enum, params []int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.TexParameteriv(%v, %v, %v) %v", target, pname, params, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnTexParameteriv, + a0: target.c(), + a1: pname.c(), + }, + parg: unsafe.Pointer(¶ms[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform1f(dst Uniform, v float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform1f(%v, %v) %v", dst, v, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform1f, + a0: dst.c(), + a1: uintptr(math.Float32bits(v)), + }, + blocking: true}) +} + +func (ctx *context) Uniform1fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform1fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform1fv, + a0: dst.c(), + a1: uintptr(len(src)), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform1i(dst Uniform, v int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform1i(%v, %v) %v", dst, v, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform1i, + a0: dst.c(), + a1: uintptr(v), + }, + blocking: true}) +} + +func (ctx *context) Uniform1iv(dst Uniform, src []int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform1iv(%v, %v) %v", dst, src, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform1iv, + a0: dst.c(), + a1: uintptr(len(src)), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform2f(dst Uniform, v0, v1 float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform2f(%v, %v, %v) %v", dst, v0, v1, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform2f, + a0: dst.c(), + a1: uintptr(math.Float32bits(v0)), + a2: uintptr(math.Float32bits(v1)), + }, + blocking: true}) +} + +func (ctx *context) Uniform2fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform2fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform2fv, + a0: dst.c(), + a1: uintptr(len(src) / 2), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform2i(dst Uniform, v0, v1 int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform2i(%v, %v, %v) %v", dst, v0, v1, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform2i, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + }, + blocking: true}) +} + +func (ctx *context) Uniform2iv(dst Uniform, src []int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform2iv(%v, %v) %v", dst, src, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform2iv, + a0: dst.c(), + a1: uintptr(len(src) / 2), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform3f(dst Uniform, v0, v1, v2 float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform3f(%v, %v, %v, %v) %v", dst, v0, v1, v2, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform3f, + a0: dst.c(), + a1: uintptr(math.Float32bits(v0)), + a2: uintptr(math.Float32bits(v1)), + a3: uintptr(math.Float32bits(v2)), + }, + blocking: true}) +} + +func (ctx *context) Uniform3fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform3fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform3fv, + a0: dst.c(), + a1: uintptr(len(src) / 3), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform3i(dst Uniform, v0, v1, v2 int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform3i(%v, %v, %v, %v) %v", dst, v0, v1, v2, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform3i, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + a3: uintptr(v2), + }, + blocking: true}) +} + +func (ctx *context) Uniform3iv(dst Uniform, src []int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform3iv(%v, %v) %v", dst, src, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform3iv, + a0: dst.c(), + a1: uintptr(len(src) / 3), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform4f(%v, %v, %v, %v, %v) %v", dst, v0, v1, v2, v3, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform4f, + a0: dst.c(), + a1: uintptr(math.Float32bits(v0)), + a2: uintptr(math.Float32bits(v1)), + a3: uintptr(math.Float32bits(v2)), + a4: uintptr(math.Float32bits(v3)), + }, + blocking: true}) +} + +func (ctx *context) Uniform4fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform4fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform4fv, + a0: dst.c(), + a1: uintptr(len(src) / 4), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) Uniform4i(dst Uniform, v0, v1, v2, v3 int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform4i(%v, %v, %v, %v, %v) %v", dst, v0, v1, v2, v3, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform4i, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + a3: uintptr(v2), + a4: uintptr(v3), + }, + blocking: true}) +} + +func (ctx *context) Uniform4iv(dst Uniform, src []int32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform4iv(%v, %v) %v", dst, src, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform4iv, + a0: dst.c(), + a1: uintptr(len(src) / 4), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) UniformMatrix2fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix2fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix2fv, + + a0: dst.c(), + a1: uintptr(len(src) / 4), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) UniformMatrix3fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix3fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix3fv, + a0: dst.c(), + a1: uintptr(len(src) / 9), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) UniformMatrix4fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix4fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix4fv, + a0: dst.c(), + a1: uintptr(len(src) / 16), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) UseProgram(p Program) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UseProgram(%v) %v", p, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUseProgram, + a0: p.c(), + }, + blocking: true}) +} + +func (ctx *context) ValidateProgram(p Program) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.ValidateProgram(%v) %v", p, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnValidateProgram, + a0: p.c(), + }, + blocking: true}) +} + +func (ctx *context) VertexAttrib1f(dst Attrib, x float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttrib1f(%v, %v) %v", dst, x, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttrib1f, + a0: dst.c(), + a1: uintptr(math.Float32bits(x)), + }, + blocking: true}) +} + +func (ctx *context) VertexAttrib1fv(dst Attrib, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttrib1fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttrib1fv, + a0: dst.c(), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) VertexAttrib2f(dst Attrib, x, y float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttrib2f(%v, %v, %v) %v", dst, x, y, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttrib2f, + a0: dst.c(), + a1: uintptr(math.Float32bits(x)), + a2: uintptr(math.Float32bits(y)), + }, + blocking: true}) +} + +func (ctx *context) VertexAttrib2fv(dst Attrib, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttrib2fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttrib2fv, + a0: dst.c(), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) VertexAttrib3f(dst Attrib, x, y, z float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttrib3f(%v, %v, %v, %v) %v", dst, x, y, z, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttrib3f, + a0: dst.c(), + a1: uintptr(math.Float32bits(x)), + a2: uintptr(math.Float32bits(y)), + a3: uintptr(math.Float32bits(z)), + }, + blocking: true}) +} + +func (ctx *context) VertexAttrib3fv(dst Attrib, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttrib3fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttrib3fv, + a0: dst.c(), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) VertexAttrib4f(dst Attrib, x, y, z, w float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttrib4f(%v, %v, %v, %v, %v) %v", dst, x, y, z, w, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttrib4f, + a0: dst.c(), + a1: uintptr(math.Float32bits(x)), + a2: uintptr(math.Float32bits(y)), + a3: uintptr(math.Float32bits(z)), + a4: uintptr(math.Float32bits(w)), + }, + blocking: true}) +} + +func (ctx *context) VertexAttrib4fv(dst Attrib, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttrib4fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttrib4fv, + a0: dst.c(), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx *context) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.VertexAttribPointer(%v, %v, %v, %v, %v, %v) %v", dst, size, ty, normalized, stride, offset, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnVertexAttribPointer, + a0: dst.c(), + a1: uintptr(size), + a2: ty.c(), + a3: glBoolean(normalized), + a4: uintptr(stride), + a5: uintptr(offset), + }, + blocking: true}) +} + +func (ctx *context) Viewport(x, y, width, height int) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Viewport(%v, %v, %v, %v) %v", x, y, width, height, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnViewport, + a0: uintptr(x), + a1: uintptr(y), + a2: uintptr(width), + a3: uintptr(height), + }, + blocking: true}) +} + +func (ctx context3) UniformMatrix2x3fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix2x3fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix2x3fv, + a0: dst.c(), + a1: uintptr(len(src) / 6), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix3x2fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix3x2fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix3x2fv, + a0: dst.c(), + a1: uintptr(len(src) / 6), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix2x4fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix2x4fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix2x4fv, + a0: dst.c(), + a1: uintptr(len(src) / 8), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix4x2fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix4x2fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix4x2fv, + a0: dst.c(), + a1: uintptr(len(src) / 8), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix3x4fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix3x4fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix3x4fv, + a0: dst.c(), + a1: uintptr(len(src) / 12), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) UniformMatrix4x3fv(dst Uniform, src []float32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.UniformMatrix4x3fv(%v, len(%d)) %v", dst, len(src), errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniformMatrix4x3fv, + a0: dst.c(), + a1: uintptr(len(src) / 12), + }, + parg: unsafe.Pointer(&src[0]), + blocking: true, + }) +} + +func (ctx context3) BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.BlitFramebuffer(%v, %v, %v, %v, %v, %v, %v, %v, %v, %v) %v", srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnBlitFramebuffer, + a0: uintptr(srcX0), + a1: uintptr(srcY0), + a2: uintptr(srcX1), + a3: uintptr(srcY1), + a4: uintptr(dstX0), + a5: uintptr(dstY0), + a6: uintptr(dstX1), + a7: uintptr(dstY1), + a8: uintptr(mask), + a9: filter.c(), + }, + blocking: true}) +} + +func (ctx context3) Uniform1ui(dst Uniform, v uint32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform1ui(%v, %v) %v", dst, v, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform1ui, + a0: dst.c(), + a1: uintptr(v), + }, + blocking: true}) +} + +func (ctx context3) Uniform2ui(dst Uniform, v0, v1 uint32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform2ui(%v, %v, %v) %v", dst, v0, v1, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform2ui, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + }, + blocking: true}) +} + +func (ctx context3) Uniform3ui(dst Uniform, v0, v1, v2 uint) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform3ui(%v, %v, %v, %v) %v", dst, v0, v1, v2, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform3ui, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + a3: uintptr(v2), + }, + blocking: true}) +} + +func (ctx context3) Uniform4ui(dst Uniform, v0, v1, v2, v3 uint32) { + defer func() { + errstr := ctx.errDrain() + log.Printf("gl.Uniform4ui(%v, %v, %v, %v, %v) %v", dst, v0, v1, v2, v3, errstr) + }() + ctx.enqueueDebug(call{ + args: fnargs{ + fn: glfnUniform4ui, + a0: dst.c(), + a1: uintptr(v0), + a2: uintptr(v1), + a3: uintptr(v2), + a4: uintptr(v3), + }, + blocking: true}) +} diff --git a/vendor/golang.org/x/mobile/gl/interface.go b/vendor/golang.org/x/mobile/gl/interface.go new file mode 100644 index 00000000..693abe42 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/interface.go @@ -0,0 +1,889 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gl + +// Context is an OpenGL ES context. +// +// A Context has a method for every GL function supported by ES 2 or later. +// In a program compiled with ES 3 support, a Context is also a Context3. +// For example, a program can: +// +// func f(glctx gl.Context) { +// glctx.(gl.Context3).BlitFramebuffer(...) +// } +// +// Calls are not safe for concurrent use. However calls can be made from +// any goroutine, the gl package removes the notion of thread-local +// context. +// +// Contexts are independent. Two contexts can be used concurrently. +type Context interface { + // ActiveTexture sets the active texture unit. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glActiveTexture.xhtml + ActiveTexture(texture Enum) + + // AttachShader attaches a shader to a program. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glAttachShader.xhtml + AttachShader(p Program, s Shader) + + // BindAttribLocation binds a vertex attribute index with a named + // variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindAttribLocation.xhtml + BindAttribLocation(p Program, a Attrib, name string) + + // BindBuffer binds a buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindBuffer.xhtml + BindBuffer(target Enum, b Buffer) + + // BindFramebuffer binds a framebuffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindFramebuffer.xhtml + BindFramebuffer(target Enum, fb Framebuffer) + + // BindRenderbuffer binds a render buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindRenderbuffer.xhtml + BindRenderbuffer(target Enum, rb Renderbuffer) + + // BindTexture binds a texture. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindTexture.xhtml + BindTexture(target Enum, t Texture) + + // BindVertexArray binds a vertex array. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBindVertexArray.xhtml + BindVertexArray(rb VertexArray) + + // BlendColor sets the blend color. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendColor.xhtml + BlendColor(red, green, blue, alpha float32) + + // BlendEquation sets both RGB and alpha blend equations. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendEquation.xhtml + BlendEquation(mode Enum) + + // BlendEquationSeparate sets RGB and alpha blend equations separately. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendEquationSeparate.xhtml + BlendEquationSeparate(modeRGB, modeAlpha Enum) + + // BlendFunc sets the pixel blending factors. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendFunc.xhtml + BlendFunc(sfactor, dfactor Enum) + + // BlendFuncSeparate sets the pixel RGB and alpha blending factors separately. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBlendFuncSeparate.xhtml + BlendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha Enum) + + // BufferData creates a new data store for the bound buffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml + BufferData(target Enum, src []byte, usage Enum) + + // BufferInit creates a new uninitialized data store for the bound buffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferData.xhtml + BufferInit(target Enum, size int, usage Enum) + + // BufferSubData sets some of data in the bound buffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glBufferSubData.xhtml + BufferSubData(target Enum, offset int, data []byte) + + // CheckFramebufferStatus reports the completeness status of the + // active framebuffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCheckFramebufferStatus.xhtml + CheckFramebufferStatus(target Enum) Enum + + // Clear clears the window. + // + // The behavior of Clear is influenced by the pixel ownership test, + // the scissor test, dithering, and the buffer writemasks. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glClear.xhtml + Clear(mask Enum) + + // ClearColor specifies the RGBA values used to clear color buffers. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearColor.xhtml + ClearColor(red, green, blue, alpha float32) + + // ClearDepthf sets the depth value used to clear the depth buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearDepthf.xhtml + ClearDepthf(d float32) + + // ClearStencil sets the index used to clear the stencil buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glClearStencil.xhtml + ClearStencil(s int) + + // ColorMask specifies whether color components in the framebuffer + // can be written. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glColorMask.xhtml + ColorMask(red, green, blue, alpha bool) + + // CompileShader compiles the source code of s. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompileShader.xhtml + CompileShader(s Shader) + + // CompressedTexImage2D writes a compressed 2D texture. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompressedTexImage2D.xhtml + CompressedTexImage2D(target Enum, level int, internalformat Enum, width, height, border int, data []byte) + + // CompressedTexSubImage2D writes a subregion of a compressed 2D texture. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCompressedTexSubImage2D.xhtml + CompressedTexSubImage2D(target Enum, level, xoffset, yoffset, width, height int, format Enum, data []byte) + + // CopyTexImage2D writes a 2D texture from the current framebuffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCopyTexImage2D.xhtml + CopyTexImage2D(target Enum, level int, internalformat Enum, x, y, width, height, border int) + + // CopyTexSubImage2D writes a 2D texture subregion from the + // current framebuffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCopyTexSubImage2D.xhtml + CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) + + // CreateBuffer creates a buffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenBuffers.xhtml + CreateBuffer() Buffer + + // CreateFramebuffer creates a framebuffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenFramebuffers.xhtml + CreateFramebuffer() Framebuffer + + // CreateProgram creates a new empty program object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCreateProgram.xhtml + CreateProgram() Program + + // CreateRenderbuffer create a renderbuffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenRenderbuffers.xhtml + CreateRenderbuffer() Renderbuffer + + // CreateShader creates a new empty shader object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCreateShader.xhtml + CreateShader(ty Enum) Shader + + // CreateTexture creates a texture object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenTextures.xhtml + CreateTexture() Texture + + // CreateVertexArray creates a vertex array. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenVertexArrays.xhtml + CreateVertexArray() VertexArray + + // CullFace specifies which polygons are candidates for culling. + // + // Valid modes: FRONT, BACK, FRONT_AND_BACK. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glCullFace.xhtml + CullFace(mode Enum) + + // DeleteBuffer deletes the given buffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteBuffers.xhtml + DeleteBuffer(v Buffer) + + // DeleteFramebuffer deletes the given framebuffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteFramebuffers.xhtml + DeleteFramebuffer(v Framebuffer) + + // DeleteProgram deletes the given program object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteProgram.xhtml + DeleteProgram(p Program) + + // DeleteRenderbuffer deletes the given render buffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteRenderbuffers.xhtml + DeleteRenderbuffer(v Renderbuffer) + + // DeleteShader deletes shader s. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteShader.xhtml + DeleteShader(s Shader) + + // DeleteTexture deletes the given texture object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteTextures.xhtml + DeleteTexture(v Texture) + + // DeleteVertexArray deletes the given render buffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDeleteVertexArrays.xhtml + DeleteVertexArray(v VertexArray) + + // DepthFunc sets the function used for depth buffer comparisons. + // + // Valid fn values: + // NEVER + // LESS + // EQUAL + // LEQUAL + // GREATER + // NOTEQUAL + // GEQUAL + // ALWAYS + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthFunc.xhtml + DepthFunc(fn Enum) + + // DepthMask sets the depth buffer enabled for writing. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthMask.xhtml + DepthMask(flag bool) + + // DepthRangef sets the mapping from normalized device coordinates to + // window coordinates. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDepthRangef.xhtml + DepthRangef(n, f float32) + + // DetachShader detaches the shader s from the program p. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDetachShader.xhtml + DetachShader(p Program, s Shader) + + // Disable disables various GL capabilities. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDisable.xhtml + Disable(cap Enum) + + // DisableVertexAttribArray disables a vertex attribute array. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDisableVertexAttribArray.xhtml + DisableVertexAttribArray(a Attrib) + + // DrawArrays renders geometric primitives from the bound data. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDrawArrays.xhtml + DrawArrays(mode Enum, first, count int) + + // DrawElements renders primitives from a bound buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glDrawElements.xhtml + DrawElements(mode Enum, count int, ty Enum, offset int) + + // TODO(crawshaw): consider DrawElements8 / DrawElements16 / DrawElements32 + + // Enable enables various GL capabilities. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glEnable.xhtml + Enable(cap Enum) + + // EnableVertexAttribArray enables a vertex attribute array. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glEnableVertexAttribArray.xhtml + EnableVertexAttribArray(a Attrib) + + // Finish blocks until the effects of all previously called GL + // commands are complete. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glFinish.xhtml + Finish() + + // Flush empties all buffers. It does not block. + // + // An OpenGL implementation may buffer network communication, + // the command stream, or data inside the graphics accelerator. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glFlush.xhtml + Flush() + + // FramebufferRenderbuffer attaches rb to the current frame buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glFramebufferRenderbuffer.xhtml + FramebufferRenderbuffer(target, attachment, rbTarget Enum, rb Renderbuffer) + + // FramebufferTexture2D attaches the t to the current frame buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glFramebufferTexture2D.xhtml + FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) + + // FrontFace defines which polygons are front-facing. + // + // Valid modes: CW, CCW. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glFrontFace.xhtml + FrontFace(mode Enum) + + // GenerateMipmap generates mipmaps for the current texture. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGenerateMipmap.xhtml + GenerateMipmap(target Enum) + + // GetActiveAttrib returns details about an active attribute variable. + // A value of 0 for index selects the first active attribute variable. + // Permissible values for index range from 0 to the number of active + // attribute variables minus 1. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveAttrib.xhtml + GetActiveAttrib(p Program, index uint32) (name string, size int, ty Enum) + + // GetActiveUniform returns details about an active uniform variable. + // A value of 0 for index selects the first active uniform variable. + // Permissible values for index range from 0 to the number of active + // uniform variables minus 1. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetActiveUniform.xhtml + GetActiveUniform(p Program, index uint32) (name string, size int, ty Enum) + + // GetAttachedShaders returns the shader objects attached to program p. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetAttachedShaders.xhtml + GetAttachedShaders(p Program) []Shader + + // GetAttribLocation returns the location of an attribute variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetAttribLocation.xhtml + GetAttribLocation(p Program, name string) Attrib + + // GetBooleanv returns the boolean values of parameter pname. + // + // Many boolean parameters can be queried more easily using IsEnabled. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml + GetBooleanv(dst []bool, pname Enum) + + // GetFloatv returns the float values of parameter pname. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml + GetFloatv(dst []float32, pname Enum) + + // GetIntegerv returns the int values of parameter pname. + // + // Single values may be queried more easily using GetInteger. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml + GetIntegerv(dst []int32, pname Enum) + + // GetInteger returns the int value of parameter pname. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGet.xhtml + GetInteger(pname Enum) int + + // GetBufferParameteri returns a parameter for the active buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetBufferParameter.xhtml + GetBufferParameteri(target, value Enum) int + + // GetError returns the next error. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetError.xhtml + GetError() Enum + + // GetFramebufferAttachmentParameteri returns attachment parameters + // for the active framebuffer object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetFramebufferAttachmentParameteriv.xhtml + GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int + + // GetProgrami returns a parameter value for a program. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetProgramiv.xhtml + GetProgrami(p Program, pname Enum) int + + // GetProgramInfoLog returns the information log for a program. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetProgramInfoLog.xhtml + GetProgramInfoLog(p Program) string + + // GetRenderbufferParameteri returns a parameter value for a render buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetRenderbufferParameteriv.xhtml + GetRenderbufferParameteri(target, pname Enum) int + + // GetShaderi returns a parameter value for a shader. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderiv.xhtml + GetShaderi(s Shader, pname Enum) int + + // GetShaderInfoLog returns the information log for a shader. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderInfoLog.xhtml + GetShaderInfoLog(s Shader) string + + // GetShaderPrecisionFormat returns range and precision limits for + // shader types. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderPrecisionFormat.xhtml + GetShaderPrecisionFormat(shadertype, precisiontype Enum) (rangeLow, rangeHigh, precision int) + + // GetShaderSource returns source code of shader s. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetShaderSource.xhtml + GetShaderSource(s Shader) string + + // GetString reports current GL state. + // + // Valid name values: + // EXTENSIONS + // RENDERER + // SHADING_LANGUAGE_VERSION + // VENDOR + // VERSION + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetString.xhtml + GetString(pname Enum) string + + // GetTexParameterfv returns the float values of a texture parameter. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetTexParameter.xhtml + GetTexParameterfv(dst []float32, target, pname Enum) + + // GetTexParameteriv returns the int values of a texture parameter. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetTexParameter.xhtml + GetTexParameteriv(dst []int32, target, pname Enum) + + // GetUniformfv returns the float values of a uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniform.xhtml + GetUniformfv(dst []float32, src Uniform, p Program) + + // GetUniformiv returns the float values of a uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniform.xhtml + GetUniformiv(dst []int32, src Uniform, p Program) + + // GetUniformLocation returns the location of a uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetUniformLocation.xhtml + GetUniformLocation(p Program, name string) Uniform + + // GetVertexAttribf reads the float value of a vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml + GetVertexAttribf(src Attrib, pname Enum) float32 + + // GetVertexAttribfv reads float values of a vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml + GetVertexAttribfv(dst []float32, src Attrib, pname Enum) + + // GetVertexAttribi reads the int value of a vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml + GetVertexAttribi(src Attrib, pname Enum) int32 + + // GetVertexAttribiv reads int values of a vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glGetVertexAttrib.xhtml + GetVertexAttribiv(dst []int32, src Attrib, pname Enum) + + // TODO(crawshaw): glGetVertexAttribPointerv + + // Hint sets implementation-specific modes. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glHint.xhtml + Hint(target, mode Enum) + + // IsBuffer reports if b is a valid buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsBuffer.xhtml + IsBuffer(b Buffer) bool + + // IsEnabled reports if cap is an enabled capability. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsEnabled.xhtml + IsEnabled(cap Enum) bool + + // IsFramebuffer reports if fb is a valid frame buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsFramebuffer.xhtml + IsFramebuffer(fb Framebuffer) bool + + // IsProgram reports if p is a valid program object. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsProgram.xhtml + IsProgram(p Program) bool + + // IsRenderbuffer reports if rb is a valid render buffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsRenderbuffer.xhtml + IsRenderbuffer(rb Renderbuffer) bool + + // IsShader reports if s is valid shader. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsShader.xhtml + IsShader(s Shader) bool + + // IsTexture reports if t is a valid texture. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glIsTexture.xhtml + IsTexture(t Texture) bool + + // LineWidth specifies the width of lines. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glLineWidth.xhtml + LineWidth(width float32) + + // LinkProgram links the specified program. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glLinkProgram.xhtml + LinkProgram(p Program) + + // PixelStorei sets pixel storage parameters. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glPixelStorei.xhtml + PixelStorei(pname Enum, param int32) + + // PolygonOffset sets the scaling factors for depth offsets. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glPolygonOffset.xhtml + PolygonOffset(factor, units float32) + + // ReadPixels returns pixel data from a buffer. + // + // In GLES 3, the source buffer is controlled with ReadBuffer. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glReadPixels.xhtml + ReadPixels(dst []byte, x, y, width, height int, format, ty Enum) + + // ReleaseShaderCompiler frees resources allocated by the shader compiler. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glReleaseShaderCompiler.xhtml + ReleaseShaderCompiler() + + // RenderbufferStorage establishes the data storage, format, and + // dimensions of a renderbuffer object's image. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glRenderbufferStorage.xhtml + RenderbufferStorage(target, internalFormat Enum, width, height int) + + // SampleCoverage sets multisample coverage parameters. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glSampleCoverage.xhtml + SampleCoverage(value float32, invert bool) + + // Scissor defines the scissor box rectangle, in window coordinates. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glScissor.xhtml + Scissor(x, y, width, height int32) + + // TODO(crawshaw): ShaderBinary + + // ShaderSource sets the source code of s to the given source code. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glShaderSource.xhtml + ShaderSource(s Shader, src string) + + // StencilFunc sets the front and back stencil test reference value. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilFunc.xhtml + StencilFunc(fn Enum, ref int, mask uint32) + + // StencilFuncSeparate sets the front or back stencil test reference value. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilFuncSeparate.xhtml + StencilFuncSeparate(face, fn Enum, ref int, mask uint32) + + // StencilMask controls the writing of bits in the stencil planes. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilMask.xhtml + StencilMask(mask uint32) + + // StencilMaskSeparate controls the writing of bits in the stencil planes. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilMaskSeparate.xhtml + StencilMaskSeparate(face Enum, mask uint32) + + // StencilOp sets front and back stencil test actions. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilOp.xhtml + StencilOp(fail, zfail, zpass Enum) + + // StencilOpSeparate sets front or back stencil tests. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glStencilOpSeparate.xhtml + StencilOpSeparate(face, sfail, dpfail, dppass Enum) + + // TexImage2D writes a 2D texture image. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexImage2D.xhtml + TexImage2D(target Enum, level int, internalFormat int, width, height int, format Enum, ty Enum, data []byte) + + // TexSubImage2D writes a subregion of a 2D texture image. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexSubImage2D.xhtml + TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) + + // TexParameterf sets a float texture parameter. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml + TexParameterf(target, pname Enum, param float32) + + // TexParameterfv sets a float texture parameter array. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml + TexParameterfv(target, pname Enum, params []float32) + + // TexParameteri sets an integer texture parameter. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml + TexParameteri(target, pname Enum, param int) + + // TexParameteriv sets an integer texture parameter array. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glTexParameter.xhtml + TexParameteriv(target, pname Enum, params []int32) + + // Uniform1f writes a float uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform1f(dst Uniform, v float32) + + // Uniform1fv writes a [len(src)]float uniform array. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform1fv(dst Uniform, src []float32) + + // Uniform1i writes an int uniform variable. + // + // Uniform1i and Uniform1iv are the only two functions that may be used + // to load uniform variables defined as sampler types. Loading samplers + // with any other function will result in a INVALID_OPERATION error. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform1i(dst Uniform, v int) + + // Uniform1iv writes a int uniform array of len(src) elements. + // + // Uniform1i and Uniform1iv are the only two functions that may be used + // to load uniform variables defined as sampler types. Loading samplers + // with any other function will result in a INVALID_OPERATION error. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform1iv(dst Uniform, src []int32) + + // Uniform2f writes a vec2 uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform2f(dst Uniform, v0, v1 float32) + + // Uniform2fv writes a vec2 uniform array of len(src)/2 elements. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform2fv(dst Uniform, src []float32) + + // Uniform2i writes an ivec2 uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform2i(dst Uniform, v0, v1 int) + + // Uniform2iv writes an ivec2 uniform array of len(src)/2 elements. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform2iv(dst Uniform, src []int32) + + // Uniform3f writes a vec3 uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform3f(dst Uniform, v0, v1, v2 float32) + + // Uniform3fv writes a vec3 uniform array of len(src)/3 elements. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform3fv(dst Uniform, src []float32) + + // Uniform3i writes an ivec3 uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform3i(dst Uniform, v0, v1, v2 int32) + + // Uniform3iv writes an ivec3 uniform array of len(src)/3 elements. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform3iv(dst Uniform, src []int32) + + // Uniform4f writes a vec4 uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform4f(dst Uniform, v0, v1, v2, v3 float32) + + // Uniform4fv writes a vec4 uniform array of len(src)/4 elements. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform4fv(dst Uniform, src []float32) + + // Uniform4i writes an ivec4 uniform variable. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform4i(dst Uniform, v0, v1, v2, v3 int32) + + // Uniform4iv writes an ivec4 uniform array of len(src)/4 elements. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + Uniform4iv(dst Uniform, src []int32) + + // UniformMatrix2fv writes 2x2 matrices. Each matrix uses four + // float32 values, so the number of matrices written is len(src)/4. + // + // Each matrix must be supplied in column major order. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + UniformMatrix2fv(dst Uniform, src []float32) + + // UniformMatrix3fv writes 3x3 matrices. Each matrix uses nine + // float32 values, so the number of matrices written is len(src)/9. + // + // Each matrix must be supplied in column major order. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + UniformMatrix3fv(dst Uniform, src []float32) + + // UniformMatrix4fv writes 4x4 matrices. Each matrix uses 16 + // float32 values, so the number of matrices written is len(src)/16. + // + // Each matrix must be supplied in column major order. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUniform.xhtml + UniformMatrix4fv(dst Uniform, src []float32) + + // UseProgram sets the active program. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glUseProgram.xhtml + UseProgram(p Program) + + // ValidateProgram checks to see whether the executables contained in + // program can execute given the current OpenGL state. + // + // Typically only used for debugging. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glValidateProgram.xhtml + ValidateProgram(p Program) + + // VertexAttrib1f writes a float vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml + VertexAttrib1f(dst Attrib, x float32) + + // VertexAttrib1fv writes a float vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml + VertexAttrib1fv(dst Attrib, src []float32) + + // VertexAttrib2f writes a vec2 vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml + VertexAttrib2f(dst Attrib, x, y float32) + + // VertexAttrib2fv writes a vec2 vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml + VertexAttrib2fv(dst Attrib, src []float32) + + // VertexAttrib3f writes a vec3 vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml + VertexAttrib3f(dst Attrib, x, y, z float32) + + // VertexAttrib3fv writes a vec3 vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml + VertexAttrib3fv(dst Attrib, src []float32) + + // VertexAttrib4f writes a vec4 vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml + VertexAttrib4f(dst Attrib, x, y, z, w float32) + + // VertexAttrib4fv writes a vec4 vertex attribute. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttrib.xhtml + VertexAttrib4fv(dst Attrib, src []float32) + + // VertexAttribPointer uses a bound buffer to define vertex attribute data. + // + // Direct use of VertexAttribPointer to load data into OpenGL is not + // supported via the Go bindings. Instead, use BindBuffer with an + // ARRAY_BUFFER and then fill it using BufferData. + // + // The size argument specifies the number of components per attribute, + // between 1-4. The stride argument specifies the byte offset between + // consecutive vertex attributes. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glVertexAttribPointer.xhtml + VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) + + // Viewport sets the viewport, an affine transformation that + // normalizes device coordinates to window coordinates. + // + // http://www.khronos.org/opengles/sdk/docs/man3/html/glViewport.xhtml + Viewport(x, y, width, height int) +} + +// Context3 is an OpenGL ES 3 context. +// +// When the gl package is compiled with GL ES 3 support, the produced +// Context object also implements the Context3 interface. +type Context3 interface { + Context + + // BlitFramebuffer copies a block of pixels between framebuffers. + // + // https://www.khronos.org/opengles/sdk/docs/man3/html/glBlitFramebuffer.xhtml + BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1 int, mask uint, filter Enum) +} + +// Worker is used by display driver code to execute OpenGL calls. +// +// Typically display driver code creates a gl.Context for an application, +// and along with it establishes a locked OS thread to execute the cgo +// calls: +// +// go func() { +// runtime.LockOSThread() +// // ... platform-specific cgo call to bind a C OpenGL context +// // into thread-local storage. +// +// glctx, worker := gl.NewContext() +// workAvailable := worker.WorkAvailable() +// go userAppCode(glctx) +// for { +// select { +// case <-workAvailable: +// worker.DoWork() +// case <-drawEvent: +// // ... platform-specific cgo call to draw screen +// } +// } +// }() +// +// This interface is an internal implementation detail and should only be used +// by the package responsible for managing the screen, such as +// golang.org/x/mobile/app. +type Worker interface { + // WorkAvailable returns a channel that communicates when DoWork should be + // called. + WorkAvailable() <-chan struct{} + + // DoWork performs any pending OpenGL calls. + DoWork() +} diff --git a/vendor/golang.org/x/mobile/gl/types_debug.go b/vendor/golang.org/x/mobile/gl/types_debug.go new file mode 100644 index 00000000..e9e9bd7c --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/types_debug.go @@ -0,0 +1,81 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin || linux || openbsd || windows) && gldebug + +package gl + +// Alternate versions of the types defined in types.go with extra +// debugging information attached. For documentation, see types.go. + +import "fmt" + +type Enum uint32 + +type Attrib struct { + Value uint + name string +} + +type Program struct { + Init bool + Value uint32 +} + +type Shader struct { + Value uint32 +} + +type Buffer struct { + Value uint32 +} + +type Framebuffer struct { + Value uint32 +} + +type Renderbuffer struct { + Value uint32 +} + +type Texture struct { + Value uint32 +} + +type Uniform struct { + Value int32 + name string +} + +type VertexArray struct { + Value uint32 +} + +func (v Attrib) c() uintptr { return uintptr(v.Value) } +func (v Enum) c() uintptr { return uintptr(v) } +func (v Program) c() uintptr { + if !v.Init { + ret := uintptr(0) + ret-- + return ret + } + return uintptr(v.Value) +} +func (v Shader) c() uintptr { return uintptr(v.Value) } +func (v Buffer) c() uintptr { return uintptr(v.Value) } +func (v Framebuffer) c() uintptr { return uintptr(v.Value) } +func (v Renderbuffer) c() uintptr { return uintptr(v.Value) } +func (v Texture) c() uintptr { return uintptr(v.Value) } +func (v Uniform) c() uintptr { return uintptr(v.Value) } +func (v VertexArray) c() uintptr { return uintptr(v.Value) } + +func (v Attrib) String() string { return fmt.Sprintf("Attrib(%d:%s)", v.Value, v.name) } +func (v Program) String() string { return fmt.Sprintf("Program(%d)", v.Value) } +func (v Shader) String() string { return fmt.Sprintf("Shader(%d)", v.Value) } +func (v Buffer) String() string { return fmt.Sprintf("Buffer(%d)", v.Value) } +func (v Framebuffer) String() string { return fmt.Sprintf("Framebuffer(%d)", v.Value) } +func (v Renderbuffer) String() string { return fmt.Sprintf("Renderbuffer(%d)", v.Value) } +func (v Texture) String() string { return fmt.Sprintf("Texture(%d)", v.Value) } +func (v Uniform) String() string { return fmt.Sprintf("Uniform(%d:%s)", v.Value, v.name) } +func (v VertexArray) String() string { return fmt.Sprintf("VertexArray(%d)", v.Value) } diff --git a/vendor/golang.org/x/mobile/gl/types_prod.go b/vendor/golang.org/x/mobile/gl/types_prod.go new file mode 100644 index 00000000..6817c6f0 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/types_prod.go @@ -0,0 +1,92 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (darwin || linux || openbsd || windows) && !gldebug + +package gl + +import "fmt" + +// Enum is equivalent to GLenum, and is normally used with one of the +// constants defined in this package. +type Enum uint32 + +// Types are defined a structs so that in debug mode they can carry +// extra information, such as a string name. See typesdebug.go. + +// Attrib identifies the location of a specific attribute variable. +type Attrib struct { + Value uint +} + +// Program identifies a compiled shader program. +type Program struct { + // Init is set by CreateProgram, as some GL drivers (in particular, + // ANGLE) return true for glIsProgram(0). + Init bool + Value uint32 +} + +// Shader identifies a GLSL shader. +type Shader struct { + Value uint32 +} + +// Buffer identifies a GL buffer object. +type Buffer struct { + Value uint32 +} + +// Framebuffer identifies a GL framebuffer. +type Framebuffer struct { + Value uint32 +} + +// A Renderbuffer is a GL object that holds an image in an internal format. +type Renderbuffer struct { + Value uint32 +} + +// A Texture identifies a GL texture unit. +type Texture struct { + Value uint32 +} + +// Uniform identifies the location of a specific uniform variable. +type Uniform struct { + Value int32 +} + +// A VertexArray is a GL object that holds vertices in an internal format. +type VertexArray struct { + Value uint32 +} + +func (v Attrib) c() uintptr { return uintptr(v.Value) } +func (v Enum) c() uintptr { return uintptr(v) } +func (v Program) c() uintptr { + if !v.Init { + ret := uintptr(0) + ret-- + return ret + } + return uintptr(v.Value) +} +func (v Shader) c() uintptr { return uintptr(v.Value) } +func (v Buffer) c() uintptr { return uintptr(v.Value) } +func (v Framebuffer) c() uintptr { return uintptr(v.Value) } +func (v Renderbuffer) c() uintptr { return uintptr(v.Value) } +func (v Texture) c() uintptr { return uintptr(v.Value) } +func (v Uniform) c() uintptr { return uintptr(v.Value) } +func (v VertexArray) c() uintptr { return uintptr(v.Value) } + +func (v Attrib) String() string { return fmt.Sprintf("Attrib(%d)", v.Value) } +func (v Program) String() string { return fmt.Sprintf("Program(%d)", v.Value) } +func (v Shader) String() string { return fmt.Sprintf("Shader(%d)", v.Value) } +func (v Buffer) String() string { return fmt.Sprintf("Buffer(%d)", v.Value) } +func (v Framebuffer) String() string { return fmt.Sprintf("Framebuffer(%d)", v.Value) } +func (v Renderbuffer) String() string { return fmt.Sprintf("Renderbuffer(%d)", v.Value) } +func (v Texture) String() string { return fmt.Sprintf("Texture(%d)", v.Value) } +func (v Uniform) String() string { return fmt.Sprintf("Uniform(%d)", v.Value) } +func (v VertexArray) String() string { return fmt.Sprintf("VertexArray(%d)", v.Value) } diff --git a/vendor/golang.org/x/mobile/gl/work.c b/vendor/golang.org/x/mobile/gl/work.c new file mode 100644 index 00000000..605e0ba9 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/work.c @@ -0,0 +1,557 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || linux || openbsd +// +build darwin linux openbsd + +#include +#include "_cgo_export.h" +#include "work.h" + +#if defined(GL_ES_VERSION_3_0) && GL_ES_VERSION_3_0 +#else +#include +static void gles3missing() { + printf("GLES3 function is missing\n"); + exit(2); +} +static void glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } +static void glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } +static void glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } +static void glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } +static void glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } +static void glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { gles3missing(); } +static void glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { gles3missing(); } +static void glUniform1ui(GLint location, GLuint v0) { gles3missing(); } +static void glUniform2ui(GLint location, GLuint v0, GLuint v1) { gles3missing(); } +static void glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) { gles3missing(); } +static void glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) { gles3missing(); } +static void glUniform1uiv(GLint location, GLsizei count, const GLuint *value) { gles3missing(); } +static void glUniform2uiv(GLint location, GLsizei count, const GLuint *value) { gles3missing(); } +static void glUniform3uiv(GLint location, GLsizei count, const GLuint *value) { gles3missing(); } +static void glUniform4uiv(GLint location, GLsizei count, const GLuint *value) { gles3missing(); } +static void glBindVertexArray(GLuint array) { gles3missing(); } +static void glGenVertexArrays(GLsizei n, GLuint *arrays) { gles3missing(); } +static void glDeleteVertexArrays(GLsizei n, const GLuint *arrays) { gles3missing(); } +#endif + +uintptr_t processFn(struct fnargs* args, char* parg) { + uintptr_t ret = 0; + switch (args->fn) { + case glfnUNDEFINED: + abort(); // bad glfn + break; + case glfnActiveTexture: + glActiveTexture((GLenum)args->a0); + break; + case glfnAttachShader: + glAttachShader((GLint)args->a0, (GLint)args->a1); + break; + case glfnBindAttribLocation: + glBindAttribLocation((GLint)args->a0, (GLint)args->a1, (GLchar*)args->a2); + break; + case glfnBindBuffer: + glBindBuffer((GLenum)args->a0, (GLuint)args->a1); + break; + case glfnBindFramebuffer: + glBindFramebuffer((GLenum)args->a0, (GLint)args->a1); + break; + case glfnBindRenderbuffer: + glBindRenderbuffer((GLenum)args->a0, (GLint)args->a1); + break; + case glfnBindTexture: + glBindTexture((GLenum)args->a0, (GLint)args->a1); + break; + case glfnBindVertexArray: + glBindVertexArray((GLenum)args->a0); + break; + case glfnBlendColor: + glBlendColor(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); + break; + case glfnBlendEquation: + glBlendEquation((GLenum)args->a0); + break; + case glfnBlendEquationSeparate: + glBlendEquationSeparate((GLenum)args->a0, (GLenum)args->a1); + break; + case glfnBlendFunc: + glBlendFunc((GLenum)args->a0, (GLenum)args->a1); + break; + case glfnBlendFuncSeparate: + glBlendFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3); + break; + case glfnBlitFramebuffer: + glBlitFramebuffer((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7, (GLbitfield)args->a8, (GLenum)args->a9); + break; + case glfnBufferData: + glBufferData((GLenum)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg, (GLenum)args->a2); + break; + case glfnBufferSubData: + glBufferSubData((GLenum)args->a0, (GLint)args->a1, (GLsizeiptr)args->a2, (GLvoid*)parg); + break; + case glfnCheckFramebufferStatus: + ret = glCheckFramebufferStatus((GLenum)args->a0); + break; + case glfnClear: + glClear((GLenum)args->a0); + break; + case glfnClearColor: + glClearColor(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); + break; + case glfnClearDepthf: + glClearDepthf(*(GLfloat*)&args->a0); + break; + case glfnClearStencil: + glClearStencil((GLint)args->a0); + break; + case glfnColorMask: + glColorMask((GLboolean)args->a0, (GLboolean)args->a1, (GLboolean)args->a2, (GLboolean)args->a3); + break; + case glfnCompileShader: + glCompileShader((GLint)args->a0); + break; + case glfnCompressedTexImage2D: + glCompressedTexImage2D((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLsizeiptr)args->a6, (GLvoid*)parg); + break; + case glfnCompressedTexSubImage2D: + glCompressedTexSubImage2D((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLenum)args->a6, (GLsizeiptr)args->a7, (GLvoid*)parg); + break; + case glfnCopyTexImage2D: + glCopyTexImage2D((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7); + break; + case glfnCopyTexSubImage2D: + glCopyTexSubImage2D((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4, (GLint)args->a5, (GLint)args->a6, (GLint)args->a7); + break; + case glfnCreateProgram: + ret = glCreateProgram(); + break; + case glfnCreateShader: + ret = glCreateShader((GLenum)args->a0); + break; + case glfnCullFace: + glCullFace((GLenum)args->a0); + break; + case glfnDeleteBuffer: + glDeleteBuffers(1, (const GLuint*)(&args->a0)); + break; + case glfnDeleteFramebuffer: + glDeleteFramebuffers(1, (const GLuint*)(&args->a0)); + break; + case glfnDeleteProgram: + glDeleteProgram((GLint)args->a0); + break; + case glfnDeleteRenderbuffer: + glDeleteRenderbuffers(1, (const GLuint*)(&args->a0)); + break; + case glfnDeleteShader: + glDeleteShader((GLint)args->a0); + break; + case glfnDeleteTexture: + glDeleteTextures(1, (const GLuint*)(&args->a0)); + break; + case glfnDeleteVertexArray: + glDeleteVertexArrays(1, (const GLuint*)(&args->a0)); + break; + case glfnDepthFunc: + glDepthFunc((GLenum)args->a0); + break; + case glfnDepthMask: + glDepthMask((GLboolean)args->a0); + break; + case glfnDepthRangef: + glDepthRangef(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1); + break; + case glfnDetachShader: + glDetachShader((GLint)args->a0, (GLint)args->a1); + break; + case glfnDisable: + glDisable((GLenum)args->a0); + break; + case glfnDisableVertexAttribArray: + glDisableVertexAttribArray((GLint)args->a0); + break; + case glfnDrawArrays: + glDrawArrays((GLenum)args->a0, (GLint)args->a1, (GLint)args->a2); + break; + case glfnDrawElements: + glDrawElements((GLenum)args->a0, (GLint)args->a1, (GLenum)args->a2, (void*)args->a3); + break; + case glfnEnable: + glEnable((GLenum)args->a0); + break; + case glfnEnableVertexAttribArray: + glEnableVertexAttribArray((GLint)args->a0); + break; + case glfnFinish: + glFinish(); + break; + case glfnFlush: + glFlush(); + break; + case glfnFramebufferRenderbuffer: + glFramebufferRenderbuffer((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint)args->a3); + break; + case glfnFramebufferTexture2D: + glFramebufferTexture2D((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint)args->a3, (GLint)args->a4); + break; + case glfnFrontFace: + glFrontFace((GLenum)args->a0); + break; + case glfnGenBuffer: + glGenBuffers(1, (GLuint*)&ret); + break; + case glfnGenFramebuffer: + glGenFramebuffers(1, (GLuint*)&ret); + break; + case glfnGenRenderbuffer: + glGenRenderbuffers(1, (GLuint*)&ret); + break; + case glfnGenTexture: + glGenTextures(1, (GLuint*)&ret); + break; + case glfnGenVertexArray: + glGenVertexArrays(1, (GLuint*)&ret); + break; + case glfnGenerateMipmap: + glGenerateMipmap((GLenum)args->a0); + break; + case glfnGetActiveAttrib: + glGetActiveAttrib( + (GLuint)args->a0, + (GLuint)args->a1, + (GLsizei)args->a2, + NULL, + (GLint*)&ret, + (GLenum*)args->a3, + (GLchar*)parg); + break; + case glfnGetActiveUniform: + glGetActiveUniform( + (GLuint)args->a0, + (GLuint)args->a1, + (GLsizei)args->a2, + NULL, + (GLint*)&ret, + (GLenum*)args->a3, + (GLchar*)parg); + break; + case glfnGetAttachedShaders: + glGetAttachedShaders((GLuint)args->a0, (GLsizei)args->a1, (GLsizei*)&ret, (GLuint*)parg); + break; + case glfnGetAttribLocation: + ret = glGetAttribLocation((GLint)args->a0, (GLchar*)args->a1); + break; + case glfnGetBooleanv: + glGetBooleanv((GLenum)args->a0, (GLboolean*)parg); + break; + case glfnGetBufferParameteri: + glGetBufferParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)&ret); + break; + case glfnGetFloatv: + glGetFloatv((GLenum)args->a0, (GLfloat*)parg); + break; + case glfnGetIntegerv: + glGetIntegerv((GLenum)args->a0, (GLint*)parg); + break; + case glfnGetError: + ret = glGetError(); + break; + case glfnGetFramebufferAttachmentParameteriv: + glGetFramebufferAttachmentParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLint*)&ret); + break; + case glfnGetProgramiv: + glGetProgramiv((GLint)args->a0, (GLenum)args->a1, (GLint*)&ret); + break; + case glfnGetProgramInfoLog: + glGetProgramInfoLog((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); + break; + case glfnGetRenderbufferParameteriv: + glGetRenderbufferParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)&ret); + break; + case glfnGetShaderiv: + glGetShaderiv((GLint)args->a0, (GLenum)args->a1, (GLint*)&ret); + break; + case glfnGetShaderInfoLog: + glGetShaderInfoLog((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); + break; + case glfnGetShaderPrecisionFormat: + glGetShaderPrecisionFormat((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg, &((GLint*)parg)[2]); + break; + case glfnGetShaderSource: + glGetShaderSource((GLuint)args->a0, (GLsizei)args->a1, 0, (GLchar*)parg); + break; + case glfnGetString: + ret = (uintptr_t)glGetString((GLenum)args->a0); + break; + case glfnGetTexParameterfv: + glGetTexParameterfv((GLenum)args->a0, (GLenum)args->a1, (GLfloat*)parg); + break; + case glfnGetTexParameteriv: + glGetTexParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg); + break; + case glfnGetUniformfv: + glGetUniformfv((GLuint)args->a0, (GLint)args->a1, (GLfloat*)parg); + break; + case glfnGetUniformiv: + glGetUniformiv((GLuint)args->a0, (GLint)args->a1, (GLint*)parg); + break; + case glfnGetUniformLocation: + ret = glGetUniformLocation((GLint)args->a0, (GLchar*)args->a1); + break; + case glfnGetVertexAttribfv: + glGetVertexAttribfv((GLuint)args->a0, (GLenum)args->a1, (GLfloat*)parg); + break; + case glfnGetVertexAttribiv: + glGetVertexAttribiv((GLuint)args->a0, (GLenum)args->a1, (GLint*)parg); + break; + case glfnHint: + glHint((GLenum)args->a0, (GLenum)args->a1); + break; + case glfnIsBuffer: + ret = glIsBuffer((GLint)args->a0); + break; + case glfnIsEnabled: + ret = glIsEnabled((GLenum)args->a0); + break; + case glfnIsFramebuffer: + ret = glIsFramebuffer((GLint)args->a0); + break; + case glfnIsProgram: + ret = glIsProgram((GLint)args->a0); + break; + case glfnIsRenderbuffer: + ret = glIsRenderbuffer((GLint)args->a0); + break; + case glfnIsShader: + ret = glIsShader((GLint)args->a0); + break; + case glfnIsTexture: + ret = glIsTexture((GLint)args->a0); + break; + case glfnLineWidth: + glLineWidth(*(GLfloat*)&args->a0); + break; + case glfnLinkProgram: + glLinkProgram((GLint)args->a0); + break; + case glfnPixelStorei: + glPixelStorei((GLenum)args->a0, (GLint)args->a1); + break; + case glfnPolygonOffset: + glPolygonOffset(*(GLfloat*)&args->a0, *(GLfloat*)&args->a1); + break; + case glfnReadPixels: + glReadPixels((GLint)args->a0, (GLint)args->a1, (GLsizei)args->a2, (GLsizei)args->a3, (GLenum)args->a4, (GLenum)args->a5, (void*)parg); + break; + case glfnReleaseShaderCompiler: + glReleaseShaderCompiler(); + break; + case glfnRenderbufferStorage: + glRenderbufferStorage((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2, (GLint)args->a3); + break; + case glfnSampleCoverage: + glSampleCoverage(*(GLfloat*)&args->a0, (GLboolean)args->a1); + break; + case glfnScissor: + glScissor((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); + break; + case glfnShaderSource: +#if defined(os_ios) || defined(os_macos) + glShaderSource((GLuint)args->a0, (GLsizei)args->a1, (const GLchar *const *)args->a2, NULL); +#else + glShaderSource((GLuint)args->a0, (GLsizei)args->a1, (const GLchar **)args->a2, NULL); +#endif + break; + case glfnStencilFunc: + glStencilFunc((GLenum)args->a0, (GLint)args->a1, (GLuint)args->a2); + break; + case glfnStencilFuncSeparate: + glStencilFuncSeparate((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2, (GLuint)args->a3); + break; + case glfnStencilMask: + glStencilMask((GLuint)args->a0); + break; + case glfnStencilMaskSeparate: + glStencilMaskSeparate((GLenum)args->a0, (GLuint)args->a1); + break; + case glfnStencilOp: + glStencilOp((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2); + break; + case glfnStencilOpSeparate: + glStencilOpSeparate((GLenum)args->a0, (GLenum)args->a1, (GLenum)args->a2, (GLenum)args->a3); + break; + case glfnTexImage2D: + glTexImage2D( + (GLenum)args->a0, + (GLint)args->a1, + (GLint)args->a2, + (GLsizei)args->a3, + (GLsizei)args->a4, + 0, // border + (GLenum)args->a5, + (GLenum)args->a6, + (const GLvoid*)parg); + break; + case glfnTexSubImage2D: + glTexSubImage2D( + (GLenum)args->a0, + (GLint)args->a1, + (GLint)args->a2, + (GLint)args->a3, + (GLsizei)args->a4, + (GLsizei)args->a5, + (GLenum)args->a6, + (GLenum)args->a7, + (const GLvoid*)parg); + break; + case glfnTexParameterf: + glTexParameterf((GLenum)args->a0, (GLenum)args->a1, *(GLfloat*)&args->a2); + break; + case glfnTexParameterfv: + glTexParameterfv((GLenum)args->a0, (GLenum)args->a1, (GLfloat*)parg); + break; + case glfnTexParameteri: + glTexParameteri((GLenum)args->a0, (GLenum)args->a1, (GLint)args->a2); + break; + case glfnTexParameteriv: + glTexParameteriv((GLenum)args->a0, (GLenum)args->a1, (GLint*)parg); + break; + case glfnUniform1f: + glUniform1f((GLint)args->a0, *(GLfloat*)&args->a1); + break; + case glfnUniform1fv: + glUniform1fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); + break; + case glfnUniform1i: + glUniform1i((GLint)args->a0, (GLint)args->a1); + break; + case glfnUniform1ui: + glUniform1ui((GLint)args->a0, (GLuint)args->a1); + break; + case glfnUniform1uiv: + glUniform1uiv((GLint)args->a0, (GLsizeiptr)args->a1, (GLuint*)parg); + break; + case glfnUniform1iv: + glUniform1iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); + break; + case glfnUniform2f: + glUniform2f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2); + break; + case glfnUniform2fv: + glUniform2fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); + break; + case glfnUniform2i: + glUniform2i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2); + break; + case glfnUniform2ui: + glUniform2ui((GLint)args->a0, (GLuint)args->a1, (GLuint)args->a2); + break; + case glfnUniform2uiv: + glUniform2uiv((GLint)args->a0, (GLsizeiptr)args->a1, (GLuint*)parg); + break; + case glfnUniform2iv: + glUniform2iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); + break; + case glfnUniform3f: + glUniform3f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); + break; + case glfnUniform3fv: + glUniform3fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); + break; + case glfnUniform3i: + glUniform3i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); + break; + case glfnUniform3ui: + glUniform3ui((GLint)args->a0, (GLuint)args->a1, (GLuint)args->a2, (GLuint)args->a3); + break; + case glfnUniform3uiv: + glUniform3uiv((GLint)args->a0, (GLsizeiptr)args->a1, (GLuint*)parg); + break; + case glfnUniform3iv: + glUniform3iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); + break; + case glfnUniform4f: + glUniform4f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3, *(GLfloat*)&args->a4); + break; + case glfnUniform4fv: + glUniform4fv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); + break; + case glfnUniform4i: + glUniform4i((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3, (GLint)args->a4); + break; + case glfnUniform4ui: + glUniform4ui((GLint)args->a0, (GLuint)args->a1, (GLuint)args->a2, (GLuint)args->a3, (GLuint)args->a4); + break; + case glfnUniform4uiv: + glUniform4uiv((GLint)args->a0, (GLsizeiptr)args->a1, (GLuint*)parg); + break; + case glfnUniform4iv: + glUniform4iv((GLint)args->a0, (GLsizeiptr)args->a1, (GLvoid*)parg); + break; + case glfnUniformMatrix2fv: + glUniformMatrix2fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUniformMatrix3fv: + glUniformMatrix3fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUniformMatrix4fv: + glUniformMatrix4fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUniformMatrix2x3fv: + glUniformMatrix2x3fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUniformMatrix3x2fv: + glUniformMatrix3x2fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUniformMatrix2x4fv: + glUniformMatrix2x4fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUniformMatrix4x2fv: + glUniformMatrix4x2fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUniformMatrix3x4fv: + glUniformMatrix3x4fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUniformMatrix4x3fv: + glUniformMatrix4x3fv((GLint)args->a0, (GLsizeiptr)args->a1, 0, (GLvoid*)parg); + break; + case glfnUseProgram: + glUseProgram((GLint)args->a0); + break; + case glfnValidateProgram: + glValidateProgram((GLint)args->a0); + break; + case glfnVertexAttrib1f: + glVertexAttrib1f((GLint)args->a0, *(GLfloat*)&args->a1); + break; + case glfnVertexAttrib1fv: + glVertexAttrib1fv((GLint)args->a0, (GLfloat*)parg); + break; + case glfnVertexAttrib2f: + glVertexAttrib2f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2); + break; + case glfnVertexAttrib2fv: + glVertexAttrib2fv((GLint)args->a0, (GLfloat*)parg); + break; + case glfnVertexAttrib3f: + glVertexAttrib3f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3); + break; + case glfnVertexAttrib3fv: + glVertexAttrib3fv((GLint)args->a0, (GLfloat*)parg); + break; + case glfnVertexAttrib4f: + glVertexAttrib4f((GLint)args->a0, *(GLfloat*)&args->a1, *(GLfloat*)&args->a2, *(GLfloat*)&args->a3, *(GLfloat*)&args->a4); + break; + case glfnVertexAttrib4fv: + glVertexAttrib4fv((GLint)args->a0, (GLfloat*)parg); + break; + case glfnVertexAttribPointer: + glVertexAttribPointer((GLuint)args->a0, (GLint)args->a1, (GLenum)args->a2, (GLboolean)args->a3, (GLsizei)args->a4, (const GLvoid*)args->a5); + break; + case glfnViewport: + glViewport((GLint)args->a0, (GLint)args->a1, (GLint)args->a2, (GLint)args->a3); + break; + } + return ret; +} diff --git a/vendor/golang.org/x/mobile/gl/work.go b/vendor/golang.org/x/mobile/gl/work.go new file mode 100644 index 00000000..a778b0c5 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/work.go @@ -0,0 +1,173 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || linux || openbsd + +package gl + +/* +#cgo ios LDFLAGS: -framework OpenGLES +#cgo darwin,!ios LDFLAGS: -framework OpenGL +#cgo linux LDFLAGS: -lGLESv2 +#cgo openbsd LDFLAGS: -L/usr/X11R6/lib/ -lGLESv2 + +#cgo android CFLAGS: -Dos_android +#cgo ios CFLAGS: -Dos_ios +#cgo darwin,!ios CFLAGS: -Dos_macos +#cgo darwin CFLAGS: -DGL_SILENCE_DEPRECATION -DGLES_SILENCE_DEPRECATION +#cgo linux CFLAGS: -Dos_linux +#cgo openbsd CFLAGS: -Dos_openbsd + +#cgo openbsd CFLAGS: -I/usr/X11R6/include/ + +#include +#include "work.h" + +uintptr_t process(struct fnargs* cargs, char* parg0, char* parg1, char* parg2, int count) { + uintptr_t ret; + + ret = processFn(&cargs[0], parg0); + if (count > 1) { + ret = processFn(&cargs[1], parg1); + } + if (count > 2) { + ret = processFn(&cargs[2], parg2); + } + + return ret; +} +*/ +import "C" + +import "unsafe" + +const workbufLen = 3 + +type context struct { + cptr uintptr + debug int32 + + workAvailable chan struct{} + + // work is a queue of calls to execute. + work chan call + + // retvalue is sent a return value when blocking calls complete. + // It is safe to use a global unbuffered channel here as calls + // cannot currently be made concurrently. + // + // TODO: the comment above about concurrent calls isn't actually true: package + // app calls package gl, but it has to do so in a separate goroutine, which + // means that its gl calls (which may be blocking) can race with other gl calls + // in the main program. We should make it safe to issue blocking gl calls + // concurrently, or get the gl calls out of package app, or both. + retvalue chan C.uintptr_t + + cargs [workbufLen]C.struct_fnargs + parg [workbufLen]*C.char +} + +func (ctx *context) WorkAvailable() <-chan struct{} { return ctx.workAvailable } + +type context3 struct { + *context +} + +// NewContext creates a cgo OpenGL context. +// +// See the Worker interface for more details on how it is used. +func NewContext() (Context, Worker) { + glctx := &context{ + workAvailable: make(chan struct{}, 1), + work: make(chan call, workbufLen), + retvalue: make(chan C.uintptr_t), + } + if C.GLES_VERSION == "GL_ES_2_0" { + return glctx, glctx + } + return context3{glctx}, glctx +} + +// Version returns a GL ES version string, either "GL_ES_2_0" or "GL_ES_3_0". +// Future versions of the gl package may return "GL_ES_3_1". +func Version() string { + return C.GLES_VERSION +} + +func (ctx *context) enqueue(c call) uintptr { + ctx.work <- c + + select { + case ctx.workAvailable <- struct{}{}: + default: + } + + if c.blocking { + return uintptr(<-ctx.retvalue) + } + return 0 +} + +func (ctx *context) DoWork() { + queue := make([]call, 0, workbufLen) + for { + // Wait until at least one piece of work is ready. + // Accumulate work until a piece is marked as blocking. + select { + case w := <-ctx.work: + queue = append(queue, w) + default: + return + } + blocking := queue[len(queue)-1].blocking + enqueue: + for len(queue) < cap(queue) && !blocking { + select { + case w := <-ctx.work: + queue = append(queue, w) + blocking = queue[len(queue)-1].blocking + default: + break enqueue + } + } + + // Process the queued GL functions. + for i, q := range queue { + ctx.cargs[i] = *(*C.struct_fnargs)(unsafe.Pointer(&q.args)) + ctx.parg[i] = (*C.char)(q.parg) + } + ret := C.process(&ctx.cargs[0], ctx.parg[0], ctx.parg[1], ctx.parg[2], C.int(len(queue))) + + // Cleanup and signal. + queue = queue[:0] + if blocking { + ctx.retvalue <- ret + } + } +} + +func init() { + if unsafe.Sizeof(C.GLint(0)) != unsafe.Sizeof(int32(0)) { + panic("GLint is not an int32") + } +} + +// cString creates C string off the Go heap. +// ret is a *char. +func (ctx *context) cString(str string) (uintptr, func()) { + ptr := unsafe.Pointer(C.CString(str)) + return uintptr(ptr), func() { C.free(ptr) } +} + +// cStringPtr creates a pointer to a C string off the Go heap. +// ret is a **char. +func (ctx *context) cStringPtr(str string) (uintptr, func()) { + s, free := ctx.cString(str) + ptr := C.malloc(C.size_t(unsafe.Sizeof((*int)(nil)))) + *(*uintptr)(ptr) = s + return uintptr(ptr), func() { + free() + C.free(ptr) + } +} diff --git a/vendor/golang.org/x/mobile/gl/work.h b/vendor/golang.org/x/mobile/gl/work.h new file mode 100644 index 00000000..5bc093b3 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/work.h @@ -0,0 +1,217 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#ifdef os_android +// TODO(crawshaw): We could include and +// condition on __ANDROID_API__ to get GLES3 headers. However +// we also need to add -lGLESv3 to LDFLAGS, which we cannot do +// from inside an ifdef. +#include +#elif os_linux +#include // install on Ubuntu with: sudo apt-get install libegl1-mesa-dev libgles2-mesa-dev libx11-dev +#elif os_openbsd +#include +#endif + +#ifdef os_ios +#include +#endif + +#ifdef os_macos +#include +#define GL_ES_VERSION_3_0 1 +#endif + +#if defined(GL_ES_VERSION_3_0) && GL_ES_VERSION_3_0 +#define GLES_VERSION "GL_ES_3_0" +#else +#define GLES_VERSION "GL_ES_2_0" +#endif + +#include +#include + +// TODO: generate this enum from fn.go. +typedef enum { + glfnUNDEFINED, + + glfnActiveTexture, + glfnAttachShader, + glfnBindAttribLocation, + glfnBindBuffer, + glfnBindFramebuffer, + glfnBindRenderbuffer, + glfnBindTexture, + glfnBindVertexArray, + glfnBlendColor, + glfnBlendEquation, + glfnBlendEquationSeparate, + glfnBlendFunc, + glfnBlendFuncSeparate, + glfnBufferData, + glfnBufferSubData, + glfnCheckFramebufferStatus, + glfnClear, + glfnClearColor, + glfnClearDepthf, + glfnClearStencil, + glfnColorMask, + glfnCompileShader, + glfnCompressedTexImage2D, + glfnCompressedTexSubImage2D, + glfnCopyTexImage2D, + glfnCopyTexSubImage2D, + glfnCreateProgram, + glfnCreateShader, + glfnCullFace, + glfnDeleteBuffer, + glfnDeleteFramebuffer, + glfnDeleteProgram, + glfnDeleteRenderbuffer, + glfnDeleteShader, + glfnDeleteTexture, + glfnDeleteVertexArray, + glfnDepthFunc, + glfnDepthRangef, + glfnDepthMask, + glfnDetachShader, + glfnDisable, + glfnDisableVertexAttribArray, + glfnDrawArrays, + glfnDrawElements, + glfnEnable, + glfnEnableVertexAttribArray, + glfnFinish, + glfnFlush, + glfnFramebufferRenderbuffer, + glfnFramebufferTexture2D, + glfnFrontFace, + glfnGenBuffer, + glfnGenFramebuffer, + glfnGenRenderbuffer, + glfnGenTexture, + glfnGenVertexArray, + glfnGenerateMipmap, + glfnGetActiveAttrib, + glfnGetActiveUniform, + glfnGetAttachedShaders, + glfnGetAttribLocation, + glfnGetBooleanv, + glfnGetBufferParameteri, + glfnGetError, + glfnGetFloatv, + glfnGetFramebufferAttachmentParameteriv, + glfnGetIntegerv, + glfnGetProgramInfoLog, + glfnGetProgramiv, + glfnGetRenderbufferParameteriv, + glfnGetShaderInfoLog, + glfnGetShaderPrecisionFormat, + glfnGetShaderSource, + glfnGetShaderiv, + glfnGetString, + glfnGetTexParameterfv, + glfnGetTexParameteriv, + glfnGetUniformLocation, + glfnGetUniformfv, + glfnGetUniformiv, + glfnGetVertexAttribfv, + glfnGetVertexAttribiv, + glfnHint, + glfnIsBuffer, + glfnIsEnabled, + glfnIsFramebuffer, + glfnIsProgram, + glfnIsRenderbuffer, + glfnIsShader, + glfnIsTexture, + glfnLineWidth, + glfnLinkProgram, + glfnPixelStorei, + glfnPolygonOffset, + glfnReadPixels, + glfnReleaseShaderCompiler, + glfnRenderbufferStorage, + glfnSampleCoverage, + glfnScissor, + glfnShaderSource, + glfnStencilFunc, + glfnStencilFuncSeparate, + glfnStencilMask, + glfnStencilMaskSeparate, + glfnStencilOp, + glfnStencilOpSeparate, + glfnTexImage2D, + glfnTexParameterf, + glfnTexParameterfv, + glfnTexParameteri, + glfnTexParameteriv, + glfnTexSubImage2D, + glfnUniform1f, + glfnUniform1fv, + glfnUniform1i, + glfnUniform1iv, + glfnUniform2f, + glfnUniform2fv, + glfnUniform2i, + glfnUniform2iv, + glfnUniform3f, + glfnUniform3fv, + glfnUniform3i, + glfnUniform3iv, + glfnUniform4f, + glfnUniform4fv, + glfnUniform4i, + glfnUniform4iv, + glfnUniformMatrix2fv, + glfnUniformMatrix3fv, + glfnUniformMatrix4fv, + glfnUseProgram, + glfnValidateProgram, + glfnVertexAttrib1f, + glfnVertexAttrib1fv, + glfnVertexAttrib2f, + glfnVertexAttrib2fv, + glfnVertexAttrib3f, + glfnVertexAttrib3fv, + glfnVertexAttrib4f, + glfnVertexAttrib4fv, + glfnVertexAttribPointer, + glfnViewport, + + // ES 3.0 functions + glfnUniformMatrix2x3fv, + glfnUniformMatrix3x2fv, + glfnUniformMatrix2x4fv, + glfnUniformMatrix4x2fv, + glfnUniformMatrix3x4fv, + glfnUniformMatrix4x3fv, + glfnBlitFramebuffer, + glfnUniform1ui, + glfnUniform2ui, + glfnUniform3ui, + glfnUniform4ui, + glfnUniform1uiv, + glfnUniform2uiv, + glfnUniform3uiv, + glfnUniform4uiv, +} glfn; + +// TODO: generate this type from fn.go. +struct fnargs { + glfn fn; + + uintptr_t a0; + uintptr_t a1; + uintptr_t a2; + uintptr_t a3; + uintptr_t a4; + uintptr_t a5; + uintptr_t a6; + uintptr_t a7; + uintptr_t a8; + uintptr_t a9; +}; + +extern uintptr_t processFn(struct fnargs* args, char* parg); diff --git a/vendor/golang.org/x/mobile/gl/work_other.go b/vendor/golang.org/x/mobile/gl/work_other.go new file mode 100644 index 00000000..3bc597d4 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/work_other.go @@ -0,0 +1,35 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build (!cgo || (!darwin && !linux && !openbsd)) && !windows + +package gl + +// This file contains stub implementations of what the other work*.go files +// provide. These stubs don't do anything, other than compile (e.g. when cgo is +// disabled). + +type context struct{} + +func (*context) enqueue(c call) uintptr { + panic("unimplemented; GOOS/CGO combination not supported") +} + +func (*context) cString(str string) (uintptr, func()) { + panic("unimplemented; GOOS/CGO combination not supported") +} + +func (*context) cStringPtr(str string) (uintptr, func()) { + panic("unimplemented; GOOS/CGO combination not supported") +} + +type context3 = context + +func NewContext() (Context, Worker) { + panic("unimplemented; GOOS/CGO combination not supported") +} + +func Version() string { + panic("unimplemented; GOOS/CGO combination not supported") +} diff --git a/vendor/golang.org/x/mobile/gl/work_windows.go b/vendor/golang.org/x/mobile/gl/work_windows.go new file mode 100644 index 00000000..4119ac61 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/work_windows.go @@ -0,0 +1,569 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package gl + +import ( + "runtime" + "syscall" + "unsafe" +) + +// context is described in work.go. +type context struct { + debug int32 + workAvailable chan struct{} + work chan call + retvalue chan uintptr + + // TODO(crawshaw): will not work with a moving collector + cStringCounter int + cStrings map[int]unsafe.Pointer +} + +func (ctx *context) WorkAvailable() <-chan struct{} { return ctx.workAvailable } + +type context3 struct { + *context +} + +func NewContext() (Context, Worker) { + if err := findDLLs(); err != nil { + panic(err) + } + glctx := &context{ + workAvailable: make(chan struct{}, 1), + work: make(chan call, 3), + retvalue: make(chan uintptr), + cStrings: make(map[int]unsafe.Pointer), + } + return glctx, glctx +} + +func (ctx *context) enqueue(c call) uintptr { + ctx.work <- c + + select { + case ctx.workAvailable <- struct{}{}: + default: + } + + if c.blocking { + return <-ctx.retvalue + } + return 0 +} + +func (ctx *context) DoWork() { + // TODO: add a work queue + for { + select { + case w := <-ctx.work: + ret := ctx.doWork(w) + if w.blocking { + ctx.retvalue <- ret + } + default: + return + } + } +} + +func (ctx *context) cString(s string) (uintptr, func()) { + buf := make([]byte, len(s)+1) + for i := 0; i < len(s); i++ { + buf[i] = s[i] + } + ret := unsafe.Pointer(&buf[0]) + id := ctx.cStringCounter + ctx.cStringCounter++ + ctx.cStrings[id] = ret + return uintptr(ret), func() { delete(ctx.cStrings, id) } +} + +func (ctx *context) cStringPtr(str string) (uintptr, func()) { + s, sfree := ctx.cString(str) + sptr := [2]uintptr{s, 0} + ret := unsafe.Pointer(&sptr[0]) + id := ctx.cStringCounter + ctx.cStringCounter++ + ctx.cStrings[id] = ret + return uintptr(ret), func() { sfree(); delete(ctx.cStrings, id) } +} + +// fixFloat copies the first four arguments into the XMM registers. +// This is for the windows/amd64 calling convention, that wants +// floating point arguments to be passed in XMM. +// +// Mercifully, type information is not required to implement +// this calling convention. In particular see the mixed int/float +// examples: +// +// https://msdn.microsoft.com/en-us/library/zthk2dkh.aspx +// +// This means it could be fixed in syscall.Syscall. The relevant +// issue is +// +// https://golang.org/issue/6510 +func fixFloat(x0, x1, x2, x3 uintptr) + +func (ctx *context) doWork(c call) (ret uintptr) { + if runtime.GOARCH == "amd64" { + fixFloat(c.args.a0, c.args.a1, c.args.a2, c.args.a3) + } + + switch c.args.fn { + case glfnActiveTexture: + syscall.Syscall(glActiveTexture.Addr(), 1, c.args.a0, 0, 0) + case glfnAttachShader: + syscall.Syscall(glAttachShader.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnBindAttribLocation: + syscall.Syscall(glBindAttribLocation.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) + case glfnBindBuffer: + syscall.Syscall(glBindBuffer.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnBindFramebuffer: + syscall.Syscall(glBindFramebuffer.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnBindRenderbuffer: + syscall.Syscall(glBindRenderbuffer.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnBindTexture: + syscall.Syscall(glBindTexture.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnBindVertexArray: + syscall.Syscall(glBindVertexArray.Addr(), 1, c.args.a0, 0, 0) + case glfnBlendColor: + syscall.Syscall6(glBlendColor.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnBlendEquation: + syscall.Syscall(glBlendEquation.Addr(), 1, c.args.a0, 0, 0) + case glfnBlendEquationSeparate: + syscall.Syscall(glBlendEquationSeparate.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnBlendFunc: + syscall.Syscall(glBlendFunc.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnBlendFuncSeparate: + syscall.Syscall6(glBlendFuncSeparate.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnBufferData: + syscall.Syscall6(glBufferData.Addr(), 4, c.args.a0, c.args.a1, uintptr(c.parg), c.args.a2, 0, 0) + case glfnBufferSubData: + syscall.Syscall6(glBufferSubData.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, uintptr(c.parg), 0, 0) + case glfnCheckFramebufferStatus: + ret, _, _ = syscall.Syscall(glCheckFramebufferStatus.Addr(), 1, c.args.a0, 0, 0) + case glfnClear: + syscall.Syscall(glClear.Addr(), 1, c.args.a0, 0, 0) + case glfnClearColor: + syscall.Syscall6(glClearColor.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnClearDepthf: + syscall.Syscall6(glClearDepthf.Addr(), 1, c.args.a0, 0, 0, 0, 0, 0) + case glfnClearStencil: + syscall.Syscall(glClearStencil.Addr(), 1, c.args.a0, 0, 0) + case glfnColorMask: + syscall.Syscall6(glColorMask.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnCompileShader: + syscall.Syscall(glCompileShader.Addr(), 1, c.args.a0, 0, 0) + case glfnCompressedTexImage2D: + syscall.Syscall9(glCompressedTexImage2D.Addr(), 8, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, uintptr(c.parg), 0) + case glfnCompressedTexSubImage2D: + syscall.Syscall9(glCompressedTexSubImage2D.Addr(), 9, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, c.args.a7, uintptr(c.parg)) + case glfnCopyTexImage2D: + syscall.Syscall9(glCopyTexImage2D.Addr(), 8, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, c.args.a7, 0) + case glfnCopyTexSubImage2D: + syscall.Syscall9(glCopyTexSubImage2D.Addr(), 8, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, c.args.a7, 0) + case glfnCreateProgram: + ret, _, _ = syscall.Syscall(glCreateProgram.Addr(), 0, 0, 0, 0) + case glfnCreateShader: + ret, _, _ = syscall.Syscall(glCreateShader.Addr(), 1, c.args.a0, 0, 0) + case glfnCullFace: + syscall.Syscall(glCullFace.Addr(), 1, c.args.a0, 0, 0) + case glfnDeleteBuffer: + syscall.Syscall(glDeleteBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) + case glfnDeleteFramebuffer: + syscall.Syscall(glDeleteFramebuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) + case glfnDeleteProgram: + syscall.Syscall(glDeleteProgram.Addr(), 1, c.args.a0, 0, 0) + case glfnDeleteRenderbuffer: + syscall.Syscall(glDeleteRenderbuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) + case glfnDeleteShader: + syscall.Syscall(glDeleteShader.Addr(), 1, c.args.a0, 0, 0) + case glfnDeleteVertexArray: + syscall.Syscall(glDeleteVertexArrays.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) + case glfnDeleteTexture: + syscall.Syscall(glDeleteTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&c.args.a0)), 0) + case glfnDepthFunc: + syscall.Syscall(glDepthFunc.Addr(), 1, c.args.a0, 0, 0) + case glfnDepthRangef: + syscall.Syscall6(glDepthRangef.Addr(), 2, c.args.a0, c.args.a1, 0, 0, 0, 0) + case glfnDepthMask: + syscall.Syscall(glDepthMask.Addr(), 1, c.args.a0, 0, 0) + case glfnDetachShader: + syscall.Syscall(glDetachShader.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnDisable: + syscall.Syscall(glDisable.Addr(), 1, c.args.a0, 0, 0) + case glfnDisableVertexAttribArray: + syscall.Syscall(glDisableVertexAttribArray.Addr(), 1, c.args.a0, 0, 0) + case glfnDrawArrays: + syscall.Syscall(glDrawArrays.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) + case glfnDrawElements: + syscall.Syscall6(glDrawElements.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnEnable: + syscall.Syscall(glEnable.Addr(), 1, c.args.a0, 0, 0) + case glfnEnableVertexAttribArray: + syscall.Syscall(glEnableVertexAttribArray.Addr(), 1, c.args.a0, 0, 0) + case glfnFinish: + syscall.Syscall(glFinish.Addr(), 0, 0, 0, 0) + case glfnFlush: + syscall.Syscall(glFlush.Addr(), 0, 0, 0, 0) + case glfnFramebufferRenderbuffer: + syscall.Syscall6(glFramebufferRenderbuffer.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnFramebufferTexture2D: + syscall.Syscall6(glFramebufferTexture2D.Addr(), 5, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, 0) + case glfnFrontFace: + syscall.Syscall(glFrontFace.Addr(), 1, c.args.a0, 0, 0) + case glfnGenBuffer: + syscall.Syscall(glGenBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) + case glfnGenFramebuffer: + syscall.Syscall(glGenFramebuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) + case glfnGenRenderbuffer: + syscall.Syscall(glGenRenderbuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) + case glfnGenVertexArray: + syscall.Syscall(glGenVertexArrays.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) + case glfnGenTexture: + syscall.Syscall(glGenTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&ret)), 0) + case glfnGenerateMipmap: + syscall.Syscall(glGenerateMipmap.Addr(), 1, c.args.a0, 0, 0) + case glfnGetActiveAttrib: + syscall.Syscall9(glGetActiveAttrib.Addr(), 7, c.args.a0, c.args.a1, c.args.a2, 0, uintptr(unsafe.Pointer(&ret)), c.args.a3, uintptr(c.parg), 0, 0) + case glfnGetActiveUniform: + syscall.Syscall9(glGetActiveUniform.Addr(), 7, c.args.a0, c.args.a1, c.args.a2, 0, uintptr(unsafe.Pointer(&ret)), c.args.a3, uintptr(c.parg), 0, 0) + case glfnGetAttachedShaders: + syscall.Syscall6(glGetAttachedShaders.Addr(), 4, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret)), uintptr(c.parg), 0, 0) + case glfnGetAttribLocation: + ret, _, _ = syscall.Syscall(glGetAttribLocation.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnGetBooleanv: + syscall.Syscall(glGetBooleanv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) + case glfnGetBufferParameteri: + syscall.Syscall(glGetBufferParameteri.Addr(), 3, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret))) + case glfnGetError: + ret, _, _ = syscall.Syscall(glGetError.Addr(), 0, 0, 0, 0) + case glfnGetFloatv: + syscall.Syscall(glGetFloatv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) + case glfnGetFramebufferAttachmentParameteriv: + syscall.Syscall6(glGetFramebufferAttachmentParameteriv.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, uintptr(unsafe.Pointer(&ret)), 0, 0) + case glfnGetIntegerv: + syscall.Syscall(glGetIntegerv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) + case glfnGetProgramInfoLog: + syscall.Syscall6(glGetProgramInfoLog.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) + case glfnGetProgramiv: + syscall.Syscall(glGetProgramiv.Addr(), 3, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret))) + case glfnGetRenderbufferParameteriv: + syscall.Syscall(glGetRenderbufferParameteriv.Addr(), 3, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret))) + case glfnGetShaderInfoLog: + syscall.Syscall6(glGetShaderInfoLog.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) + case glfnGetShaderPrecisionFormat: + // c.parg is a [3]int32. The first [2]int32 of the array is one + // parameter, the final *int32 is another parameter. + syscall.Syscall6(glGetShaderPrecisionFormat.Addr(), 4, c.args.a0, c.args.a1, uintptr(c.parg), uintptr(c.parg)+2*unsafe.Sizeof(uintptr(0)), 0, 0) + case glfnGetShaderSource: + syscall.Syscall6(glGetShaderSource.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) + case glfnGetShaderiv: + syscall.Syscall(glGetShaderiv.Addr(), 3, c.args.a0, c.args.a1, uintptr(unsafe.Pointer(&ret))) + case glfnGetString: + ret, _, _ = syscall.Syscall(glGetString.Addr(), 1, c.args.a0, 0, 0) + case glfnGetTexParameterfv: + syscall.Syscall(glGetTexParameterfv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnGetTexParameteriv: + syscall.Syscall(glGetTexParameteriv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnGetUniformLocation: + ret, _, _ = syscall.Syscall(glGetUniformLocation.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnGetUniformfv: + syscall.Syscall(glGetUniformfv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnGetUniformiv: + syscall.Syscall(glGetUniformiv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnGetVertexAttribfv: + syscall.Syscall(glGetVertexAttribfv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnGetVertexAttribiv: + syscall.Syscall(glGetVertexAttribiv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnHint: + syscall.Syscall(glHint.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnIsBuffer: + syscall.Syscall(glIsBuffer.Addr(), 1, c.args.a0, 0, 0) + case glfnIsEnabled: + syscall.Syscall(glIsEnabled.Addr(), 1, c.args.a0, 0, 0) + case glfnIsFramebuffer: + syscall.Syscall(glIsFramebuffer.Addr(), 1, c.args.a0, 0, 0) + case glfnIsProgram: + ret, _, _ = syscall.Syscall(glIsProgram.Addr(), 1, c.args.a0, 0, 0) + case glfnIsRenderbuffer: + syscall.Syscall(glIsRenderbuffer.Addr(), 1, c.args.a0, 0, 0) + case glfnIsShader: + syscall.Syscall(glIsShader.Addr(), 1, c.args.a0, 0, 0) + case glfnIsTexture: + syscall.Syscall(glIsTexture.Addr(), 1, c.args.a0, 0, 0) + case glfnLineWidth: + syscall.Syscall(glLineWidth.Addr(), 1, c.args.a0, 0, 0) + case glfnLinkProgram: + syscall.Syscall(glLinkProgram.Addr(), 1, c.args.a0, 0, 0) + case glfnPixelStorei: + syscall.Syscall(glPixelStorei.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnPolygonOffset: + syscall.Syscall6(glPolygonOffset.Addr(), 2, c.args.a0, c.args.a1, 0, 0, 0, 0) + case glfnReadPixels: + syscall.Syscall9(glReadPixels.Addr(), 7, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, uintptr(c.parg), 0, 0) + case glfnReleaseShaderCompiler: + syscall.Syscall(glReleaseShaderCompiler.Addr(), 0, 0, 0, 0) + case glfnRenderbufferStorage: + syscall.Syscall6(glRenderbufferStorage.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnSampleCoverage: + syscall.Syscall6(glSampleCoverage.Addr(), 1, c.args.a0, 0, 0, 0, 0, 0) + case glfnScissor: + syscall.Syscall6(glScissor.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnShaderSource: + syscall.Syscall6(glShaderSource.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, 0, 0, 0) + case glfnStencilFunc: + syscall.Syscall(glStencilFunc.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) + case glfnStencilFuncSeparate: + syscall.Syscall6(glStencilFuncSeparate.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnStencilMask: + syscall.Syscall(glStencilMask.Addr(), 1, c.args.a0, 0, 0) + case glfnStencilMaskSeparate: + syscall.Syscall(glStencilMaskSeparate.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnStencilOp: + syscall.Syscall(glStencilOp.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) + case glfnStencilOpSeparate: + syscall.Syscall6(glStencilOpSeparate.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnTexImage2D: + syscall.Syscall9(glTexImage2D.Addr(), 9, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, 0, c.args.a5, c.args.a6, uintptr(c.parg)) + case glfnTexParameterf: + syscall.Syscall6(glTexParameterf.Addr(), 3, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnTexParameterfv: + syscall.Syscall(glTexParameterfv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnTexParameteri: + syscall.Syscall(glTexParameteri.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) + case glfnTexParameteriv: + syscall.Syscall(glTexParameteriv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnTexSubImage2D: + syscall.Syscall9(glTexSubImage2D.Addr(), 9, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5, c.args.a6, c.args.a7, uintptr(c.parg)) + case glfnUniform1f: + syscall.Syscall6(glUniform1f.Addr(), 2, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnUniform1fv: + syscall.Syscall(glUniform1fv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnUniform1i: + syscall.Syscall(glUniform1i.Addr(), 2, c.args.a0, c.args.a1, 0) + case glfnUniform1iv: + syscall.Syscall(glUniform1iv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnUniform2f: + syscall.Syscall6(glUniform2f.Addr(), 3, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnUniform2fv: + syscall.Syscall(glUniform2fv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnUniform2i: + syscall.Syscall(glUniform2i.Addr(), 3, c.args.a0, c.args.a1, c.args.a2) + case glfnUniform2iv: + syscall.Syscall(glUniform2iv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnUniform3f: + syscall.Syscall6(glUniform3f.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnUniform3fv: + syscall.Syscall(glUniform3fv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnUniform3i: + syscall.Syscall6(glUniform3i.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + case glfnUniform3iv: + syscall.Syscall(glUniform3iv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnUniform4f: + syscall.Syscall6(glUniform4f.Addr(), 5, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnUniform4fv: + syscall.Syscall(glUniform4fv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnUniform4i: + syscall.Syscall6(glUniform4i.Addr(), 5, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, 0) + case glfnUniform4iv: + syscall.Syscall(glUniform4iv.Addr(), 3, c.args.a0, c.args.a1, uintptr(c.parg)) + case glfnUniformMatrix2fv: + syscall.Syscall6(glUniformMatrix2fv.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) + case glfnUniformMatrix3fv: + syscall.Syscall6(glUniformMatrix3fv.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) + case glfnUniformMatrix4fv: + syscall.Syscall6(glUniformMatrix4fv.Addr(), 4, c.args.a0, c.args.a1, 0, uintptr(c.parg), 0, 0) + case glfnUseProgram: + syscall.Syscall(glUseProgram.Addr(), 1, c.args.a0, 0, 0) + case glfnValidateProgram: + syscall.Syscall(glValidateProgram.Addr(), 1, c.args.a0, 0, 0) + case glfnVertexAttrib1f: + syscall.Syscall6(glVertexAttrib1f.Addr(), 2, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnVertexAttrib1fv: + syscall.Syscall(glVertexAttrib1fv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) + case glfnVertexAttrib2f: + syscall.Syscall6(glVertexAttrib2f.Addr(), 3, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnVertexAttrib2fv: + syscall.Syscall(glVertexAttrib2fv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) + case glfnVertexAttrib3f: + syscall.Syscall6(glVertexAttrib3f.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnVertexAttrib3fv: + syscall.Syscall(glVertexAttrib3fv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) + case glfnVertexAttrib4f: + syscall.Syscall6(glVertexAttrib4f.Addr(), 5, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnVertexAttrib4fv: + syscall.Syscall(glVertexAttrib4fv.Addr(), 2, c.args.a0, uintptr(c.parg), 0) + case glfnVertexAttribPointer: + syscall.Syscall6(glVertexAttribPointer.Addr(), 6, c.args.a0, c.args.a1, c.args.a2, c.args.a3, c.args.a4, c.args.a5) + case glfnViewport: + syscall.Syscall6(glViewport.Addr(), 4, c.args.a0, c.args.a1, c.args.a2, c.args.a3, 0, 0) + default: + panic("unknown GL function") + } + + return ret +} + +// Exported libraries for a Windows GUI driver. +// +// LibEGL is not used directly by the gl package, but is needed by any +// driver hoping to use OpenGL ES. +// +// LibD3DCompiler is needed by libglesv2.dll for compiling shaders. +var ( + LibGLESv2 = syscall.NewLazyDLL("libglesv2.dll") + LibEGL = syscall.NewLazyDLL("libegl.dll") + LibD3DCompiler = syscall.NewLazyDLL("d3dcompiler_47.dll") +) + +var ( + libGLESv2 = LibGLESv2 + glActiveTexture = libGLESv2.NewProc("glActiveTexture") + glAttachShader = libGLESv2.NewProc("glAttachShader") + glBindAttribLocation = libGLESv2.NewProc("glBindAttribLocation") + glBindBuffer = libGLESv2.NewProc("glBindBuffer") + glBindFramebuffer = libGLESv2.NewProc("glBindFramebuffer") + glBindRenderbuffer = libGLESv2.NewProc("glBindRenderbuffer") + glBindTexture = libGLESv2.NewProc("glBindTexture") + glBindVertexArray = libGLESv2.NewProc("glBindVertexArray") + glBlendColor = libGLESv2.NewProc("glBlendColor") + glBlendEquation = libGLESv2.NewProc("glBlendEquation") + glBlendEquationSeparate = libGLESv2.NewProc("glBlendEquationSeparate") + glBlendFunc = libGLESv2.NewProc("glBlendFunc") + glBlendFuncSeparate = libGLESv2.NewProc("glBlendFuncSeparate") + glBufferData = libGLESv2.NewProc("glBufferData") + glBufferSubData = libGLESv2.NewProc("glBufferSubData") + glCheckFramebufferStatus = libGLESv2.NewProc("glCheckFramebufferStatus") + glClear = libGLESv2.NewProc("glClear") + glClearColor = libGLESv2.NewProc("glClearColor") + glClearDepthf = libGLESv2.NewProc("glClearDepthf") + glClearStencil = libGLESv2.NewProc("glClearStencil") + glColorMask = libGLESv2.NewProc("glColorMask") + glCompileShader = libGLESv2.NewProc("glCompileShader") + glCompressedTexImage2D = libGLESv2.NewProc("glCompressedTexImage2D") + glCompressedTexSubImage2D = libGLESv2.NewProc("glCompressedTexSubImage2D") + glCopyTexImage2D = libGLESv2.NewProc("glCopyTexImage2D") + glCopyTexSubImage2D = libGLESv2.NewProc("glCopyTexSubImage2D") + glCreateProgram = libGLESv2.NewProc("glCreateProgram") + glCreateShader = libGLESv2.NewProc("glCreateShader") + glCullFace = libGLESv2.NewProc("glCullFace") + glDeleteBuffers = libGLESv2.NewProc("glDeleteBuffers") + glDeleteFramebuffers = libGLESv2.NewProc("glDeleteFramebuffers") + glDeleteProgram = libGLESv2.NewProc("glDeleteProgram") + glDeleteRenderbuffers = libGLESv2.NewProc("glDeleteRenderbuffers") + glDeleteShader = libGLESv2.NewProc("glDeleteShader") + glDeleteTextures = libGLESv2.NewProc("glDeleteTextures") + glDeleteVertexArrays = libGLESv2.NewProc("glDeleteVertexArrays") + glDepthFunc = libGLESv2.NewProc("glDepthFunc") + glDepthRangef = libGLESv2.NewProc("glDepthRangef") + glDepthMask = libGLESv2.NewProc("glDepthMask") + glDetachShader = libGLESv2.NewProc("glDetachShader") + glDisable = libGLESv2.NewProc("glDisable") + glDisableVertexAttribArray = libGLESv2.NewProc("glDisableVertexAttribArray") + glDrawArrays = libGLESv2.NewProc("glDrawArrays") + glDrawElements = libGLESv2.NewProc("glDrawElements") + glEnable = libGLESv2.NewProc("glEnable") + glEnableVertexAttribArray = libGLESv2.NewProc("glEnableVertexAttribArray") + glFinish = libGLESv2.NewProc("glFinish") + glFlush = libGLESv2.NewProc("glFlush") + glFramebufferRenderbuffer = libGLESv2.NewProc("glFramebufferRenderbuffer") + glFramebufferTexture2D = libGLESv2.NewProc("glFramebufferTexture2D") + glFrontFace = libGLESv2.NewProc("glFrontFace") + glGenBuffers = libGLESv2.NewProc("glGenBuffers") + glGenFramebuffers = libGLESv2.NewProc("glGenFramebuffers") + glGenRenderbuffers = libGLESv2.NewProc("glGenRenderbuffers") + glGenTextures = libGLESv2.NewProc("glGenTextures") + glGenVertexArrays = libGLESv2.NewProc("glGenVertexArrays") + glGenerateMipmap = libGLESv2.NewProc("glGenerateMipmap") + glGetActiveAttrib = libGLESv2.NewProc("glGetActiveAttrib") + glGetActiveUniform = libGLESv2.NewProc("glGetActiveUniform") + glGetAttachedShaders = libGLESv2.NewProc("glGetAttachedShaders") + glGetAttribLocation = libGLESv2.NewProc("glGetAttribLocation") + glGetBooleanv = libGLESv2.NewProc("glGetBooleanv") + glGetBufferParameteri = libGLESv2.NewProc("glGetBufferParameteri") + glGetError = libGLESv2.NewProc("glGetError") + glGetFloatv = libGLESv2.NewProc("glGetFloatv") + glGetFramebufferAttachmentParameteriv = libGLESv2.NewProc("glGetFramebufferAttachmentParameteriv") + glGetIntegerv = libGLESv2.NewProc("glGetIntegerv") + glGetProgramInfoLog = libGLESv2.NewProc("glGetProgramInfoLog") + glGetProgramiv = libGLESv2.NewProc("glGetProgramiv") + glGetRenderbufferParameteriv = libGLESv2.NewProc("glGetRenderbufferParameteriv") + glGetShaderInfoLog = libGLESv2.NewProc("glGetShaderInfoLog") + glGetShaderPrecisionFormat = libGLESv2.NewProc("glGetShaderPrecisionFormat") + glGetShaderSource = libGLESv2.NewProc("glGetShaderSource") + glGetShaderiv = libGLESv2.NewProc("glGetShaderiv") + glGetString = libGLESv2.NewProc("glGetString") + glGetTexParameterfv = libGLESv2.NewProc("glGetTexParameterfv") + glGetTexParameteriv = libGLESv2.NewProc("glGetTexParameteriv") + glGetUniformLocation = libGLESv2.NewProc("glGetUniformLocation") + glGetUniformfv = libGLESv2.NewProc("glGetUniformfv") + glGetUniformiv = libGLESv2.NewProc("glGetUniformiv") + glGetVertexAttribfv = libGLESv2.NewProc("glGetVertexAttribfv") + glGetVertexAttribiv = libGLESv2.NewProc("glGetVertexAttribiv") + glHint = libGLESv2.NewProc("glHint") + glIsBuffer = libGLESv2.NewProc("glIsBuffer") + glIsEnabled = libGLESv2.NewProc("glIsEnabled") + glIsFramebuffer = libGLESv2.NewProc("glIsFramebuffer") + glIsProgram = libGLESv2.NewProc("glIsProgram") + glIsRenderbuffer = libGLESv2.NewProc("glIsRenderbuffer") + glIsShader = libGLESv2.NewProc("glIsShader") + glIsTexture = libGLESv2.NewProc("glIsTexture") + glLineWidth = libGLESv2.NewProc("glLineWidth") + glLinkProgram = libGLESv2.NewProc("glLinkProgram") + glPixelStorei = libGLESv2.NewProc("glPixelStorei") + glPolygonOffset = libGLESv2.NewProc("glPolygonOffset") + glReadPixels = libGLESv2.NewProc("glReadPixels") + glReleaseShaderCompiler = libGLESv2.NewProc("glReleaseShaderCompiler") + glRenderbufferStorage = libGLESv2.NewProc("glRenderbufferStorage") + glSampleCoverage = libGLESv2.NewProc("glSampleCoverage") + glScissor = libGLESv2.NewProc("glScissor") + glShaderSource = libGLESv2.NewProc("glShaderSource") + glStencilFunc = libGLESv2.NewProc("glStencilFunc") + glStencilFuncSeparate = libGLESv2.NewProc("glStencilFuncSeparate") + glStencilMask = libGLESv2.NewProc("glStencilMask") + glStencilMaskSeparate = libGLESv2.NewProc("glStencilMaskSeparate") + glStencilOp = libGLESv2.NewProc("glStencilOp") + glStencilOpSeparate = libGLESv2.NewProc("glStencilOpSeparate") + glTexImage2D = libGLESv2.NewProc("glTexImage2D") + glTexParameterf = libGLESv2.NewProc("glTexParameterf") + glTexParameterfv = libGLESv2.NewProc("glTexParameterfv") + glTexParameteri = libGLESv2.NewProc("glTexParameteri") + glTexParameteriv = libGLESv2.NewProc("glTexParameteriv") + glTexSubImage2D = libGLESv2.NewProc("glTexSubImage2D") + glUniform1f = libGLESv2.NewProc("glUniform1f") + glUniform1fv = libGLESv2.NewProc("glUniform1fv") + glUniform1i = libGLESv2.NewProc("glUniform1i") + glUniform1iv = libGLESv2.NewProc("glUniform1iv") + glUniform2f = libGLESv2.NewProc("glUniform2f") + glUniform2fv = libGLESv2.NewProc("glUniform2fv") + glUniform2i = libGLESv2.NewProc("glUniform2i") + glUniform2iv = libGLESv2.NewProc("glUniform2iv") + glUniform3f = libGLESv2.NewProc("glUniform3f") + glUniform3fv = libGLESv2.NewProc("glUniform3fv") + glUniform3i = libGLESv2.NewProc("glUniform3i") + glUniform3iv = libGLESv2.NewProc("glUniform3iv") + glUniform4f = libGLESv2.NewProc("glUniform4f") + glUniform4fv = libGLESv2.NewProc("glUniform4fv") + glUniform4i = libGLESv2.NewProc("glUniform4i") + glUniform4iv = libGLESv2.NewProc("glUniform4iv") + glUniformMatrix2fv = libGLESv2.NewProc("glUniformMatrix2fv") + glUniformMatrix3fv = libGLESv2.NewProc("glUniformMatrix3fv") + glUniformMatrix4fv = libGLESv2.NewProc("glUniformMatrix4fv") + glUseProgram = libGLESv2.NewProc("glUseProgram") + glValidateProgram = libGLESv2.NewProc("glValidateProgram") + glVertexAttrib1f = libGLESv2.NewProc("glVertexAttrib1f") + glVertexAttrib1fv = libGLESv2.NewProc("glVertexAttrib1fv") + glVertexAttrib2f = libGLESv2.NewProc("glVertexAttrib2f") + glVertexAttrib2fv = libGLESv2.NewProc("glVertexAttrib2fv") + glVertexAttrib3f = libGLESv2.NewProc("glVertexAttrib3f") + glVertexAttrib3fv = libGLESv2.NewProc("glVertexAttrib3fv") + glVertexAttrib4f = libGLESv2.NewProc("glVertexAttrib4f") + glVertexAttrib4fv = libGLESv2.NewProc("glVertexAttrib4fv") + glVertexAttribPointer = libGLESv2.NewProc("glVertexAttribPointer") + glViewport = libGLESv2.NewProc("glViewport") +) diff --git a/vendor/golang.org/x/mobile/gl/work_windows_386.s b/vendor/golang.org/x/mobile/gl/work_windows_386.s new file mode 100644 index 00000000..c80e98a0 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/work_windows_386.s @@ -0,0 +1,9 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// fixFloat is unnecessary for windows/386 +TEXT ·fixFloat(SB),NOSPLIT,$0-16 + RET diff --git a/vendor/golang.org/x/mobile/gl/work_windows_amd64.s b/vendor/golang.org/x/mobile/gl/work_windows_amd64.s new file mode 100644 index 00000000..e74ac5c0 --- /dev/null +++ b/vendor/golang.org/x/mobile/gl/work_windows_amd64.s @@ -0,0 +1,12 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +TEXT ·fixFloat(SB),NOSPLIT,$0-32 + MOVQ x0+0(FP), X0 + MOVQ x1+8(FP), X1 + MOVQ x2+16(FP), X2 + MOVQ x3+24(FP), X3 + RET diff --git a/vendor/golang.org/x/mobile/internal/mobileinit/ctx_android.go b/vendor/golang.org/x/mobile/internal/mobileinit/ctx_android.go new file mode 100644 index 00000000..b58881a2 --- /dev/null +++ b/vendor/golang.org/x/mobile/internal/mobileinit/ctx_android.go @@ -0,0 +1,124 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mobileinit + +/* +#include +#include + +static char* lockJNI(JavaVM *vm, uintptr_t* envp, int* attachedp) { + JNIEnv* env; + + if (vm == NULL) { + return "no current JVM"; + } + + *attachedp = 0; + switch ((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6)) { + case JNI_OK: + break; + case JNI_EDETACHED: + if ((*vm)->AttachCurrentThread(vm, &env, 0) != 0) { + return "cannot attach to JVM"; + } + *attachedp = 1; + break; + case JNI_EVERSION: + return "bad JNI version"; + default: + return "unknown JNI error from GetEnv"; + } + + *envp = (uintptr_t)env; + return NULL; +} + +static char* checkException(uintptr_t jnienv) { + jthrowable exc; + JNIEnv* env = (JNIEnv*)jnienv; + + if (!(*env)->ExceptionCheck(env)) { + return NULL; + } + + exc = (*env)->ExceptionOccurred(env); + (*env)->ExceptionClear(env); + + jclass clazz = (*env)->FindClass(env, "java/lang/Throwable"); + jmethodID toString = (*env)->GetMethodID(env, clazz, "toString", "()Ljava/lang/String;"); + jobject msgStr = (*env)->CallObjectMethod(env, exc, toString); + return (char*)(*env)->GetStringUTFChars(env, msgStr, 0); +} + +static void unlockJNI(JavaVM *vm) { + (*vm)->DetachCurrentThread(vm); +} +*/ +import "C" + +import ( + "errors" + "runtime" + "unsafe" +) + +// currentVM is stored to initialize other cgo packages. +// +// As all the Go packages in a program form a single shared library, +// there can only be one JNI_OnLoad function for initialization. In +// OpenJDK there is JNI_GetCreatedJavaVMs, but this is not available +// on android. +var currentVM *C.JavaVM + +// currentCtx is Android's android.context.Context. May be NULL. +var currentCtx C.jobject + +// SetCurrentContext populates the global Context object with the specified +// current JavaVM instance (vm) and android.context.Context object (ctx). +// The android.context.Context object must be a global reference. +func SetCurrentContext(vm unsafe.Pointer, ctx uintptr) { + currentVM = (*C.JavaVM)(vm) + currentCtx = (C.jobject)(ctx) +} + +// RunOnJVM runs fn on a new goroutine locked to an OS thread with a JNIEnv. +// +// RunOnJVM blocks until the call to fn is complete. Any Java +// exception or failure to attach to the JVM is returned as an error. +// +// The function fn takes vm, the current JavaVM*, +// env, the current JNIEnv*, and +// ctx, a jobject representing the global android.context.Context. +func RunOnJVM(fn func(vm, env, ctx uintptr) error) error { + errch := make(chan error) + go func() { + runtime.LockOSThread() + defer runtime.UnlockOSThread() + + env := C.uintptr_t(0) + attached := C.int(0) + if errStr := C.lockJNI(currentVM, &env, &attached); errStr != nil { + errch <- errors.New(C.GoString(errStr)) + return + } + if attached != 0 { + defer C.unlockJNI(currentVM) + } + + vm := uintptr(unsafe.Pointer(currentVM)) + if err := fn(vm, uintptr(env), uintptr(currentCtx)); err != nil { + errch <- err + return + } + + if exc := C.checkException(env); exc != nil { + errch <- errors.New(C.GoString(exc)) + C.free(unsafe.Pointer(exc)) + return + } + errch <- nil + }() + return <-errch +} diff --git a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit.go b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit.go new file mode 100644 index 00000000..65c09121 --- /dev/null +++ b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit.go @@ -0,0 +1,11 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package mobileinit contains common initialization logic for mobile platforms +// that is relevant to both all-Go apps and gobind-based apps. +// +// Long-term, some code in this package should consider moving into Go stdlib. +package mobileinit + +import "C" diff --git a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_android.go b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_android.go new file mode 100644 index 00000000..cd73f430 --- /dev/null +++ b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_android.go @@ -0,0 +1,93 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mobileinit + +/* +To view the log output run: +adb logcat GoLog:I *:S +*/ + +// Android redirects stdout and stderr to /dev/null. +// As these are common debugging utilities in Go, +// we redirect them to logcat. +// +// Unfortunately, logcat is line oriented, so we must buffer. + +/* +#cgo LDFLAGS: -landroid -llog + +#include +#include +#include +*/ +import "C" + +import ( + "bufio" + "log" + "os" + "syscall" + "unsafe" +) + +var ( + ctag = C.CString("GoLog") + // Store the writer end of the redirected stderr and stdout + // so that they are not garbage collected and closed. + stderr, stdout *os.File +) + +type infoWriter struct{} + +func (infoWriter) Write(p []byte) (n int, err error) { + cstr := C.CString(string(p)) + C.__android_log_write(C.ANDROID_LOG_INFO, ctag, cstr) + C.free(unsafe.Pointer(cstr)) + return len(p), nil +} + +func lineLog(f *os.File, priority C.int) { + const logSize = 1024 // matches android/log.h. + r := bufio.NewReaderSize(f, logSize) + for { + line, _, err := r.ReadLine() + str := string(line) + if err != nil { + str += " " + err.Error() + } + cstr := C.CString(str) + C.__android_log_write(priority, ctag, cstr) + C.free(unsafe.Pointer(cstr)) + if err != nil { + break + } + } +} + +func init() { + log.SetOutput(infoWriter{}) + // android logcat includes all of log.LstdFlags + log.SetFlags(log.Flags() &^ log.LstdFlags) + + r, w, err := os.Pipe() + if err != nil { + panic(err) + } + stderr = w + if err := syscall.Dup3(int(w.Fd()), int(os.Stderr.Fd()), 0); err != nil { + panic(err) + } + go lineLog(r, C.ANDROID_LOG_ERROR) + + r, w, err = os.Pipe() + if err != nil { + panic(err) + } + stdout = w + if err := syscall.Dup3(int(w.Fd()), int(os.Stdout.Fd()), 0); err != nil { + panic(err) + } + go lineLog(r, C.ANDROID_LOG_INFO) +} diff --git a/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_ios.go b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_ios.go new file mode 100644 index 00000000..d41b228e --- /dev/null +++ b/vendor/golang.org/x/mobile/internal/mobileinit/mobileinit_ios.go @@ -0,0 +1,41 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package mobileinit + +import ( + "io" + "log" + "os" + "unsafe" +) + +/* +#include +#include + +os_log_t create_os_log() { + return os_log_create("org.golang.mobile", "os_log"); +} + +void os_log_wrap(os_log_t log, const char *str) { + os_log(log, "%s", str); +} +*/ +import "C" + +type osWriter struct { + w C.os_log_t +} + +func (o osWriter) Write(p []byte) (n int, err error) { + cstr := C.CString(string(p)) + C.os_log_wrap(o.w, cstr) + C.free(unsafe.Pointer(cstr)) + return len(p), nil +} + +func init() { + log.SetOutput(io.MultiWriter(os.Stderr, osWriter{C.create_os_log()})) +} diff --git a/vendor/golang.org/x/sys/plan9/asm.s b/vendor/golang.org/x/sys/plan9/asm.s new file mode 100644 index 00000000..06449ebf --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/asm.s @@ -0,0 +1,8 @@ +// Copyright 2014 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +TEXT ·use(SB),NOSPLIT,$0 + RET diff --git a/vendor/golang.org/x/sys/plan9/asm_plan9_386.s b/vendor/golang.org/x/sys/plan9/asm_plan9_386.s new file mode 100644 index 00000000..bc5cab1f --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/asm_plan9_386.s @@ -0,0 +1,30 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// +// System call support for 386, Plan 9 +// + +// Just jump to package syscall's implementation for all these functions. +// The runtime may know about them. + +TEXT ·Syscall(SB),NOSPLIT,$0-32 + JMP syscall·Syscall(SB) + +TEXT ·Syscall6(SB),NOSPLIT,$0-44 + JMP syscall·Syscall6(SB) + +TEXT ·RawSyscall(SB),NOSPLIT,$0-28 + JMP syscall·RawSyscall(SB) + +TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 + JMP syscall·RawSyscall6(SB) + +TEXT ·seek(SB),NOSPLIT,$0-36 + JMP syscall·seek(SB) + +TEXT ·exit(SB),NOSPLIT,$4-4 + JMP syscall·exit(SB) diff --git a/vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s b/vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s new file mode 100644 index 00000000..d3448e67 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/asm_plan9_amd64.s @@ -0,0 +1,30 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// +// System call support for amd64, Plan 9 +// + +// Just jump to package syscall's implementation for all these functions. +// The runtime may know about them. + +TEXT ·Syscall(SB),NOSPLIT,$0-64 + JMP syscall·Syscall(SB) + +TEXT ·Syscall6(SB),NOSPLIT,$0-88 + JMP syscall·Syscall6(SB) + +TEXT ·RawSyscall(SB),NOSPLIT,$0-56 + JMP syscall·RawSyscall(SB) + +TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 + JMP syscall·RawSyscall6(SB) + +TEXT ·seek(SB),NOSPLIT,$0-56 + JMP syscall·seek(SB) + +TEXT ·exit(SB),NOSPLIT,$8-8 + JMP syscall·exit(SB) diff --git a/vendor/golang.org/x/sys/plan9/asm_plan9_arm.s b/vendor/golang.org/x/sys/plan9/asm_plan9_arm.s new file mode 100644 index 00000000..afb7c0a9 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/asm_plan9_arm.s @@ -0,0 +1,25 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +#include "textflag.h" + +// System call support for plan9 on arm + +// Just jump to package syscall's implementation for all these functions. +// The runtime may know about them. + +TEXT ·Syscall(SB),NOSPLIT,$0-32 + JMP syscall·Syscall(SB) + +TEXT ·Syscall6(SB),NOSPLIT,$0-44 + JMP syscall·Syscall6(SB) + +TEXT ·RawSyscall(SB),NOSPLIT,$0-28 + JMP syscall·RawSyscall(SB) + +TEXT ·RawSyscall6(SB),NOSPLIT,$0-40 + JMP syscall·RawSyscall6(SB) + +TEXT ·seek(SB),NOSPLIT,$0-36 + JMP syscall·exit(SB) diff --git a/vendor/golang.org/x/sys/plan9/const_plan9.go b/vendor/golang.org/x/sys/plan9/const_plan9.go new file mode 100644 index 00000000..b4e85a3a --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/const_plan9.go @@ -0,0 +1,70 @@ +package plan9 + +// Plan 9 Constants + +// Open modes +const ( + O_RDONLY = 0 + O_WRONLY = 1 + O_RDWR = 2 + O_TRUNC = 16 + O_CLOEXEC = 32 + O_EXCL = 0x1000 +) + +// Rfork flags +const ( + RFNAMEG = 1 << 0 + RFENVG = 1 << 1 + RFFDG = 1 << 2 + RFNOTEG = 1 << 3 + RFPROC = 1 << 4 + RFMEM = 1 << 5 + RFNOWAIT = 1 << 6 + RFCNAMEG = 1 << 10 + RFCENVG = 1 << 11 + RFCFDG = 1 << 12 + RFREND = 1 << 13 + RFNOMNT = 1 << 14 +) + +// Qid.Type bits +const ( + QTDIR = 0x80 + QTAPPEND = 0x40 + QTEXCL = 0x20 + QTMOUNT = 0x10 + QTAUTH = 0x08 + QTTMP = 0x04 + QTFILE = 0x00 +) + +// Dir.Mode bits +const ( + DMDIR = 0x80000000 + DMAPPEND = 0x40000000 + DMEXCL = 0x20000000 + DMMOUNT = 0x10000000 + DMAUTH = 0x08000000 + DMTMP = 0x04000000 + DMREAD = 0x4 + DMWRITE = 0x2 + DMEXEC = 0x1 +) + +const ( + STATMAX = 65535 + ERRMAX = 128 + STATFIXLEN = 49 +) + +// Mount and bind flags +const ( + MREPL = 0x0000 + MBEFORE = 0x0001 + MAFTER = 0x0002 + MORDER = 0x0003 + MCREATE = 0x0004 + MCACHE = 0x0010 + MMASK = 0x0017 +) diff --git a/vendor/golang.org/x/sys/plan9/dir_plan9.go b/vendor/golang.org/x/sys/plan9/dir_plan9.go new file mode 100644 index 00000000..0955e0c5 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/dir_plan9.go @@ -0,0 +1,212 @@ +// Copyright 2012 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Plan 9 directory marshalling. See intro(5). + +package plan9 + +import "errors" + +var ( + ErrShortStat = errors.New("stat buffer too short") + ErrBadStat = errors.New("malformed stat buffer") + ErrBadName = errors.New("bad character in file name") +) + +// A Qid represents a 9P server's unique identification for a file. +type Qid struct { + Path uint64 // the file server's unique identification for the file + Vers uint32 // version number for given Path + Type uint8 // the type of the file (plan9.QTDIR for example) +} + +// A Dir contains the metadata for a file. +type Dir struct { + // system-modified data + Type uint16 // server type + Dev uint32 // server subtype + + // file data + Qid Qid // unique id from server + Mode uint32 // permissions + Atime uint32 // last read time + Mtime uint32 // last write time + Length int64 // file length + Name string // last element of path + Uid string // owner name + Gid string // group name + Muid string // last modifier name +} + +var nullDir = Dir{ + Type: ^uint16(0), + Dev: ^uint32(0), + Qid: Qid{ + Path: ^uint64(0), + Vers: ^uint32(0), + Type: ^uint8(0), + }, + Mode: ^uint32(0), + Atime: ^uint32(0), + Mtime: ^uint32(0), + Length: ^int64(0), +} + +// Null assigns special "don't touch" values to members of d to +// avoid modifying them during plan9.Wstat. +func (d *Dir) Null() { *d = nullDir } + +// Marshal encodes a 9P stat message corresponding to d into b +// +// If there isn't enough space in b for a stat message, ErrShortStat is returned. +func (d *Dir) Marshal(b []byte) (n int, err error) { + n = STATFIXLEN + len(d.Name) + len(d.Uid) + len(d.Gid) + len(d.Muid) + if n > len(b) { + return n, ErrShortStat + } + + for _, c := range d.Name { + if c == '/' { + return n, ErrBadName + } + } + + b = pbit16(b, uint16(n)-2) + b = pbit16(b, d.Type) + b = pbit32(b, d.Dev) + b = pbit8(b, d.Qid.Type) + b = pbit32(b, d.Qid.Vers) + b = pbit64(b, d.Qid.Path) + b = pbit32(b, d.Mode) + b = pbit32(b, d.Atime) + b = pbit32(b, d.Mtime) + b = pbit64(b, uint64(d.Length)) + b = pstring(b, d.Name) + b = pstring(b, d.Uid) + b = pstring(b, d.Gid) + b = pstring(b, d.Muid) + + return n, nil +} + +// UnmarshalDir decodes a single 9P stat message from b and returns the resulting Dir. +// +// If b is too small to hold a valid stat message, ErrShortStat is returned. +// +// If the stat message itself is invalid, ErrBadStat is returned. +func UnmarshalDir(b []byte) (*Dir, error) { + if len(b) < STATFIXLEN { + return nil, ErrShortStat + } + size, buf := gbit16(b) + if len(b) != int(size)+2 { + return nil, ErrBadStat + } + b = buf + + var d Dir + d.Type, b = gbit16(b) + d.Dev, b = gbit32(b) + d.Qid.Type, b = gbit8(b) + d.Qid.Vers, b = gbit32(b) + d.Qid.Path, b = gbit64(b) + d.Mode, b = gbit32(b) + d.Atime, b = gbit32(b) + d.Mtime, b = gbit32(b) + + n, b := gbit64(b) + d.Length = int64(n) + + var ok bool + if d.Name, b, ok = gstring(b); !ok { + return nil, ErrBadStat + } + if d.Uid, b, ok = gstring(b); !ok { + return nil, ErrBadStat + } + if d.Gid, b, ok = gstring(b); !ok { + return nil, ErrBadStat + } + if d.Muid, b, ok = gstring(b); !ok { + return nil, ErrBadStat + } + + return &d, nil +} + +// pbit8 copies the 8-bit number v to b and returns the remaining slice of b. +func pbit8(b []byte, v uint8) []byte { + b[0] = byte(v) + return b[1:] +} + +// pbit16 copies the 16-bit number v to b in little-endian order and returns the remaining slice of b. +func pbit16(b []byte, v uint16) []byte { + b[0] = byte(v) + b[1] = byte(v >> 8) + return b[2:] +} + +// pbit32 copies the 32-bit number v to b in little-endian order and returns the remaining slice of b. +func pbit32(b []byte, v uint32) []byte { + b[0] = byte(v) + b[1] = byte(v >> 8) + b[2] = byte(v >> 16) + b[3] = byte(v >> 24) + return b[4:] +} + +// pbit64 copies the 64-bit number v to b in little-endian order and returns the remaining slice of b. +func pbit64(b []byte, v uint64) []byte { + b[0] = byte(v) + b[1] = byte(v >> 8) + b[2] = byte(v >> 16) + b[3] = byte(v >> 24) + b[4] = byte(v >> 32) + b[5] = byte(v >> 40) + b[6] = byte(v >> 48) + b[7] = byte(v >> 56) + return b[8:] +} + +// pstring copies the string s to b, prepending it with a 16-bit length in little-endian order, and +// returning the remaining slice of b.. +func pstring(b []byte, s string) []byte { + b = pbit16(b, uint16(len(s))) + n := copy(b, s) + return b[n:] +} + +// gbit8 reads an 8-bit number from b and returns it with the remaining slice of b. +func gbit8(b []byte) (uint8, []byte) { + return uint8(b[0]), b[1:] +} + +// gbit16 reads a 16-bit number in little-endian order from b and returns it with the remaining slice of b. +func gbit16(b []byte) (uint16, []byte) { + return uint16(b[0]) | uint16(b[1])<<8, b[2:] +} + +// gbit32 reads a 32-bit number in little-endian order from b and returns it with the remaining slice of b. +func gbit32(b []byte) (uint32, []byte) { + return uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24, b[4:] +} + +// gbit64 reads a 64-bit number in little-endian order from b and returns it with the remaining slice of b. +func gbit64(b []byte) (uint64, []byte) { + lo := uint32(b[0]) | uint32(b[1])<<8 | uint32(b[2])<<16 | uint32(b[3])<<24 + hi := uint32(b[4]) | uint32(b[5])<<8 | uint32(b[6])<<16 | uint32(b[7])<<24 + return uint64(lo) | uint64(hi)<<32, b[8:] +} + +// gstring reads a string from b, prefixed with a 16-bit length in little-endian order. +// It returns the string with the remaining slice of b and a boolean. If the length is +// greater than the number of bytes in b, the boolean will be false. +func gstring(b []byte) (string, []byte, bool) { + n, b := gbit16(b) + if int(n) > len(b) { + return "", b, false + } + return string(b[:n]), b[n:], true +} diff --git a/vendor/golang.org/x/sys/plan9/env_plan9.go b/vendor/golang.org/x/sys/plan9/env_plan9.go new file mode 100644 index 00000000..8f191800 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/env_plan9.go @@ -0,0 +1,31 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Plan 9 environment variables. + +package plan9 + +import ( + "syscall" +) + +func Getenv(key string) (value string, found bool) { + return syscall.Getenv(key) +} + +func Setenv(key, value string) error { + return syscall.Setenv(key, value) +} + +func Clearenv() { + syscall.Clearenv() +} + +func Environ() []string { + return syscall.Environ() +} + +func Unsetenv(key string) error { + return syscall.Unsetenv(key) +} diff --git a/vendor/golang.org/x/sys/plan9/errors_plan9.go b/vendor/golang.org/x/sys/plan9/errors_plan9.go new file mode 100644 index 00000000..65fe74d3 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/errors_plan9.go @@ -0,0 +1,50 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package plan9 + +import "syscall" + +// Constants +const ( + // Invented values to support what package os expects. + O_CREAT = 0x02000 + O_APPEND = 0x00400 + O_NOCTTY = 0x00000 + O_NONBLOCK = 0x00000 + O_SYNC = 0x00000 + O_ASYNC = 0x00000 + + S_IFMT = 0x1f000 + S_IFIFO = 0x1000 + S_IFCHR = 0x2000 + S_IFDIR = 0x4000 + S_IFBLK = 0x6000 + S_IFREG = 0x8000 + S_IFLNK = 0xa000 + S_IFSOCK = 0xc000 +) + +// Errors +var ( + EINVAL = syscall.NewError("bad arg in system call") + ENOTDIR = syscall.NewError("not a directory") + EISDIR = syscall.NewError("file is a directory") + ENOENT = syscall.NewError("file does not exist") + EEXIST = syscall.NewError("file already exists") + EMFILE = syscall.NewError("no free file descriptors") + EIO = syscall.NewError("i/o error") + ENAMETOOLONG = syscall.NewError("file name too long") + EINTR = syscall.NewError("interrupted") + EPERM = syscall.NewError("permission denied") + EBUSY = syscall.NewError("no free devices") + ETIMEDOUT = syscall.NewError("connection timed out") + EPLAN9 = syscall.NewError("not supported by plan 9") + + // The following errors do not correspond to any + // Plan 9 system messages. Invented to support + // what package os and others expect. + EACCES = syscall.NewError("access permission denied") + EAFNOSUPPORT = syscall.NewError("address family not supported by protocol") +) diff --git a/vendor/golang.org/x/sys/plan9/mkall.sh b/vendor/golang.org/x/sys/plan9/mkall.sh new file mode 100644 index 00000000..1650fbcc --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/mkall.sh @@ -0,0 +1,150 @@ +#!/usr/bin/env bash +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# The plan9 package provides access to the raw system call +# interface of the underlying operating system. Porting Go to +# a new architecture/operating system combination requires +# some manual effort, though there are tools that automate +# much of the process. The auto-generated files have names +# beginning with z. +# +# This script runs or (given -n) prints suggested commands to generate z files +# for the current system. Running those commands is not automatic. +# This script is documentation more than anything else. +# +# * asm_${GOOS}_${GOARCH}.s +# +# This hand-written assembly file implements system call dispatch. +# There are three entry points: +# +# func Syscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr); +# func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr); +# func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr); +# +# The first and second are the standard ones; they differ only in +# how many arguments can be passed to the kernel. +# The third is for low-level use by the ForkExec wrapper; +# unlike the first two, it does not call into the scheduler to +# let it know that a system call is running. +# +# * syscall_${GOOS}.go +# +# This hand-written Go file implements system calls that need +# special handling and lists "//sys" comments giving prototypes +# for ones that can be auto-generated. Mksyscall reads those +# comments to generate the stubs. +# +# * syscall_${GOOS}_${GOARCH}.go +# +# Same as syscall_${GOOS}.go except that it contains code specific +# to ${GOOS} on one particular architecture. +# +# * types_${GOOS}.c +# +# This hand-written C file includes standard C headers and then +# creates typedef or enum names beginning with a dollar sign +# (use of $ in variable names is a gcc extension). The hardest +# part about preparing this file is figuring out which headers to +# include and which symbols need to be #defined to get the +# actual data structures that pass through to the kernel system calls. +# Some C libraries present alternate versions for binary compatibility +# and translate them on the way in and out of system calls, but +# there is almost always a #define that can get the real ones. +# See types_darwin.c and types_linux.c for examples. +# +# * zerror_${GOOS}_${GOARCH}.go +# +# This machine-generated file defines the system's error numbers, +# error strings, and signal numbers. The generator is "mkerrors.sh". +# Usually no arguments are needed, but mkerrors.sh will pass its +# arguments on to godefs. +# +# * zsyscall_${GOOS}_${GOARCH}.go +# +# Generated by mksyscall.pl; see syscall_${GOOS}.go above. +# +# * zsysnum_${GOOS}_${GOARCH}.go +# +# Generated by mksysnum_${GOOS}. +# +# * ztypes_${GOOS}_${GOARCH}.go +# +# Generated by godefs; see types_${GOOS}.c above. + +GOOSARCH="${GOOS}_${GOARCH}" + +# defaults +mksyscall="go run mksyscall.go" +mkerrors="./mkerrors.sh" +zerrors="zerrors_$GOOSARCH.go" +mksysctl="" +zsysctl="zsysctl_$GOOSARCH.go" +mksysnum= +mktypes= +run="sh" + +case "$1" in +-syscalls) + for i in zsyscall*go + do + sed 1q $i | sed 's;^// ;;' | sh > _$i && gofmt < _$i > $i + rm _$i + done + exit 0 + ;; +-n) + run="cat" + shift +esac + +case "$#" in +0) + ;; +*) + echo 'usage: mkall.sh [-n]' 1>&2 + exit 2 +esac + +case "$GOOSARCH" in +_* | *_ | _) + echo 'undefined $GOOS_$GOARCH:' "$GOOSARCH" 1>&2 + exit 1 + ;; +plan9_386) + mkerrors= + mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,386" + mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h" + mktypes="XXX" + ;; +plan9_amd64) + mkerrors= + mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,amd64" + mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h" + mktypes="XXX" + ;; +plan9_arm) + mkerrors= + mksyscall="go run mksyscall.go -l32 -plan9 -tags plan9,arm" + mksysnum="./mksysnum_plan9.sh /n/sources/plan9/sys/src/libc/9syscall/sys.h" + mktypes="XXX" + ;; +*) + echo 'unrecognized $GOOS_$GOARCH: ' "$GOOSARCH" 1>&2 + exit 1 + ;; +esac + +( + if [ -n "$mkerrors" ]; then echo "$mkerrors |gofmt >$zerrors"; fi + case "$GOOS" in + plan9) + syscall_goos="syscall_$GOOS.go" + if [ -n "$mksyscall" ]; then echo "$mksyscall $syscall_goos |gofmt >zsyscall_$GOOSARCH.go"; fi + ;; + esac + if [ -n "$mksysctl" ]; then echo "$mksysctl |gofmt >$zsysctl"; fi + if [ -n "$mksysnum" ]; then echo "$mksysnum |gofmt >zsysnum_$GOOSARCH.go"; fi + if [ -n "$mktypes" ]; then echo "$mktypes types_$GOOS.go |gofmt >ztypes_$GOOSARCH.go"; fi +) | $run diff --git a/vendor/golang.org/x/sys/plan9/mkerrors.sh b/vendor/golang.org/x/sys/plan9/mkerrors.sh new file mode 100644 index 00000000..526d04ab --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/mkerrors.sh @@ -0,0 +1,246 @@ +#!/usr/bin/env bash +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +# Generate Go code listing errors and other #defined constant +# values (ENAMETOOLONG etc.), by asking the preprocessor +# about the definitions. + +unset LANG +export LC_ALL=C +export LC_CTYPE=C + +CC=${CC:-gcc} + +uname=$(uname) + +includes=' +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +' + +ccflags="$@" + +# Write go tool cgo -godefs input. +( + echo package plan9 + echo + echo '/*' + indirect="includes_$(uname)" + echo "${!indirect} $includes" + echo '*/' + echo 'import "C"' + echo + echo 'const (' + + # The gcc command line prints all the #defines + # it encounters while processing the input + echo "${!indirect} $includes" | $CC -x c - -E -dM $ccflags | + awk ' + $1 != "#define" || $2 ~ /\(/ || $3 == "" {next} + + $2 ~ /^E([ABCD]X|[BIS]P|[SD]I|S|FL)$/ {next} # 386 registers + $2 ~ /^(SIGEV_|SIGSTKSZ|SIGRT(MIN|MAX))/ {next} + $2 ~ /^(SCM_SRCRT)$/ {next} + $2 ~ /^(MAP_FAILED)$/ {next} + + $2 !~ /^ETH_/ && + $2 !~ /^EPROC_/ && + $2 !~ /^EQUIV_/ && + $2 !~ /^EXPR_/ && + $2 ~ /^E[A-Z0-9_]+$/ || + $2 ~ /^B[0-9_]+$/ || + $2 ~ /^V[A-Z0-9]+$/ || + $2 ~ /^CS[A-Z0-9]/ || + $2 ~ /^I(SIG|CANON|CRNL|EXTEN|MAXBEL|STRIP|UTF8)$/ || + $2 ~ /^IGN/ || + $2 ~ /^IX(ON|ANY|OFF)$/ || + $2 ~ /^IN(LCR|PCK)$/ || + $2 ~ /(^FLU?SH)|(FLU?SH$)/ || + $2 ~ /^C(LOCAL|READ)$/ || + $2 == "BRKINT" || + $2 == "HUPCL" || + $2 == "PENDIN" || + $2 == "TOSTOP" || + $2 ~ /^PAR/ || + $2 ~ /^SIG[^_]/ || + $2 ~ /^O[CNPFP][A-Z]+[^_][A-Z]+$/ || + $2 ~ /^IN_/ || + $2 ~ /^LOCK_(SH|EX|NB|UN)$/ || + $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|ICMP6|TCP|EVFILT|NOTE|EV|SHUT|PROT|MAP|PACKET|MSG|SCM|MCL|DT|MADV|PR)_/ || + $2 == "ICMPV6_FILTER" || + $2 == "SOMAXCONN" || + $2 == "NAME_MAX" || + $2 == "IFNAMSIZ" || + $2 ~ /^CTL_(MAXNAME|NET|QUERY)$/ || + $2 ~ /^SYSCTL_VERS/ || + $2 ~ /^(MS|MNT)_/ || + $2 ~ /^TUN(SET|GET|ATTACH|DETACH)/ || + $2 ~ /^(O|F|FD|NAME|S|PTRACE|PT)_/ || + $2 ~ /^LINUX_REBOOT_CMD_/ || + $2 ~ /^LINUX_REBOOT_MAGIC[12]$/ || + $2 !~ "NLA_TYPE_MASK" && + $2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P)_/ || + $2 ~ /^SIOC/ || + $2 ~ /^TIOC/ || + $2 !~ "RTF_BITS" && + $2 ~ /^(IFF|IFT|NET_RT|RTM|RTF|RTV|RTA|RTAX)_/ || + $2 ~ /^BIOC/ || + $2 ~ /^RUSAGE_(SELF|CHILDREN|THREAD)/ || + $2 ~ /^RLIMIT_(AS|CORE|CPU|DATA|FSIZE|NOFILE|STACK)|RLIM_INFINITY/ || + $2 ~ /^PRIO_(PROCESS|PGRP|USER)/ || + $2 ~ /^CLONE_[A-Z_]+/ || + $2 !~ /^(BPF_TIMEVAL)$/ && + $2 ~ /^(BPF|DLT)_/ || + $2 !~ "WMESGLEN" && + $2 ~ /^W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", $2, $2)} + $2 ~ /^__WCOREFLAG$/ {next} + $2 ~ /^__W[A-Z0-9]+$/ {printf("\t%s = C.%s\n", substr($2,3), $2)} + + {next} + ' | sort + + echo ')' +) >_const.go + +# Pull out the error names for later. +errors=$( + echo '#include ' | $CC -x c - -E -dM $ccflags | + awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print $2 }' | + sort +) + +# Pull out the signal names for later. +signals=$( + echo '#include ' | $CC -x c - -E -dM $ccflags | + awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' | + grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' | + sort +) + +# Again, writing regexps to a file. +echo '#include ' | $CC -x c - -E -dM $ccflags | + awk '$1=="#define" && $2 ~ /^E[A-Z0-9_]+$/ { print "^\t" $2 "[ \t]*=" }' | + sort >_error.grep +echo '#include ' | $CC -x c - -E -dM $ccflags | + awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' | + grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT' | + sort >_signal.grep + +echo '// mkerrors.sh' "$@" +echo '// Code generated by the command above; DO NOT EDIT.' +echo +go tool cgo -godefs -- "$@" _const.go >_error.out +cat _error.out | grep -vf _error.grep | grep -vf _signal.grep +echo +echo '// Errors' +echo 'const (' +cat _error.out | grep -f _error.grep | sed 's/=\(.*\)/= Errno(\1)/' +echo ')' + +echo +echo '// Signals' +echo 'const (' +cat _error.out | grep -f _signal.grep | sed 's/=\(.*\)/= Signal(\1)/' +echo ')' + +# Run C program to print error and syscall strings. +( + echo -E " +#include +#include +#include +#include +#include +#include + +#define nelem(x) (sizeof(x)/sizeof((x)[0])) + +enum { A = 'A', Z = 'Z', a = 'a', z = 'z' }; // avoid need for single quotes below + +int errors[] = { +" + for i in $errors + do + echo -E ' '$i, + done + + echo -E " +}; + +int signals[] = { +" + for i in $signals + do + echo -E ' '$i, + done + + # Use -E because on some systems bash builtin interprets \n itself. + echo -E ' +}; + +static int +intcmp(const void *a, const void *b) +{ + return *(int*)a - *(int*)b; +} + +int +main(void) +{ + int i, j, e; + char buf[1024], *p; + + printf("\n\n// Error table\n"); + printf("var errors = [...]string {\n"); + qsort(errors, nelem(errors), sizeof errors[0], intcmp); + for(i=0; i 0 && errors[i-1] == e) + continue; + strcpy(buf, strerror(e)); + // lowercase first letter: Bad -> bad, but STREAM -> STREAM. + if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) + buf[0] += a - A; + printf("\t%d: \"%s\",\n", e, buf); + } + printf("}\n\n"); + + printf("\n\n// Signal table\n"); + printf("var signals = [...]string {\n"); + qsort(signals, nelem(signals), sizeof signals[0], intcmp); + for(i=0; i 0 && signals[i-1] == e) + continue; + strcpy(buf, strsignal(e)); + // lowercase first letter: Bad -> bad, but STREAM -> STREAM. + if(A <= buf[0] && buf[0] <= Z && a <= buf[1] && buf[1] <= z) + buf[0] += a - A; + // cut trailing : number. + p = strrchr(buf, ":"[0]); + if(p) + *p = '\0'; + printf("\t%d: \"%s\",\n", e, buf); + } + printf("}\n\n"); + + return 0; +} + +' +) >_errors.c + +$CC $ccflags -o _errors _errors.c && $GORUN ./_errors && rm -f _errors.c _errors _const.go _error.grep _signal.grep _error.out diff --git a/vendor/golang.org/x/sys/plan9/mksysnum_plan9.sh b/vendor/golang.org/x/sys/plan9/mksysnum_plan9.sh new file mode 100644 index 00000000..3c3ab058 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/mksysnum_plan9.sh @@ -0,0 +1,23 @@ +#!/bin/sh +# Copyright 2009 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +COMMAND="mksysnum_plan9.sh $@" + +cat <= 10 { + buf[i] = byte(val%10 + '0') + i-- + val /= 10 + } + buf[i] = byte(val + '0') + return string(buf[i:]) +} diff --git a/vendor/golang.org/x/sys/plan9/syscall.go b/vendor/golang.org/x/sys/plan9/syscall.go new file mode 100644 index 00000000..d631fd66 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/syscall.go @@ -0,0 +1,109 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build plan9 + +// Package plan9 contains an interface to the low-level operating system +// primitives. OS details vary depending on the underlying system, and +// by default, godoc will display the OS-specific documentation for the current +// system. If you want godoc to display documentation for another +// system, set $GOOS and $GOARCH to the desired system. For example, if +// you want to view documentation for freebsd/arm on linux/amd64, set $GOOS +// to freebsd and $GOARCH to arm. +// +// The primary use of this package is inside other packages that provide a more +// portable interface to the system, such as "os", "time" and "net". Use +// those packages rather than this one if you can. +// +// For details of the functions and data types in this package consult +// the manuals for the appropriate operating system. +// +// These calls return err == nil to indicate success; otherwise +// err represents an operating system error describing the failure and +// holds a value of type syscall.ErrorString. +package plan9 // import "golang.org/x/sys/plan9" + +import ( + "bytes" + "strings" + "unsafe" +) + +// ByteSliceFromString returns a NUL-terminated slice of bytes +// containing the text of s. If s contains a NUL byte at any +// location, it returns (nil, EINVAL). +func ByteSliceFromString(s string) ([]byte, error) { + if strings.IndexByte(s, 0) != -1 { + return nil, EINVAL + } + a := make([]byte, len(s)+1) + copy(a, s) + return a, nil +} + +// BytePtrFromString returns a pointer to a NUL-terminated array of +// bytes containing the text of s. If s contains a NUL byte at any +// location, it returns (nil, EINVAL). +func BytePtrFromString(s string) (*byte, error) { + a, err := ByteSliceFromString(s) + if err != nil { + return nil, err + } + return &a[0], nil +} + +// ByteSliceToString returns a string form of the text represented by the slice s, with a terminating NUL and any +// bytes after the NUL removed. +func ByteSliceToString(s []byte) string { + if i := bytes.IndexByte(s, 0); i != -1 { + s = s[:i] + } + return string(s) +} + +// BytePtrToString takes a pointer to a sequence of text and returns the corresponding string. +// If the pointer is nil, it returns the empty string. It assumes that the text sequence is terminated +// at a zero byte; if the zero byte is not present, the program may crash. +func BytePtrToString(p *byte) string { + if p == nil { + return "" + } + if *p == 0 { + return "" + } + + // Find NUL terminator. + n := 0 + for ptr := unsafe.Pointer(p); *(*byte)(ptr) != 0; n++ { + ptr = unsafe.Pointer(uintptr(ptr) + 1) + } + + return string(unsafe.Slice(p, n)) +} + +// Single-word zero for use when we need a valid pointer to 0 bytes. +// See mksyscall.pl. +var _zero uintptr + +func (ts *Timespec) Unix() (sec int64, nsec int64) { + return int64(ts.Sec), int64(ts.Nsec) +} + +func (tv *Timeval) Unix() (sec int64, nsec int64) { + return int64(tv.Sec), int64(tv.Usec) * 1000 +} + +func (ts *Timespec) Nano() int64 { + return int64(ts.Sec)*1e9 + int64(ts.Nsec) +} + +func (tv *Timeval) Nano() int64 { + return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000 +} + +// use is a no-op, but the compiler cannot see that it is. +// Calling use(p) ensures that p is kept live until that point. +// +//go:noescape +func use(p unsafe.Pointer) diff --git a/vendor/golang.org/x/sys/plan9/syscall_plan9.go b/vendor/golang.org/x/sys/plan9/syscall_plan9.go new file mode 100644 index 00000000..d079d811 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/syscall_plan9.go @@ -0,0 +1,361 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Plan 9 system calls. +// This file is compiled as ordinary Go code, +// but it is also input to mksyscall, +// which parses the //sys lines and generates system call stubs. +// Note that sometimes we use a lowercase //sys name and +// wrap it in our own nicer implementation. + +package plan9 + +import ( + "bytes" + "syscall" + "unsafe" +) + +// A Note is a string describing a process note. +// It implements the os.Signal interface. +type Note string + +func (n Note) Signal() {} + +func (n Note) String() string { + return string(n) +} + +var ( + Stdin = 0 + Stdout = 1 + Stderr = 2 +) + +// For testing: clients can set this flag to force +// creation of IPv6 sockets to return EAFNOSUPPORT. +var SocketDisableIPv6 bool + +func Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err syscall.ErrorString) +func Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err syscall.ErrorString) +func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2, err uintptr) +func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) + +func atoi(b []byte) (n uint) { + n = 0 + for i := 0; i < len(b); i++ { + n = n*10 + uint(b[i]-'0') + } + return +} + +func cstring(s []byte) string { + i := bytes.IndexByte(s, 0) + if i == -1 { + i = len(s) + } + return string(s[:i]) +} + +func errstr() string { + var buf [ERRMAX]byte + + RawSyscall(SYS_ERRSTR, uintptr(unsafe.Pointer(&buf[0])), uintptr(len(buf)), 0) + + buf[len(buf)-1] = 0 + return cstring(buf[:]) +} + +// Implemented in assembly to import from runtime. +func exit(code int) + +func Exit(code int) { exit(code) } + +func readnum(path string) (uint, error) { + var b [12]byte + + fd, e := Open(path, O_RDONLY) + if e != nil { + return 0, e + } + defer Close(fd) + + n, e := Pread(fd, b[:], 0) + + if e != nil { + return 0, e + } + + m := 0 + for ; m < n && b[m] == ' '; m++ { + } + + return atoi(b[m : n-1]), nil +} + +func Getpid() (pid int) { + n, _ := readnum("#c/pid") + return int(n) +} + +func Getppid() (ppid int) { + n, _ := readnum("#c/ppid") + return int(n) +} + +func Read(fd int, p []byte) (n int, err error) { + return Pread(fd, p, -1) +} + +func Write(fd int, p []byte) (n int, err error) { + return Pwrite(fd, p, -1) +} + +var ioSync int64 + +//sys fd2path(fd int, buf []byte) (err error) + +func Fd2path(fd int) (path string, err error) { + var buf [512]byte + + e := fd2path(fd, buf[:]) + if e != nil { + return "", e + } + return cstring(buf[:]), nil +} + +//sys pipe(p *[2]int32) (err error) + +func Pipe(p []int) (err error) { + if len(p) != 2 { + return syscall.ErrorString("bad arg in system call") + } + var pp [2]int32 + err = pipe(&pp) + if err == nil { + p[0] = int(pp[0]) + p[1] = int(pp[1]) + } + return +} + +// Underlying system call writes to newoffset via pointer. +// Implemented in assembly to avoid allocation. +func seek(placeholder uintptr, fd int, offset int64, whence int) (newoffset int64, err string) + +func Seek(fd int, offset int64, whence int) (newoffset int64, err error) { + newoffset, e := seek(0, fd, offset, whence) + + if newoffset == -1 { + err = syscall.ErrorString(e) + } + return +} + +func Mkdir(path string, mode uint32) (err error) { + fd, err := Create(path, O_RDONLY, DMDIR|mode) + + if fd != -1 { + Close(fd) + } + + return +} + +type Waitmsg struct { + Pid int + Time [3]uint32 + Msg string +} + +func (w Waitmsg) Exited() bool { return true } +func (w Waitmsg) Signaled() bool { return false } + +func (w Waitmsg) ExitStatus() int { + if len(w.Msg) == 0 { + // a normal exit returns no message + return 0 + } + return 1 +} + +//sys await(s []byte) (n int, err error) + +func Await(w *Waitmsg) (err error) { + var buf [512]byte + var f [5][]byte + + n, err := await(buf[:]) + + if err != nil || w == nil { + return + } + + nf := 0 + p := 0 + for i := 0; i < n && nf < len(f)-1; i++ { + if buf[i] == ' ' { + f[nf] = buf[p:i] + p = i + 1 + nf++ + } + } + f[nf] = buf[p:] + nf++ + + if nf != len(f) { + return syscall.ErrorString("invalid wait message") + } + w.Pid = int(atoi(f[0])) + w.Time[0] = uint32(atoi(f[1])) + w.Time[1] = uint32(atoi(f[2])) + w.Time[2] = uint32(atoi(f[3])) + w.Msg = cstring(f[4]) + if w.Msg == "''" { + // await() returns '' for no error + w.Msg = "" + } + return +} + +func Unmount(name, old string) (err error) { + fixwd() + oldp, err := BytePtrFromString(old) + if err != nil { + return err + } + oldptr := uintptr(unsafe.Pointer(oldp)) + + var r0 uintptr + var e syscall.ErrorString + + // bind(2) man page: If name is zero, everything bound or mounted upon old is unbound or unmounted. + if name == "" { + r0, _, e = Syscall(SYS_UNMOUNT, _zero, oldptr, 0) + } else { + namep, err := BytePtrFromString(name) + if err != nil { + return err + } + r0, _, e = Syscall(SYS_UNMOUNT, uintptr(unsafe.Pointer(namep)), oldptr, 0) + } + + if int32(r0) == -1 { + err = e + } + return +} + +func Fchdir(fd int) (err error) { + path, err := Fd2path(fd) + + if err != nil { + return + } + + return Chdir(path) +} + +type Timespec struct { + Sec int32 + Nsec int32 +} + +type Timeval struct { + Sec int32 + Usec int32 +} + +func NsecToTimeval(nsec int64) (tv Timeval) { + nsec += 999 // round up to microsecond + tv.Usec = int32(nsec % 1e9 / 1e3) + tv.Sec = int32(nsec / 1e9) + return +} + +func nsec() int64 { + var scratch int64 + + r0, _, _ := Syscall(SYS_NSEC, uintptr(unsafe.Pointer(&scratch)), 0, 0) + // TODO(aram): remove hack after I fix _nsec in the pc64 kernel. + if r0 == 0 { + return scratch + } + return int64(r0) +} + +func Gettimeofday(tv *Timeval) error { + nsec := nsec() + *tv = NsecToTimeval(nsec) + return nil +} + +func Getpagesize() int { return 0x1000 } + +func Getegid() (egid int) { return -1 } +func Geteuid() (euid int) { return -1 } +func Getgid() (gid int) { return -1 } +func Getuid() (uid int) { return -1 } + +func Getgroups() (gids []int, err error) { + return make([]int, 0), nil +} + +//sys open(path string, mode int) (fd int, err error) + +func Open(path string, mode int) (fd int, err error) { + fixwd() + return open(path, mode) +} + +//sys create(path string, mode int, perm uint32) (fd int, err error) + +func Create(path string, mode int, perm uint32) (fd int, err error) { + fixwd() + return create(path, mode, perm) +} + +//sys remove(path string) (err error) + +func Remove(path string) error { + fixwd() + return remove(path) +} + +//sys stat(path string, edir []byte) (n int, err error) + +func Stat(path string, edir []byte) (n int, err error) { + fixwd() + return stat(path, edir) +} + +//sys bind(name string, old string, flag int) (err error) + +func Bind(name string, old string, flag int) (err error) { + fixwd() + return bind(name, old, flag) +} + +//sys mount(fd int, afd int, old string, flag int, aname string) (err error) + +func Mount(fd int, afd int, old string, flag int, aname string) (err error) { + fixwd() + return mount(fd, afd, old, flag, aname) +} + +//sys wstat(path string, edir []byte) (err error) + +func Wstat(path string, edir []byte) (err error) { + fixwd() + return wstat(path, edir) +} + +//sys chdir(path string) (err error) +//sys Dup(oldfd int, newfd int) (fd int, err error) +//sys Pread(fd int, p []byte, offset int64) (n int, err error) +//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) +//sys Close(fd int) (err error) +//sys Fstat(fd int, edir []byte) (n int, err error) +//sys Fwstat(fd int, edir []byte) (err error) diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go new file mode 100644 index 00000000..f780d5c8 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_386.go @@ -0,0 +1,284 @@ +// go run mksyscall.go -l32 -plan9 -tags plan9,386 syscall_plan9.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build plan9 && 386 + +package plan9 + +import "unsafe" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fd2path(fd int, buf []byte) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe(p *[2]int32) (err error) { + r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func await(s []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(s) > 0 { + _p0 = unsafe.Pointer(&s[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func open(path string, mode int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func create(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func remove(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func stat(path string, edir []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(edir) > 0 { + _p1 = unsafe.Pointer(&edir[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(name string, old string, flag int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(old) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mount(fd int, afd int, old string, flag int, aname string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(old) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(aname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func wstat(path string, edir []byte) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(edir) > 0 { + _p1 = unsafe.Pointer(&edir[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(oldfd int, newfd int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Close(fd int) (err error) { + r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, edir []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(edir) > 0 { + _p0 = unsafe.Pointer(&edir[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fwstat(fd int, edir []byte) (err error) { + var _p0 unsafe.Pointer + if len(edir) > 0 { + _p0 = unsafe.Pointer(&edir[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) + if int32(r0) == -1 { + err = e1 + } + return +} diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go new file mode 100644 index 00000000..7de61065 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_amd64.go @@ -0,0 +1,284 @@ +// go run mksyscall.go -l32 -plan9 -tags plan9,amd64 syscall_plan9.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build plan9 && amd64 + +package plan9 + +import "unsafe" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fd2path(fd int, buf []byte) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe(p *[2]int32) (err error) { + r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func await(s []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(s) > 0 { + _p0 = unsafe.Pointer(&s[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func open(path string, mode int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func create(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func remove(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func stat(path string, edir []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(edir) > 0 { + _p1 = unsafe.Pointer(&edir[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(name string, old string, flag int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(old) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mount(fd int, afd int, old string, flag int, aname string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(old) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(aname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func wstat(path string, edir []byte) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(edir) > 0 { + _p1 = unsafe.Pointer(&edir[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(oldfd int, newfd int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Close(fd int) (err error) { + r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, edir []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(edir) > 0 { + _p0 = unsafe.Pointer(&edir[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fwstat(fd int, edir []byte) (err error) { + var _p0 unsafe.Pointer + if len(edir) > 0 { + _p0 = unsafe.Pointer(&edir[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) + if int32(r0) == -1 { + err = e1 + } + return +} diff --git a/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go new file mode 100644 index 00000000..ea85780f --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/zsyscall_plan9_arm.go @@ -0,0 +1,284 @@ +// go run mksyscall.go -l32 -plan9 -tags plan9,arm syscall_plan9.go +// Code generated by the command above; see README.md. DO NOT EDIT. + +//go:build plan9 && arm + +package plan9 + +import "unsafe" + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func fd2path(fd int, buf []byte) (err error) { + var _p0 unsafe.Pointer + if len(buf) > 0 { + _p0 = unsafe.Pointer(&buf[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FD2PATH, uintptr(fd), uintptr(_p0), uintptr(len(buf))) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func pipe(p *[2]int32) (err error) { + r0, _, e1 := Syscall(SYS_PIPE, uintptr(unsafe.Pointer(p)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func await(s []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(s) > 0 { + _p0 = unsafe.Pointer(&s[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_AWAIT, uintptr(_p0), uintptr(len(s)), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func open(path string, mode int) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_OPEN, uintptr(unsafe.Pointer(_p0)), uintptr(mode), 0) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func create(path string, mode int, perm uint32) (fd int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_CREATE, uintptr(unsafe.Pointer(_p0)), uintptr(mode), uintptr(perm)) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func remove(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_REMOVE, uintptr(unsafe.Pointer(_p0)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func stat(path string, edir []byte) (n int, err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(edir) > 0 { + _p1 = unsafe.Pointer(&edir[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_STAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func bind(name string, old string, flag int) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(name) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(old) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_BIND, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_p1)), uintptr(flag)) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func mount(fd int, afd int, old string, flag int, aname string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(old) + if err != nil { + return + } + var _p1 *byte + _p1, err = BytePtrFromString(aname) + if err != nil { + return + } + r0, _, e1 := Syscall6(SYS_MOUNT, uintptr(fd), uintptr(afd), uintptr(unsafe.Pointer(_p0)), uintptr(flag), uintptr(unsafe.Pointer(_p1)), 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func wstat(path string, edir []byte) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + var _p1 unsafe.Pointer + if len(edir) > 0 { + _p1 = unsafe.Pointer(&edir[0]) + } else { + _p1 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_WSTAT, uintptr(unsafe.Pointer(_p0)), uintptr(_p1), uintptr(len(edir))) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func chdir(path string) (err error) { + var _p0 *byte + _p0, err = BytePtrFromString(path) + if err != nil { + return + } + r0, _, e1 := Syscall(SYS_CHDIR, uintptr(unsafe.Pointer(_p0)), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Dup(oldfd int, newfd int) (fd int, err error) { + r0, _, e1 := Syscall(SYS_DUP, uintptr(oldfd), uintptr(newfd), 0) + fd = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pread(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PREAD, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Pwrite(fd int, p []byte, offset int64) (n int, err error) { + var _p0 unsafe.Pointer + if len(p) > 0 { + _p0 = unsafe.Pointer(&p[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall6(SYS_PWRITE, uintptr(fd), uintptr(_p0), uintptr(len(p)), uintptr(offset), uintptr(offset>>32), 0) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Close(fd int) (err error) { + r0, _, e1 := Syscall(SYS_CLOSE, uintptr(fd), 0, 0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fstat(fd int, edir []byte) (n int, err error) { + var _p0 unsafe.Pointer + if len(edir) > 0 { + _p0 = unsafe.Pointer(&edir[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) + n = int(r0) + if int32(r0) == -1 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func Fwstat(fd int, edir []byte) (err error) { + var _p0 unsafe.Pointer + if len(edir) > 0 { + _p0 = unsafe.Pointer(&edir[0]) + } else { + _p0 = unsafe.Pointer(&_zero) + } + r0, _, e1 := Syscall(SYS_FWSTAT, uintptr(fd), uintptr(_p0), uintptr(len(edir))) + if int32(r0) == -1 { + err = e1 + } + return +} diff --git a/vendor/golang.org/x/sys/plan9/zsysnum_plan9.go b/vendor/golang.org/x/sys/plan9/zsysnum_plan9.go new file mode 100644 index 00000000..22e8abd4 --- /dev/null +++ b/vendor/golang.org/x/sys/plan9/zsysnum_plan9.go @@ -0,0 +1,49 @@ +// mksysnum_plan9.sh /opt/plan9/sys/src/libc/9syscall/sys.h +// MACHINE GENERATED BY THE ABOVE COMMAND; DO NOT EDIT + +package plan9 + +const ( + SYS_SYSR1 = 0 + SYS_BIND = 2 + SYS_CHDIR = 3 + SYS_CLOSE = 4 + SYS_DUP = 5 + SYS_ALARM = 6 + SYS_EXEC = 7 + SYS_EXITS = 8 + SYS_FAUTH = 10 + SYS_SEGBRK = 12 + SYS_OPEN = 14 + SYS_OSEEK = 16 + SYS_SLEEP = 17 + SYS_RFORK = 19 + SYS_PIPE = 21 + SYS_CREATE = 22 + SYS_FD2PATH = 23 + SYS_BRK_ = 24 + SYS_REMOVE = 25 + SYS_NOTIFY = 28 + SYS_NOTED = 29 + SYS_SEGATTACH = 30 + SYS_SEGDETACH = 31 + SYS_SEGFREE = 32 + SYS_SEGFLUSH = 33 + SYS_RENDEZVOUS = 34 + SYS_UNMOUNT = 35 + SYS_SEMACQUIRE = 37 + SYS_SEMRELEASE = 38 + SYS_SEEK = 39 + SYS_FVERSION = 40 + SYS_ERRSTR = 41 + SYS_STAT = 42 + SYS_FSTAT = 43 + SYS_WSTAT = 44 + SYS_FWSTAT = 45 + SYS_MOUNT = 46 + SYS_AWAIT = 47 + SYS_PREAD = 50 + SYS_PWRITE = 51 + SYS_TSEMACQUIRE = 52 + SYS_NSEC = 53 +) diff --git a/vendor/golang.org/x/term/CONTRIBUTING.md b/vendor/golang.org/x/term/CONTRIBUTING.md new file mode 100644 index 00000000..d0485e88 --- /dev/null +++ b/vendor/golang.org/x/term/CONTRIBUTING.md @@ -0,0 +1,26 @@ +# Contributing to Go + +Go is an open source project. + +It is the work of hundreds of contributors. We appreciate your help! + +## Filing issues + +When [filing an issue](https://golang.org/issue/new), make sure to answer these five questions: + +1. What version of Go are you using (`go version`)? +2. What operating system and processor architecture are you using? +3. What did you do? +4. What did you expect to see? +5. What did you see instead? + +General questions should go to the [golang-nuts mailing list](https://groups.google.com/group/golang-nuts) instead of the issue tracker. +The gophers there will answer or ask you to file an issue if you've tripped over a bug. + +## Contributing code + +Please read the [Contribution Guidelines](https://golang.org/doc/contribute.html) +before sending patches. + +Unless otherwise noted, the Go source files are distributed under +the BSD-style license found in the LICENSE file. diff --git a/vendor/golang.org/x/term/LICENSE b/vendor/golang.org/x/term/LICENSE new file mode 100644 index 00000000..2a7cf70d --- /dev/null +++ b/vendor/golang.org/x/term/LICENSE @@ -0,0 +1,27 @@ +Copyright 2009 The Go Authors. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google LLC nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/golang.org/x/term/PATENTS b/vendor/golang.org/x/term/PATENTS new file mode 100644 index 00000000..73309904 --- /dev/null +++ b/vendor/golang.org/x/term/PATENTS @@ -0,0 +1,22 @@ +Additional IP Rights Grant (Patents) + +"This implementation" means the copyrightable works distributed by +Google as part of the Go project. + +Google hereby grants to You a perpetual, worldwide, non-exclusive, +no-charge, royalty-free, irrevocable (except as stated in this section) +patent license to make, have made, use, offer to sell, sell, import, +transfer and otherwise run, modify and propagate the contents of this +implementation of Go, where such license applies only to those patent +claims, both currently owned or controlled by Google and acquired in +the future, licensable by Google that are necessarily infringed by this +implementation of Go. This grant does not include claims that would be +infringed only as a consequence of further modification of this +implementation. If you or your agent or exclusive licensee institute or +order or agree to the institution of patent litigation against any +entity (including a cross-claim or counterclaim in a lawsuit) alleging +that this implementation of Go or any code incorporated within this +implementation of Go constitutes direct or contributory patent +infringement, or inducement of patent infringement, then any patent +rights granted to you under this License for this implementation of Go +shall terminate as of the date such litigation is filed. diff --git a/vendor/golang.org/x/term/README.md b/vendor/golang.org/x/term/README.md new file mode 100644 index 00000000..05ff623f --- /dev/null +++ b/vendor/golang.org/x/term/README.md @@ -0,0 +1,16 @@ +# Go terminal/console support + +[![Go Reference](https://pkg.go.dev/badge/golang.org/x/term.svg)](https://pkg.go.dev/golang.org/x/term) + +This repository provides Go terminal and console support packages. + +## Report Issues / Send Patches + +This repository uses Gerrit for code changes. To learn how to submit changes to +this repository, see https://go.dev/doc/contribute. + +The git repository is https://go.googlesource.com/term. + +The main issue tracker for the term repository is located at +https://go.dev/issues. Prefix your issue with "x/term:" in the +subject line, so it is easy to find. diff --git a/vendor/golang.org/x/term/codereview.cfg b/vendor/golang.org/x/term/codereview.cfg new file mode 100644 index 00000000..3f8b14b6 --- /dev/null +++ b/vendor/golang.org/x/term/codereview.cfg @@ -0,0 +1 @@ +issuerepo: golang/go diff --git a/vendor/golang.org/x/term/term.go b/vendor/golang.org/x/term/term.go new file mode 100644 index 00000000..1a40d101 --- /dev/null +++ b/vendor/golang.org/x/term/term.go @@ -0,0 +1,60 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package term provides support functions for dealing with terminals, as +// commonly found on UNIX systems. +// +// Putting a terminal into raw mode is the most common requirement: +// +// oldState, err := term.MakeRaw(int(os.Stdin.Fd())) +// if err != nil { +// panic(err) +// } +// defer term.Restore(int(os.Stdin.Fd()), oldState) +// +// Note that on non-Unix systems os.Stdin.Fd() may not be 0. +package term + +// State contains the state of a terminal. +type State struct { + state +} + +// IsTerminal returns whether the given file descriptor is a terminal. +func IsTerminal(fd int) bool { + return isTerminal(fd) +} + +// MakeRaw puts the terminal connected to the given file descriptor into raw +// mode and returns the previous state of the terminal so that it can be +// restored. +func MakeRaw(fd int) (*State, error) { + return makeRaw(fd) +} + +// GetState returns the current state of a terminal which may be useful to +// restore the terminal after a signal. +func GetState(fd int) (*State, error) { + return getState(fd) +} + +// Restore restores the terminal connected to the given file descriptor to a +// previous state. +func Restore(fd int, oldState *State) error { + return restore(fd, oldState) +} + +// GetSize returns the visible dimensions of the given terminal. +// +// These dimensions don't include any scrollback buffer height. +func GetSize(fd int) (width, height int, err error) { + return getSize(fd) +} + +// ReadPassword reads a line of input from a terminal without local echo. This +// is commonly used for inputting passwords and other sensitive data. The slice +// returned does not include the \n. +func ReadPassword(fd int) ([]byte, error) { + return readPassword(fd) +} diff --git a/vendor/golang.org/x/term/term_plan9.go b/vendor/golang.org/x/term/term_plan9.go new file mode 100644 index 00000000..21afa55c --- /dev/null +++ b/vendor/golang.org/x/term/term_plan9.go @@ -0,0 +1,42 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package term + +import ( + "fmt" + "runtime" + + "golang.org/x/sys/plan9" +) + +type state struct{} + +func isTerminal(fd int) bool { + path, err := plan9.Fd2path(fd) + if err != nil { + return false + } + return path == "/dev/cons" || path == "/mnt/term/dev/cons" +} + +func makeRaw(fd int) (*State, error) { + return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func getState(fd int) (*State, error) { + return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func restore(fd int, state *State) error { + return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func getSize(fd int) (width, height int, err error) { + return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func readPassword(fd int) ([]byte, error) { + return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} diff --git a/vendor/golang.org/x/term/term_unix.go b/vendor/golang.org/x/term/term_unix.go new file mode 100644 index 00000000..1ad0ddfe --- /dev/null +++ b/vendor/golang.org/x/term/term_unix.go @@ -0,0 +1,91 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris || zos + +package term + +import ( + "golang.org/x/sys/unix" +) + +type state struct { + termios unix.Termios +} + +func isTerminal(fd int) bool { + _, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + return err == nil +} + +func makeRaw(fd int) (*State, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + oldState := State{state{termios: *termios}} + + // This attempts to replicate the behaviour documented for cfmakeraw in + // the termios(3) manpage. + termios.Iflag &^= unix.IGNBRK | unix.BRKINT | unix.PARMRK | unix.ISTRIP | unix.INLCR | unix.IGNCR | unix.ICRNL | unix.IXON + termios.Oflag &^= unix.OPOST + termios.Lflag &^= unix.ECHO | unix.ECHONL | unix.ICANON | unix.ISIG | unix.IEXTEN + termios.Cflag &^= unix.CSIZE | unix.PARENB + termios.Cflag |= unix.CS8 + termios.Cc[unix.VMIN] = 1 + termios.Cc[unix.VTIME] = 0 + if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, termios); err != nil { + return nil, err + } + + return &oldState, nil +} + +func getState(fd int) (*State, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + return &State{state{termios: *termios}}, nil +} + +func restore(fd int, state *State) error { + return unix.IoctlSetTermios(fd, ioctlWriteTermios, &state.termios) +} + +func getSize(fd int) (width, height int, err error) { + ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ) + if err != nil { + return 0, 0, err + } + return int(ws.Col), int(ws.Row), nil +} + +// passwordReader is an io.Reader that reads from a specific file descriptor. +type passwordReader int + +func (r passwordReader) Read(buf []byte) (int, error) { + return unix.Read(int(r), buf) +} + +func readPassword(fd int) ([]byte, error) { + termios, err := unix.IoctlGetTermios(fd, ioctlReadTermios) + if err != nil { + return nil, err + } + + newState := *termios + newState.Lflag &^= unix.ECHO + newState.Lflag |= unix.ICANON | unix.ISIG + newState.Iflag |= unix.ICRNL + if err := unix.IoctlSetTermios(fd, ioctlWriteTermios, &newState); err != nil { + return nil, err + } + + defer unix.IoctlSetTermios(fd, ioctlWriteTermios, termios) + + return readPasswordLine(passwordReader(fd)) +} diff --git a/vendor/golang.org/x/term/term_unix_bsd.go b/vendor/golang.org/x/term/term_unix_bsd.go new file mode 100644 index 00000000..9dbf5462 --- /dev/null +++ b/vendor/golang.org/x/term/term_unix_bsd.go @@ -0,0 +1,12 @@ +// Copyright 2013 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build darwin || dragonfly || freebsd || netbsd || openbsd + +package term + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TIOCGETA +const ioctlWriteTermios = unix.TIOCSETA diff --git a/vendor/golang.org/x/term/term_unix_other.go b/vendor/golang.org/x/term/term_unix_other.go new file mode 100644 index 00000000..1b36de79 --- /dev/null +++ b/vendor/golang.org/x/term/term_unix_other.go @@ -0,0 +1,12 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build aix || linux || solaris || zos + +package term + +import "golang.org/x/sys/unix" + +const ioctlReadTermios = unix.TCGETS +const ioctlWriteTermios = unix.TCSETS diff --git a/vendor/golang.org/x/term/term_unsupported.go b/vendor/golang.org/x/term/term_unsupported.go new file mode 100644 index 00000000..3c409e58 --- /dev/null +++ b/vendor/golang.org/x/term/term_unsupported.go @@ -0,0 +1,38 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !aix && !darwin && !dragonfly && !freebsd && !linux && !netbsd && !openbsd && !zos && !windows && !solaris && !plan9 + +package term + +import ( + "fmt" + "runtime" +) + +type state struct{} + +func isTerminal(fd int) bool { + return false +} + +func makeRaw(fd int) (*State, error) { + return nil, fmt.Errorf("terminal: MakeRaw not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func getState(fd int) (*State, error) { + return nil, fmt.Errorf("terminal: GetState not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func restore(fd int, state *State) error { + return fmt.Errorf("terminal: Restore not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func getSize(fd int) (width, height int, err error) { + return 0, 0, fmt.Errorf("terminal: GetSize not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} + +func readPassword(fd int) ([]byte, error) { + return nil, fmt.Errorf("terminal: ReadPassword not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) +} diff --git a/vendor/golang.org/x/term/term_windows.go b/vendor/golang.org/x/term/term_windows.go new file mode 100644 index 00000000..df6bf948 --- /dev/null +++ b/vendor/golang.org/x/term/term_windows.go @@ -0,0 +1,80 @@ +// Copyright 2019 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package term + +import ( + "os" + + "golang.org/x/sys/windows" +) + +type state struct { + mode uint32 +} + +func isTerminal(fd int) bool { + var st uint32 + err := windows.GetConsoleMode(windows.Handle(fd), &st) + return err == nil +} + +func makeRaw(fd int) (*State, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + raw := st &^ (windows.ENABLE_ECHO_INPUT | windows.ENABLE_PROCESSED_INPUT | windows.ENABLE_LINE_INPUT | windows.ENABLE_PROCESSED_OUTPUT) + raw |= windows.ENABLE_VIRTUAL_TERMINAL_INPUT + if err := windows.SetConsoleMode(windows.Handle(fd), raw); err != nil { + return nil, err + } + return &State{state{st}}, nil +} + +func getState(fd int) (*State, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + return &State{state{st}}, nil +} + +func restore(fd int, state *State) error { + return windows.SetConsoleMode(windows.Handle(fd), state.mode) +} + +func getSize(fd int) (width, height int, err error) { + var info windows.ConsoleScreenBufferInfo + if err := windows.GetConsoleScreenBufferInfo(windows.Handle(fd), &info); err != nil { + return 0, 0, err + } + return int(info.Window.Right - info.Window.Left + 1), int(info.Window.Bottom - info.Window.Top + 1), nil +} + +func readPassword(fd int) ([]byte, error) { + var st uint32 + if err := windows.GetConsoleMode(windows.Handle(fd), &st); err != nil { + return nil, err + } + old := st + + st &^= (windows.ENABLE_ECHO_INPUT | windows.ENABLE_LINE_INPUT) + st |= (windows.ENABLE_PROCESSED_OUTPUT | windows.ENABLE_PROCESSED_INPUT) + if err := windows.SetConsoleMode(windows.Handle(fd), st); err != nil { + return nil, err + } + + defer windows.SetConsoleMode(windows.Handle(fd), old) + + var h windows.Handle + p, _ := windows.GetCurrentProcess() + if err := windows.DuplicateHandle(p, windows.Handle(fd), p, &h, 0, false, windows.DUPLICATE_SAME_ACCESS); err != nil { + return nil, err + } + + f := os.NewFile(uintptr(h), "stdin") + defer f.Close() + return readPasswordLine(f) +} diff --git a/vendor/golang.org/x/term/terminal.go b/vendor/golang.org/x/term/terminal.go new file mode 100644 index 00000000..13e9a64a --- /dev/null +++ b/vendor/golang.org/x/term/terminal.go @@ -0,0 +1,1043 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package term + +import ( + "bytes" + "fmt" + "io" + "runtime" + "strconv" + "sync" + "unicode/utf8" +) + +// EscapeCodes contains escape sequences that can be written to the terminal in +// order to achieve different styles of text. +type EscapeCodes struct { + // Foreground colors + Black, Red, Green, Yellow, Blue, Magenta, Cyan, White []byte + + // Reset all attributes + Reset []byte +} + +var vt100EscapeCodes = EscapeCodes{ + Black: []byte{keyEscape, '[', '3', '0', 'm'}, + Red: []byte{keyEscape, '[', '3', '1', 'm'}, + Green: []byte{keyEscape, '[', '3', '2', 'm'}, + Yellow: []byte{keyEscape, '[', '3', '3', 'm'}, + Blue: []byte{keyEscape, '[', '3', '4', 'm'}, + Magenta: []byte{keyEscape, '[', '3', '5', 'm'}, + Cyan: []byte{keyEscape, '[', '3', '6', 'm'}, + White: []byte{keyEscape, '[', '3', '7', 'm'}, + + Reset: []byte{keyEscape, '[', '0', 'm'}, +} + +// A History provides a (possibly bounded) queue of input lines read by [Terminal.ReadLine]. +type History interface { + // Add will be called by [Terminal.ReadLine] to add + // a new, most recent entry to the history. + // It is allowed to drop any entry, including + // the entry being added (e.g., if it's deemed an invalid entry), + // the least-recent entry (e.g., to keep the history bounded), + // or any other entry. + Add(entry string) + + // Len returns the number of entries in the history. + Len() int + + // At returns an entry from the history. + // Index 0 is the most-recently added entry and + // index Len()-1 is the least-recently added entry. + // If index is < 0 or >= Len(), it panics. + At(idx int) string +} + +// Terminal contains the state for running a VT100 terminal that is capable of +// reading lines of input. +type Terminal struct { + // AutoCompleteCallback, if non-null, is called for each keypress with + // the full input line and the current position of the cursor (in + // bytes, as an index into |line|). If it returns ok=false, the key + // press is processed normally. Otherwise it returns a replacement line + // and the new cursor position. + // + // This will be disabled during ReadPassword. + AutoCompleteCallback func(line string, pos int, key rune) (newLine string, newPos int, ok bool) + + // Escape contains a pointer to the escape codes for this terminal. + // It's always a valid pointer, although the escape codes themselves + // may be empty if the terminal doesn't support them. + Escape *EscapeCodes + + // lock protects the terminal and the state in this object from + // concurrent processing of a key press and a Write() call. + lock sync.Mutex + + c io.ReadWriter + prompt []rune + + // line is the current line being entered. + line []rune + // pos is the logical position of the cursor in line + pos int + // echo is true if local echo is enabled + echo bool + // pasteActive is true iff there is a bracketed paste operation in + // progress. + pasteActive bool + + // cursorX contains the current X value of the cursor where the left + // edge is 0. cursorY contains the row number where the first row of + // the current line is 0. + cursorX, cursorY int + // maxLine is the greatest value of cursorY so far. + maxLine int + + termWidth, termHeight int + + // outBuf contains the terminal data to be sent. + outBuf []byte + // remainder contains the remainder of any partial key sequences after + // a read. It aliases into inBuf. + remainder []byte + inBuf [256]byte + + // History records and retrieves lines of input read by [ReadLine] which + // a user can retrieve and navigate using the up and down arrow keys. + // + // It is not safe to call ReadLine concurrently with any methods on History. + // + // [NewTerminal] sets this to a default implementation that records the + // last 100 lines of input. + History History + // historyIndex stores the currently accessed history entry, where zero + // means the immediately previous entry. + historyIndex int + // When navigating up and down the history it's possible to return to + // the incomplete, initial line. That value is stored in + // historyPending. + historyPending string +} + +// NewTerminal runs a VT100 terminal on the given ReadWriter. If the ReadWriter is +// a local terminal, that terminal must first have been put into raw mode. +// prompt is a string that is written at the start of each input line (i.e. +// "> "). +func NewTerminal(c io.ReadWriter, prompt string) *Terminal { + return &Terminal{ + Escape: &vt100EscapeCodes, + c: c, + prompt: []rune(prompt), + termWidth: 80, + termHeight: 24, + echo: true, + historyIndex: -1, + History: &stRingBuffer{}, + } +} + +const ( + keyCtrlC = 3 + keyCtrlD = 4 + keyCtrlU = 21 + keyEnter = '\r' + keyEscape = 27 + keyBackspace = 127 + keyUnknown = 0xd800 /* UTF-16 surrogate area */ + iota + keyUp + keyDown + keyLeft + keyRight + keyAltLeft + keyAltRight + keyHome + keyEnd + keyDeleteWord + keyDeleteLine + keyClearScreen + keyPasteStart + keyPasteEnd +) + +var ( + crlf = []byte{'\r', '\n'} + pasteStart = []byte{keyEscape, '[', '2', '0', '0', '~'} + pasteEnd = []byte{keyEscape, '[', '2', '0', '1', '~'} +) + +// bytesToKey tries to parse a key sequence from b. If successful, it returns +// the key and the remainder of the input. Otherwise it returns utf8.RuneError. +func bytesToKey(b []byte, pasteActive bool) (rune, []byte) { + if len(b) == 0 { + return utf8.RuneError, nil + } + + if !pasteActive { + switch b[0] { + case 1: // ^A + return keyHome, b[1:] + case 2: // ^B + return keyLeft, b[1:] + case 5: // ^E + return keyEnd, b[1:] + case 6: // ^F + return keyRight, b[1:] + case 8: // ^H + return keyBackspace, b[1:] + case 11: // ^K + return keyDeleteLine, b[1:] + case 12: // ^L + return keyClearScreen, b[1:] + case 23: // ^W + return keyDeleteWord, b[1:] + case 14: // ^N + return keyDown, b[1:] + case 16: // ^P + return keyUp, b[1:] + } + } + + if b[0] != keyEscape { + if !utf8.FullRune(b) { + return utf8.RuneError, b + } + r, l := utf8.DecodeRune(b) + return r, b[l:] + } + + if !pasteActive && len(b) >= 3 && b[0] == keyEscape && b[1] == '[' { + switch b[2] { + case 'A': + return keyUp, b[3:] + case 'B': + return keyDown, b[3:] + case 'C': + return keyRight, b[3:] + case 'D': + return keyLeft, b[3:] + case 'H': + return keyHome, b[3:] + case 'F': + return keyEnd, b[3:] + } + } + + if !pasteActive && len(b) >= 6 && b[0] == keyEscape && b[1] == '[' && b[2] == '1' && b[3] == ';' && b[4] == '3' { + switch b[5] { + case 'C': + return keyAltRight, b[6:] + case 'D': + return keyAltLeft, b[6:] + } + } + + if !pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteStart) { + return keyPasteStart, b[6:] + } + + if pasteActive && len(b) >= 6 && bytes.Equal(b[:6], pasteEnd) { + return keyPasteEnd, b[6:] + } + + // If we get here then we have a key that we don't recognise, or a + // partial sequence. It's not clear how one should find the end of a + // sequence without knowing them all, but it seems that [a-zA-Z~] only + // appears at the end of a sequence. + for i, c := range b[0:] { + if c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '~' { + return keyUnknown, b[i+1:] + } + } + + return utf8.RuneError, b +} + +// queue appends data to the end of t.outBuf +func (t *Terminal) queue(data []rune) { + t.outBuf = append(t.outBuf, []byte(string(data))...) +} + +var space = []rune{' '} + +func isPrintable(key rune) bool { + isInSurrogateArea := key >= 0xd800 && key <= 0xdbff + return key >= 32 && !isInSurrogateArea +} + +// moveCursorToPos appends data to t.outBuf which will move the cursor to the +// given, logical position in the text. +func (t *Terminal) moveCursorToPos(pos int) { + if !t.echo { + return + } + + x := visualLength(t.prompt) + pos + y := x / t.termWidth + x = x % t.termWidth + + up := 0 + if y < t.cursorY { + up = t.cursorY - y + } + + down := 0 + if y > t.cursorY { + down = y - t.cursorY + } + + left := 0 + if x < t.cursorX { + left = t.cursorX - x + } + + right := 0 + if x > t.cursorX { + right = x - t.cursorX + } + + t.cursorX = x + t.cursorY = y + t.move(up, down, left, right) +} + +func (t *Terminal) move(up, down, left, right int) { + m := []rune{} + + // 1 unit up can be expressed as ^[[A or ^[A + // 5 units up can be expressed as ^[[5A + + if up == 1 { + m = append(m, keyEscape, '[', 'A') + } else if up > 1 { + m = append(m, keyEscape, '[') + m = append(m, []rune(strconv.Itoa(up))...) + m = append(m, 'A') + } + + if down == 1 { + m = append(m, keyEscape, '[', 'B') + } else if down > 1 { + m = append(m, keyEscape, '[') + m = append(m, []rune(strconv.Itoa(down))...) + m = append(m, 'B') + } + + if right == 1 { + m = append(m, keyEscape, '[', 'C') + } else if right > 1 { + m = append(m, keyEscape, '[') + m = append(m, []rune(strconv.Itoa(right))...) + m = append(m, 'C') + } + + if left == 1 { + m = append(m, keyEscape, '[', 'D') + } else if left > 1 { + m = append(m, keyEscape, '[') + m = append(m, []rune(strconv.Itoa(left))...) + m = append(m, 'D') + } + + t.queue(m) +} + +func (t *Terminal) clearLineToRight() { + op := []rune{keyEscape, '[', 'K'} + t.queue(op) +} + +const maxLineLength = 4096 + +func (t *Terminal) setLine(newLine []rune, newPos int) { + if t.echo { + t.moveCursorToPos(0) + t.writeLine(newLine) + for i := len(newLine); i < len(t.line); i++ { + t.writeLine(space) + } + t.moveCursorToPos(newPos) + } + t.line = newLine + t.pos = newPos +} + +func (t *Terminal) advanceCursor(places int) { + t.cursorX += places + t.cursorY += t.cursorX / t.termWidth + if t.cursorY > t.maxLine { + t.maxLine = t.cursorY + } + t.cursorX = t.cursorX % t.termWidth + + if places > 0 && t.cursorX == 0 { + // Normally terminals will advance the current position + // when writing a character. But that doesn't happen + // for the last character in a line. However, when + // writing a character (except a new line) that causes + // a line wrap, the position will be advanced two + // places. + // + // So, if we are stopping at the end of a line, we + // need to write a newline so that our cursor can be + // advanced to the next line. + t.outBuf = append(t.outBuf, '\r', '\n') + } +} + +func (t *Terminal) eraseNPreviousChars(n int) { + if n == 0 { + return + } + + if t.pos < n { + n = t.pos + } + t.pos -= n + t.moveCursorToPos(t.pos) + + copy(t.line[t.pos:], t.line[n+t.pos:]) + t.line = t.line[:len(t.line)-n] + if t.echo { + t.writeLine(t.line[t.pos:]) + for i := 0; i < n; i++ { + t.queue(space) + } + t.advanceCursor(n) + t.moveCursorToPos(t.pos) + } +} + +// countToLeftWord returns then number of characters from the cursor to the +// start of the previous word. +func (t *Terminal) countToLeftWord() int { + if t.pos == 0 { + return 0 + } + + pos := t.pos - 1 + for pos > 0 { + if t.line[pos] != ' ' { + break + } + pos-- + } + for pos > 0 { + if t.line[pos] == ' ' { + pos++ + break + } + pos-- + } + + return t.pos - pos +} + +// countToRightWord returns then number of characters from the cursor to the +// start of the next word. +func (t *Terminal) countToRightWord() int { + pos := t.pos + for pos < len(t.line) { + if t.line[pos] == ' ' { + break + } + pos++ + } + for pos < len(t.line) { + if t.line[pos] != ' ' { + break + } + pos++ + } + return pos - t.pos +} + +// visualLength returns the number of visible glyphs in s. +func visualLength(runes []rune) int { + inEscapeSeq := false + length := 0 + + for _, r := range runes { + switch { + case inEscapeSeq: + if (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') { + inEscapeSeq = false + } + case r == '\x1b': + inEscapeSeq = true + default: + length++ + } + } + + return length +} + +// histroryAt unlocks the terminal and relocks it while calling History.At. +func (t *Terminal) historyAt(idx int) (string, bool) { + t.lock.Unlock() // Unlock to avoid deadlock if History methods use the output writer. + defer t.lock.Lock() // panic in At (or Len) protection. + if idx < 0 || idx >= t.History.Len() { + return "", false + } + return t.History.At(idx), true +} + +// historyAdd unlocks the terminal and relocks it while calling History.Add. +func (t *Terminal) historyAdd(entry string) { + t.lock.Unlock() // Unlock to avoid deadlock if History methods use the output writer. + defer t.lock.Lock() // panic in Add protection. + t.History.Add(entry) +} + +// handleKey processes the given key and, optionally, returns a line of text +// that the user has entered. +func (t *Terminal) handleKey(key rune) (line string, ok bool) { + if t.pasteActive && key != keyEnter { + t.addKeyToLine(key) + return + } + + switch key { + case keyBackspace: + if t.pos == 0 { + return + } + t.eraseNPreviousChars(1) + case keyAltLeft: + // move left by a word. + t.pos -= t.countToLeftWord() + t.moveCursorToPos(t.pos) + case keyAltRight: + // move right by a word. + t.pos += t.countToRightWord() + t.moveCursorToPos(t.pos) + case keyLeft: + if t.pos == 0 { + return + } + t.pos-- + t.moveCursorToPos(t.pos) + case keyRight: + if t.pos == len(t.line) { + return + } + t.pos++ + t.moveCursorToPos(t.pos) + case keyHome: + if t.pos == 0 { + return + } + t.pos = 0 + t.moveCursorToPos(t.pos) + case keyEnd: + if t.pos == len(t.line) { + return + } + t.pos = len(t.line) + t.moveCursorToPos(t.pos) + case keyUp: + entry, ok := t.historyAt(t.historyIndex + 1) + if !ok { + return "", false + } + if t.historyIndex == -1 { + t.historyPending = string(t.line) + } + t.historyIndex++ + runes := []rune(entry) + t.setLine(runes, len(runes)) + case keyDown: + switch t.historyIndex { + case -1: + return + case 0: + runes := []rune(t.historyPending) + t.setLine(runes, len(runes)) + t.historyIndex-- + default: + entry, ok := t.historyAt(t.historyIndex - 1) + if ok { + t.historyIndex-- + runes := []rune(entry) + t.setLine(runes, len(runes)) + } + } + case keyEnter: + t.moveCursorToPos(len(t.line)) + t.queue([]rune("\r\n")) + line = string(t.line) + ok = true + t.line = t.line[:0] + t.pos = 0 + t.cursorX = 0 + t.cursorY = 0 + t.maxLine = 0 + case keyDeleteWord: + // Delete zero or more spaces and then one or more characters. + t.eraseNPreviousChars(t.countToLeftWord()) + case keyDeleteLine: + // Delete everything from the current cursor position to the + // end of line. + for i := t.pos; i < len(t.line); i++ { + t.queue(space) + t.advanceCursor(1) + } + t.line = t.line[:t.pos] + t.moveCursorToPos(t.pos) + case keyCtrlD: + // Erase the character under the current position. + // The EOF case when the line is empty is handled in + // readLine(). + if t.pos < len(t.line) { + t.pos++ + t.eraseNPreviousChars(1) + } + case keyCtrlU: + t.eraseNPreviousChars(t.pos) + case keyClearScreen: + // Erases the screen and moves the cursor to the home position. + t.queue([]rune("\x1b[2J\x1b[H")) + t.queue(t.prompt) + t.cursorX, t.cursorY = 0, 0 + t.advanceCursor(visualLength(t.prompt)) + t.setLine(t.line, t.pos) + default: + if t.AutoCompleteCallback != nil { + prefix := string(t.line[:t.pos]) + suffix := string(t.line[t.pos:]) + + t.lock.Unlock() + newLine, newPos, completeOk := t.AutoCompleteCallback(prefix+suffix, len(prefix), key) + t.lock.Lock() + + if completeOk { + t.setLine([]rune(newLine), utf8.RuneCount([]byte(newLine)[:newPos])) + return + } + } + if !isPrintable(key) { + return + } + if len(t.line) == maxLineLength { + return + } + t.addKeyToLine(key) + } + return +} + +// addKeyToLine inserts the given key at the current position in the current +// line. +func (t *Terminal) addKeyToLine(key rune) { + if len(t.line) == cap(t.line) { + newLine := make([]rune, len(t.line), 2*(1+len(t.line))) + copy(newLine, t.line) + t.line = newLine + } + t.line = t.line[:len(t.line)+1] + copy(t.line[t.pos+1:], t.line[t.pos:]) + t.line[t.pos] = key + if t.echo { + t.writeLine(t.line[t.pos:]) + } + t.pos++ + t.moveCursorToPos(t.pos) +} + +func (t *Terminal) writeLine(line []rune) { + for len(line) != 0 { + remainingOnLine := t.termWidth - t.cursorX + todo := len(line) + if todo > remainingOnLine { + todo = remainingOnLine + } + t.queue(line[:todo]) + t.advanceCursor(visualLength(line[:todo])) + line = line[todo:] + } +} + +// writeWithCRLF writes buf to w but replaces all occurrences of \n with \r\n. +func writeWithCRLF(w io.Writer, buf []byte) (n int, err error) { + for len(buf) > 0 { + i := bytes.IndexByte(buf, '\n') + todo := len(buf) + if i >= 0 { + todo = i + } + + var nn int + nn, err = w.Write(buf[:todo]) + n += nn + if err != nil { + return n, err + } + buf = buf[todo:] + + if i >= 0 { + if _, err = w.Write(crlf); err != nil { + return n, err + } + n++ + buf = buf[1:] + } + } + + return n, nil +} + +func (t *Terminal) Write(buf []byte) (n int, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + if t.cursorX == 0 && t.cursorY == 0 { + // This is the easy case: there's nothing on the screen that we + // have to move out of the way. + return writeWithCRLF(t.c, buf) + } + + // We have a prompt and possibly user input on the screen. We + // have to clear it first. + t.move(0 /* up */, 0 /* down */, t.cursorX /* left */, 0 /* right */) + t.cursorX = 0 + t.clearLineToRight() + + for t.cursorY > 0 { + t.move(1 /* up */, 0, 0, 0) + t.cursorY-- + t.clearLineToRight() + } + + if _, err = t.c.Write(t.outBuf); err != nil { + return + } + t.outBuf = t.outBuf[:0] + + if n, err = writeWithCRLF(t.c, buf); err != nil { + return + } + + t.writeLine(t.prompt) + if t.echo { + t.writeLine(t.line) + } + + t.moveCursorToPos(t.pos) + + if _, err = t.c.Write(t.outBuf); err != nil { + return + } + t.outBuf = t.outBuf[:0] + return +} + +// ReadPassword temporarily changes the prompt and reads a password, without +// echo, from the terminal. +// +// The AutoCompleteCallback is disabled during this call. +func (t *Terminal) ReadPassword(prompt string) (line string, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + oldPrompt := t.prompt + t.prompt = []rune(prompt) + t.echo = false + oldAutoCompleteCallback := t.AutoCompleteCallback + t.AutoCompleteCallback = nil + defer func() { + t.AutoCompleteCallback = oldAutoCompleteCallback + }() + + line, err = t.readLine() + + t.prompt = oldPrompt + t.echo = true + + return +} + +// ReadLine returns a line of input from the terminal. +func (t *Terminal) ReadLine() (line string, err error) { + t.lock.Lock() + defer t.lock.Unlock() + + return t.readLine() +} + +func (t *Terminal) readLine() (line string, err error) { + // t.lock must be held at this point + + if t.cursorX == 0 && t.cursorY == 0 { + t.writeLine(t.prompt) + t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + } + + lineIsPasted := t.pasteActive + + for { + rest := t.remainder + lineOk := false + for !lineOk { + var key rune + key, rest = bytesToKey(rest, t.pasteActive) + if key == utf8.RuneError { + break + } + if !t.pasteActive { + if key == keyCtrlD { + if len(t.line) == 0 { + return "", io.EOF + } + } + if key == keyCtrlC { + return "", io.EOF + } + if key == keyPasteStart { + t.pasteActive = true + if len(t.line) == 0 { + lineIsPasted = true + } + continue + } + } else if key == keyPasteEnd { + t.pasteActive = false + continue + } + if !t.pasteActive { + lineIsPasted = false + } + line, lineOk = t.handleKey(key) + } + if len(rest) > 0 { + n := copy(t.inBuf[:], rest) + t.remainder = t.inBuf[:n] + } else { + t.remainder = nil + } + t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + if lineOk { + if t.echo { + t.historyIndex = -1 + t.historyAdd(line) + } + if lineIsPasted { + err = ErrPasteIndicator + } + return + } + + // t.remainder is a slice at the beginning of t.inBuf + // containing a partial key sequence + readBuf := t.inBuf[len(t.remainder):] + var n int + + t.lock.Unlock() + n, err = t.c.Read(readBuf) + t.lock.Lock() + + if err != nil { + return + } + + t.remainder = t.inBuf[:n+len(t.remainder)] + } +} + +// SetPrompt sets the prompt to be used when reading subsequent lines. +func (t *Terminal) SetPrompt(prompt string) { + t.lock.Lock() + defer t.lock.Unlock() + + t.prompt = []rune(prompt) +} + +func (t *Terminal) clearAndRepaintLinePlusNPrevious(numPrevLines int) { + // Move cursor to column zero at the start of the line. + t.move(t.cursorY, 0, t.cursorX, 0) + t.cursorX, t.cursorY = 0, 0 + t.clearLineToRight() + for t.cursorY < numPrevLines { + // Move down a line + t.move(0, 1, 0, 0) + t.cursorY++ + t.clearLineToRight() + } + // Move back to beginning. + t.move(t.cursorY, 0, 0, 0) + t.cursorX, t.cursorY = 0, 0 + + t.queue(t.prompt) + t.advanceCursor(visualLength(t.prompt)) + t.writeLine(t.line) + t.moveCursorToPos(t.pos) +} + +func (t *Terminal) SetSize(width, height int) error { + t.lock.Lock() + defer t.lock.Unlock() + + if width == 0 { + width = 1 + } + + oldWidth := t.termWidth + t.termWidth, t.termHeight = width, height + + switch { + case width == oldWidth: + // If the width didn't change then nothing else needs to be + // done. + return nil + case len(t.line) == 0 && t.cursorX == 0 && t.cursorY == 0: + // If there is nothing on current line and no prompt printed, + // just do nothing + return nil + case width < oldWidth: + // Some terminals (e.g. xterm) will truncate lines that were + // too long when shinking. Others, (e.g. gnome-terminal) will + // attempt to wrap them. For the former, repainting t.maxLine + // works great, but that behaviour goes badly wrong in the case + // of the latter because they have doubled every full line. + + // We assume that we are working on a terminal that wraps lines + // and adjust the cursor position based on every previous line + // wrapping and turning into two. This causes the prompt on + // xterms to move upwards, which isn't great, but it avoids a + // huge mess with gnome-terminal. + if t.cursorX >= t.termWidth { + t.cursorX = t.termWidth - 1 + } + t.cursorY *= 2 + t.clearAndRepaintLinePlusNPrevious(t.maxLine * 2) + case width > oldWidth: + // If the terminal expands then our position calculations will + // be wrong in the future because we think the cursor is + // |t.pos| chars into the string, but there will be a gap at + // the end of any wrapped line. + // + // But the position will actually be correct until we move, so + // we can move back to the beginning and repaint everything. + t.clearAndRepaintLinePlusNPrevious(t.maxLine) + } + + _, err := t.c.Write(t.outBuf) + t.outBuf = t.outBuf[:0] + return err +} + +type pasteIndicatorError struct{} + +func (pasteIndicatorError) Error() string { + return "terminal: ErrPasteIndicator not correctly handled" +} + +// ErrPasteIndicator may be returned from ReadLine as the error, in addition +// to valid line data. It indicates that bracketed paste mode is enabled and +// that the returned line consists only of pasted data. Programs may wish to +// interpret pasted data more literally than typed data. +var ErrPasteIndicator = pasteIndicatorError{} + +// SetBracketedPasteMode requests that the terminal bracket paste operations +// with markers. Not all terminals support this but, if it is supported, then +// enabling this mode will stop any autocomplete callback from running due to +// pastes. Additionally, any lines that are completely pasted will be returned +// from ReadLine with the error set to ErrPasteIndicator. +func (t *Terminal) SetBracketedPasteMode(on bool) { + if on { + io.WriteString(t.c, "\x1b[?2004h") + } else { + io.WriteString(t.c, "\x1b[?2004l") + } +} + +// stRingBuffer is a ring buffer of strings. +type stRingBuffer struct { + // entries contains max elements. + entries []string + max int + // head contains the index of the element most recently added to the ring. + head int + // size contains the number of elements in the ring. + size int +} + +func (s *stRingBuffer) Add(a string) { + if s.entries == nil { + const defaultNumEntries = 100 + s.entries = make([]string, defaultNumEntries) + s.max = defaultNumEntries + } + + s.head = (s.head + 1) % s.max + s.entries[s.head] = a + if s.size < s.max { + s.size++ + } +} + +func (s *stRingBuffer) Len() int { + return s.size +} + +// At returns the value passed to the nth previous call to Add. +// If n is zero then the immediately prior value is returned, if one, then the +// next most recent, and so on. If such an element doesn't exist then ok is +// false. +func (s *stRingBuffer) At(n int) string { + if n < 0 || n >= s.size { + panic(fmt.Sprintf("term: history index [%d] out of range [0,%d)", n, s.size)) + } + index := s.head - n + if index < 0 { + index += s.max + } + return s.entries[index] +} + +// readPasswordLine reads from reader until it finds \n or io.EOF. +// The slice returned does not include the \n. +// readPasswordLine also ignores any \r it finds. +// Windows uses \r as end of line. So, on Windows, readPasswordLine +// reads until it finds \r and ignores any \n it finds during processing. +func readPasswordLine(reader io.Reader) ([]byte, error) { + var buf [1]byte + var ret []byte + + for { + n, err := reader.Read(buf[:]) + if n > 0 { + switch buf[0] { + case '\b': + if len(ret) > 0 { + ret = ret[:len(ret)-1] + } + case '\n': + if runtime.GOOS != "windows" { + return ret, nil + } + // otherwise ignore \n + case '\r': + if runtime.GOOS == "windows" { + return ret, nil + } + // otherwise ignore \r + default: + ret = append(ret, buf[0]) + } + continue + } + if err != nil { + if err == io.EOF && len(ret) > 0 { + return ret, nil + } + return ret, err + } + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index ae89577c..d8f70102 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -12,9 +12,41 @@ github.com/Microsoft/go-winio/pkg/guid # github.com/StackExchange/wmi v1.2.1 ## explicit; go 1.13 github.com/StackExchange/wmi +# github.com/atotto/clipboard v0.1.4 +## explicit +github.com/atotto/clipboard +# github.com/aymanbagabas/go-osc52/v2 v2.0.1 +## explicit; go 1.16 +github.com/aymanbagabas/go-osc52/v2 # github.com/cenkalti/backoff/v4 v4.3.0 ## explicit; go 1.18 github.com/cenkalti/backoff/v4 +# github.com/charmbracelet/bubbles v0.21.0 +## explicit; go 1.23.0 +github.com/charmbracelet/bubbles/cursor +github.com/charmbracelet/bubbles/key +github.com/charmbracelet/bubbles/runeutil +github.com/charmbracelet/bubbles/textinput +# github.com/charmbracelet/bubbletea v1.3.6 +## explicit; go 1.23.0 +github.com/charmbracelet/bubbletea +# github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc +## explicit; go 1.18 +github.com/charmbracelet/colorprofile +# github.com/charmbracelet/lipgloss v1.1.0 +## explicit; go 1.18 +github.com/charmbracelet/lipgloss +# github.com/charmbracelet/x/ansi v0.9.3 +## explicit; go 1.23.0 +github.com/charmbracelet/x/ansi +github.com/charmbracelet/x/ansi/kitty +github.com/charmbracelet/x/ansi/parser +# github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd +## explicit; go 1.18 +github.com/charmbracelet/x/cellbuf +# github.com/charmbracelet/x/term v0.2.1 +## explicit; go 1.18 +github.com/charmbracelet/x/term # github.com/containerd/containerd/v2 v2.1.3 ## explicit; go 1.23.0 github.com/containerd/containerd/v2/core/content @@ -187,6 +219,9 @@ github.com/elastic/go-sysinfo/types # github.com/elastic/go-windows v1.0.2 ## explicit; go 1.18 github.com/elastic/go-windows +# github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f +## explicit; go 1.16 +github.com/erikgeiser/coninput # github.com/fatih/color v1.15.0 ## explicit; go 1.17 github.com/fatih/color @@ -309,12 +344,18 @@ github.com/klauspost/compress/internal/le github.com/klauspost/compress/internal/snapref github.com/klauspost/compress/zstd github.com/klauspost/compress/zstd/internal/xxhash +# github.com/lucasb-eyer/go-colorful v1.2.0 +## explicit; go 1.12 +github.com/lucasb-eyer/go-colorful # github.com/mattn/go-colorable v0.1.13 ## explicit; go 1.15 github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.20 ## explicit; go 1.15 github.com/mattn/go-isatty +# github.com/mattn/go-localereader v0.0.1 +## explicit +github.com/mattn/go-localereader # github.com/mattn/go-runewidth v0.0.16 ## explicit; go 1.9 github.com/mattn/go-runewidth @@ -349,6 +390,16 @@ github.com/modern-go/reflect2 # github.com/morikuni/aec v1.0.0 ## explicit github.com/morikuni/aec +# github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 +## explicit; go 1.17 +github.com/muesli/ansi +github.com/muesli/ansi/compressor +# github.com/muesli/cancelreader v0.2.2 +## explicit; go 1.17 +github.com/muesli/cancelreader +# github.com/muesli/termenv v0.16.0 +## explicit; go 1.17 +github.com/muesli/termenv # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 ## explicit github.com/munnerz/goautoneg @@ -419,6 +470,9 @@ github.com/stretchr/testify/require # github.com/vbatts/tar-split v0.12.1 ## explicit; go 1.17 github.com/vbatts/tar-split/archive/tar +# github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e +## explicit; go 1.19 +github.com/xo/terminfo # go.opentelemetry.io/auto/sdk v1.1.0 ## explicit; go 1.22.0 go.opentelemetry.io/auto/sdk @@ -501,6 +555,9 @@ go.opentelemetry.io/proto/otlp/trace/v1 # go.uber.org/mock v0.5.0 ## explicit; go 1.22 go.uber.org/mock/gomock +# golang.design/x/clipboard v0.7.1 +## explicit; go 1.24 +golang.design/x/clipboard # golang.org/x/crypto v0.39.0 ## explicit; go 1.23.0 golang.org/x/crypto/blowfish @@ -514,6 +571,33 @@ golang.org/x/crypto/ssh/internal/bcrypt_pbkdf ## explicit; go 1.22.0 golang.org/x/exp/constraints golang.org/x/exp/maps +# golang.org/x/exp/shiny v0.0.0-20250606033433-dcc06ee1d476 +## explicit; go 1.23.0 +golang.org/x/exp/shiny/driver/gldriver +golang.org/x/exp/shiny/driver/internal/drawer +golang.org/x/exp/shiny/driver/internal/errscreen +golang.org/x/exp/shiny/driver/internal/event +golang.org/x/exp/shiny/driver/internal/lifecycler +golang.org/x/exp/shiny/driver/internal/win32 +golang.org/x/exp/shiny/driver/internal/x11key +golang.org/x/exp/shiny/screen +# golang.org/x/image v0.28.0 +## explicit; go 1.23.0 +golang.org/x/image/bmp +golang.org/x/image/math/f64 +# golang.org/x/mobile v0.0.0-20250606033058-a2a15c67f36f +## explicit; go 1.23.0 +golang.org/x/mobile/app +golang.org/x/mobile/app/internal/callfn +golang.org/x/mobile/event/key +golang.org/x/mobile/event/lifecycle +golang.org/x/mobile/event/mouse +golang.org/x/mobile/event/paint +golang.org/x/mobile/event/size +golang.org/x/mobile/event/touch +golang.org/x/mobile/geom +golang.org/x/mobile/gl +golang.org/x/mobile/internal/mobileinit # golang.org/x/mod v0.25.0 ## explicit; go 1.23.0 golang.org/x/mod/semver @@ -534,9 +618,13 @@ golang.org/x/sync/singleflight # golang.org/x/sys v0.33.0 ## explicit; go 1.23.0 golang.org/x/sys/cpu +golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows golang.org/x/sys/windows/registry +# golang.org/x/term v0.32.0 +## explicit; go 1.23.0 +golang.org/x/term # golang.org/x/text v0.26.0 ## explicit; go 1.23.0 golang.org/x/text/secure/bidirule