| // Copyright 2020 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This helper binary can be compiled to aid in development / debugging of the |
| // QR generation code. It prints a QR code to the console and thus allows much |
| // faster iteration. It is not built by default, see the BUILD.gn in this |
| // directory. |
| |
| #include <stdio.h> |
| |
| #include <utility> |
| |
| #include "base/containers/span.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "components/qr_code_generator/qr_code_generator.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| // kTerminalBackgroundIsBright controls the output polarity. Many QR scanners |
| // will cope with inverted bright / dark but, if you have a bright terminal |
| // background, you may need to change this. |
| constexpr bool kTerminalBackgroundIsBright = false; |
| |
| // kPaint is a pair of UTF-8 encoded code points for U+2588 ("FULL BLOCK"). |
| static constexpr char kPaint[] = "\xe2\x96\x88\xe2\x96\x88"; |
| static constexpr char kNoPaint[] = " "; |
| |
| static void PrintHorizontalLine(const char* white, int size) { |
| for (int x = 0; x < size + 2; x++) { |
| fputs(white, stdout); |
| } |
| fputs("\n", stdout); |
| } |
| |
| int main(int argc, char** argv) { |
| // Presubmits don't allow fprintf to a variable called |stderr|. |
| FILE* const STDERR = stderr; |
| |
| if (argc < 2 || argc > 3) { |
| fprintf(STDERR, "Usage: %s <input string> [mask number]\n", argv[0]); |
| return 1; |
| } |
| |
| const uint8_t* const input = reinterpret_cast<const uint8_t*>(argv[1]); |
| const size_t input_len = strlen(argv[1]); |
| |
| absl::optional<uint8_t> mask; |
| if (argc == 3) { |
| unsigned mask_unsigned; |
| if (!base::StringToUint(argv[2], &mask_unsigned) || mask_unsigned > 7) { |
| fprintf(STDERR, "Mask numbers run from zero to seven.\n"); |
| return 1; |
| } |
| mask = static_cast<uint8_t>(mask_unsigned); |
| } |
| |
| const char* black = kNoPaint; |
| const char* white = kPaint; |
| if (kTerminalBackgroundIsBright) { |
| std::swap(black, white); |
| } |
| |
| QRCodeGenerator generator; |
| absl::optional<QRCodeGenerator::GeneratedCode> code = |
| generator.Generate(base::span<const uint8_t>(input, input_len), mask); |
| if (!code) { |
| fprintf(STDERR, "Input too long to be encoded.\n"); |
| return 2; |
| } |
| |
| const int size = code->qr_size; |
| PrintHorizontalLine(white, size); |
| |
| int i = 0; |
| for (int y = 0; y < size; y++) { |
| fputs(white, stdout); |
| for (int x = 0; x < size; x++) { |
| fputs((code->data[i++] & 1) ? black : white, stdout); |
| } |
| fputs(white, stdout); |
| fputs("\n", stdout); |
| } |
| |
| PrintHorizontalLine(white, size); |
| |
| return 0; |
| } |