docs: @Override
      protected void encode() {
  
          eciProcess();
  
          // mode 2 -> mode 3 if postal code isn't strictly numeric
          if (mode == 2) {
              for (int i = 0; i < 10 && i < primaryData.length(); i++) {
                  if ((primaryData.charAt(i) < '0') || (primaryData.charAt(i) > '9')) {
                      mode = 3;
                      break;
                  }
              }
          }
  
          // initialize the set and character arrays
          processText();
  
          // start building the codeword array, starting with a copy of the character data
          // insert primary message if this is a structured carrier message; insert mode otherwise
          codewords = Arrays.copyOf(character, character.length);
          if (mode == 2 || mode == 3) {
              int[] primary = getPrimaryCodewords();
              codewords = insertArray(codewords, 0, primary);
          } else {
              codewords = insertArray(codewords, 0, new int[] { mode });
          }
  
          // insert structured append flag if necessary
          if (structuredAppendTotal > 1) {
  
              int[] flag = new int[2];
              flag[0] = 33; // padding
              flag[1] = ((structuredAppendPosition - 1) << 3) | (structuredAppendTotal - 1); // position + total
  
              int index;
              if (mode == 2 || mode == 3) {
                  index = 10; // first two data symbols in the secondary message
              } else {
                  index = 1; // first two data symbols in the primary message (first symbol at index 0 isn't a data symbol)
              }
  
              codewords = insertArray(codewords, index, flag);
          }
  
          int secondaryMax, secondaryECMax;
          if (mode == 5) {
              // 68 data codewords, 56 error corrections in secondary message
              secondaryMax = 68;
              secondaryECMax = 56;
          } else {
              // 84 data codewords, 40 error corrections in secondary message
              secondaryMax = 84;
              secondaryECMax = 40;
          }
  
          // truncate data codewords to maximum data space available
          int totalMax = secondaryMax + 10;
          if (codewords.length > totalMax) {
              codewords = Arrays.copyOfRange(codewords, 0, totalMax);
          }
  
          // insert primary error correction between primary message and secondary message (always EEC)
          int[] primary = Arrays.copyOfRange(codewords, 0, 10);
          int[] primaryCheck = getErrorCorrection(primary, 10);
          codewords = insertArray(codewords, 10, primaryCheck);
  
          // calculate secondary error correction
          int[] secondary = Arrays.copyOfRange(codewords, 20, codewords.length);
          int[] secondaryOdd = new int[secondary.length / 2];
          int[] secondaryEven = new int[secondary.length / 2];
          for (int i = 0; i < secondary.length; i++) {
              if ((i & 1) != 0) { // odd
                  secondaryOdd[(i - 1) / 2] = secondary[i];
              } else { // even
                  secondaryEven[i / 2] = secondary[i];
              }
          }
          int[] secondaryECOdd = getErrorCorrection(secondaryOdd, secondaryECMax / 2);
          int[] secondaryECEven = getErrorCorrection(secondaryEven, secondaryECMax / 2);
  
          // add secondary error correction after secondary message
          codewords = Arrays.copyOf(codewords, codewords.length + secondaryECOdd.length + secondaryECEven.length);
          for (int i = 0; i < secondaryECOdd.length; i++) {
              codewords[20 + secondaryMax + (2 * i) + 1] = secondaryECOdd[i];
          }
          for (int i = 0; i < secondaryECEven.length; i++) {
              codewords[20 + secondaryMax + (2 * i)] = secondaryECEven[i];
          }
  
          encodeInfo += "Mode: " + mode + "\n";
          encodeInfo += "ECC Codewords: " + secondaryECMax + "\n";
          encodeInfo += "Codewords: ";
          for (int i = 0; i < codewords.length; i++) {
              encodeInfo += Integer.toString(codewords[i]) + " ";
          }
          encodeInfo += "\n";
  
          // copy data into symbol grid
          int[] bit_pattern = new int[7];
          for (int i = 0; i < 33; i++) {
              for (int j = 0; j < 30; j++) {
  
                  int block = (MAXICODE_GRID[(i * 30) + j] + 5) / 6;
                  int bit = (MAXICODE_GRID[(i * 30) + j] + 5) % 6;
  
                  if (block != 0) {
  
                      bit_pattern[0] = (codewords[block - 1] & 0x20) >> 5;
                      bit_pattern[1] = (codewords[block - 1] & 0x10) >> 4;
                      bit_pattern[2] = (codewords[block - 1] & 0x8) >> 3;
                      bit_pattern[3] = (codewords[block - 1] & 0x4) >> 2;
                      bit_pattern[4] = (codewords[block - 1] & 0x2) >> 1;
                      bit_pattern[5] = (codewords[block - 1] & 0x1);
  
                      if (bit_pattern[bit] != 0) {
                          grid[i][j] = true;
                      } else {
                          grid[i][j] = false;
                      }
                  }
              }
          }
  
          // add orientation markings
          grid[0][28] = true;  // top right filler
          grid[0][29] = true;
          grid[9][10] = true;  // top left marker
          grid[9][11] = true;
          grid[10][11] = true;
          grid[15][7] = true;  // left hand marker
          grid[16][8] = true;
          grid[16][20] = true; // right hand marker
          grid[17][20] = true;
          grid[22][10] = true; // bottom left marker
          grid[23][10] = true;
          grid[22][17] = true; // bottom right marker
          grid[23][17] = true;
  
          // the following is provided for compatibility, but the results are not useful
          row_count = 33;
          readable = "";
          pattern = new String[33];
          row_height = new int[33];
          for (int i = 0; i < 33; i++) {
              StringBuilder bin = new StringBuilder(30);
              for (int j = 0; j < 30; j++) {
                  if (grid[i][j]) {
                      bin.append("1");
                  } else {
                      bin.append("0");
                  }
              }
              pattern[i] = bin2pat(bin.toString());
              row_height[i] = 1;
          }
          symbol_height = 72;
          symbol_width = 74;
      }