Replace some #defines with CBC_HighLevelEncoder::Encoding enum.

Change-Id: I8dbe2da1b01b608b6b1061d48d0094cb122f915e
Reviewed-on: https://pdfium-review.googlesource.com/c/46710
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp b/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp
index 3d0249e..469a8eb 100644
--- a/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp
+++ b/fxbarcode/datamatrix/BC_ASCIIEncoder.cpp
@@ -56,8 +56,8 @@
 
 CBC_ASCIIEncoder::~CBC_ASCIIEncoder() = default;
 
-int32_t CBC_ASCIIEncoder::getEncodingMode() {
-  return ASCII_ENCODATION;
+CBC_HighLevelEncoder::Encoding CBC_ASCIIEncoder::GetEncodingMode() {
+  return CBC_HighLevelEncoder::Encoding::ASCII;
 }
 
 bool CBC_ASCIIEncoder::Encode(CBC_EncoderContext* context) {
@@ -74,33 +74,30 @@
   }
 
   wchar_t c = context->getCurrentChar();
-  int32_t newMode = CBC_HighLevelEncoder::LookAheadTest(
-      context->m_msg, context->m_pos, getEncodingMode());
-  if (newMode != getEncodingMode()) {
+  CBC_HighLevelEncoder::Encoding newMode = CBC_HighLevelEncoder::LookAheadTest(
+      context->m_msg, context->m_pos, GetEncodingMode());
+  if (newMode != GetEncodingMode()) {
     switch (newMode) {
-      case BASE256_ENCODATION:
+      case CBC_HighLevelEncoder::Encoding::BASE256:
         context->writeCodeword(CBC_HighLevelEncoder::LATCH_TO_BASE256);
-        context->signalEncoderChange(BASE256_ENCODATION);
-        return true;
-      case C40_ENCODATION:
+        break;
+      case CBC_HighLevelEncoder::Encoding::C40:
         context->writeCodeword(CBC_HighLevelEncoder::LATCH_TO_C40);
-        context->signalEncoderChange(C40_ENCODATION);
-        return true;
-      case X12_ENCODATION:
+        break;
+      case CBC_HighLevelEncoder::Encoding::X12:
         context->writeCodeword(CBC_HighLevelEncoder::LATCH_TO_ANSIX12);
-        context->signalEncoderChange(X12_ENCODATION);
-        return true;
-      case TEXT_ENCODATION:
+        break;
+      case CBC_HighLevelEncoder::Encoding::TEXT:
         context->writeCodeword(CBC_HighLevelEncoder::LATCH_TO_TEXT);
-        context->signalEncoderChange(TEXT_ENCODATION);
-        return true;
-      case EDIFACT_ENCODATION:
+        break;
+      case CBC_HighLevelEncoder::Encoding::EDIFACT:
         context->writeCodeword(CBC_HighLevelEncoder::LATCH_TO_EDIFACT);
-        context->signalEncoderChange(EDIFACT_ENCODATION);
-        return true;
+        break;
       default:
         return false;
     }
+    context->SignalEncoderChange(newMode);
+    return true;
   }
 
   if (CBC_HighLevelEncoder::IsExtendedASCII(c)) {
diff --git a/fxbarcode/datamatrix/BC_ASCIIEncoder.h b/fxbarcode/datamatrix/BC_ASCIIEncoder.h
index 1b210ed..8b3c2de 100644
--- a/fxbarcode/datamatrix/BC_ASCIIEncoder.h
+++ b/fxbarcode/datamatrix/BC_ASCIIEncoder.h
@@ -17,7 +17,7 @@
   ~CBC_ASCIIEncoder() override;
 
   // CBC_Encoder
-  int32_t getEncodingMode() override;
+  CBC_HighLevelEncoder::Encoding GetEncodingMode() override;
   bool Encode(CBC_EncoderContext* context) override;
 };
 
diff --git a/fxbarcode/datamatrix/BC_Base256Encoder.cpp b/fxbarcode/datamatrix/BC_Base256Encoder.cpp
index 9512547..ea70f68 100644
--- a/fxbarcode/datamatrix/BC_Base256Encoder.cpp
+++ b/fxbarcode/datamatrix/BC_Base256Encoder.cpp
@@ -43,8 +43,8 @@
 
 CBC_Base256Encoder::~CBC_Base256Encoder() = default;
 
-int32_t CBC_Base256Encoder::getEncodingMode() {
-  return BASE256_ENCODATION;
+CBC_HighLevelEncoder::Encoding CBC_Base256Encoder::GetEncodingMode() {
+  return CBC_HighLevelEncoder::Encoding::BASE256;
 }
 
 bool CBC_Base256Encoder::Encode(CBC_EncoderContext* context) {
@@ -55,10 +55,11 @@
     wchar_t c = context->getCurrentChar();
     buffer += c;
     context->m_pos++;
-    int32_t newMode = CBC_HighLevelEncoder::LookAheadTest(
-        context->m_msg, context->m_pos, getEncodingMode());
-    if (newMode != getEncodingMode()) {
-      context->signalEncoderChange(newMode);
+    CBC_HighLevelEncoder::Encoding newMode =
+        CBC_HighLevelEncoder::LookAheadTest(context->m_msg, context->m_pos,
+                                            GetEncodingMode());
+    if (newMode != GetEncodingMode()) {
+      context->SignalEncoderChange(newMode);
       break;
     }
   }
diff --git a/fxbarcode/datamatrix/BC_Base256Encoder.h b/fxbarcode/datamatrix/BC_Base256Encoder.h
index e60333f..4897cc5 100644
--- a/fxbarcode/datamatrix/BC_Base256Encoder.h
+++ b/fxbarcode/datamatrix/BC_Base256Encoder.h
@@ -15,7 +15,7 @@
   ~CBC_Base256Encoder() override;
 
   // CBC_Encoder
-  int32_t getEncodingMode() override;
+  CBC_HighLevelEncoder::Encoding GetEncodingMode() override;
   bool Encode(CBC_EncoderContext* context) override;
 };
 
diff --git a/fxbarcode/datamatrix/BC_C40Encoder.cpp b/fxbarcode/datamatrix/BC_C40Encoder.cpp
index 1a2b0d6..9f20a35 100644
--- a/fxbarcode/datamatrix/BC_C40Encoder.cpp
+++ b/fxbarcode/datamatrix/BC_C40Encoder.cpp
@@ -48,8 +48,8 @@
 
 CBC_C40Encoder::~CBC_C40Encoder() = default;
 
-int32_t CBC_C40Encoder::getEncodingMode() {
-  return C40_ENCODATION;
+CBC_HighLevelEncoder::Encoding CBC_C40Encoder::GetEncodingMode() {
+  return CBC_HighLevelEncoder::Encoding::C40;
 }
 
 bool CBC_C40Encoder::Encode(CBC_EncoderContext* context) {
@@ -86,10 +86,11 @@
     }
     size_t count = buffer.GetLength();
     if ((count % 3) == 0) {
-      int32_t newMode = CBC_HighLevelEncoder::LookAheadTest(
-          context->m_msg, context->m_pos, getEncodingMode());
-      if (newMode != getEncodingMode()) {
-        context->signalEncoderChange(newMode);
+      CBC_HighLevelEncoder::Encoding newMode =
+          CBC_HighLevelEncoder::LookAheadTest(context->m_msg, context->m_pos,
+                                              GetEncodingMode());
+      if (newMode != GetEncodingMode()) {
+        context->SignalEncoderChange(newMode);
         break;
       }
     }
@@ -135,7 +136,7 @@
   } else {
     return false;
   }
-  context->signalEncoderChange(ASCII_ENCODATION);
+  context->SignalEncoderChange(CBC_HighLevelEncoder::Encoding::ASCII);
   return true;
 }
 
diff --git a/fxbarcode/datamatrix/BC_C40Encoder.h b/fxbarcode/datamatrix/BC_C40Encoder.h
index 6a4df23..8bea47b 100644
--- a/fxbarcode/datamatrix/BC_C40Encoder.h
+++ b/fxbarcode/datamatrix/BC_C40Encoder.h
@@ -16,7 +16,7 @@
   ~CBC_C40Encoder() override;
 
   // CBC_Encoder
-  int32_t getEncodingMode() override;
+  CBC_HighLevelEncoder::Encoding GetEncodingMode() override;
   bool Encode(CBC_EncoderContext* context) override;
 
   static void WriteNextTriplet(CBC_EncoderContext* context, WideString* buffer);
diff --git a/fxbarcode/datamatrix/BC_EdifactEncoder.cpp b/fxbarcode/datamatrix/BC_EdifactEncoder.cpp
index 0622be5..bd86a95 100644
--- a/fxbarcode/datamatrix/BC_EdifactEncoder.cpp
+++ b/fxbarcode/datamatrix/BC_EdifactEncoder.cpp
@@ -96,7 +96,7 @@
   } else {
     context->writeCodewords(encoded);
   }
-  context->signalEncoderChange(ASCII_ENCODATION);
+  context->SignalEncoderChange(CBC_HighLevelEncoder::Encoding::ASCII);
   return true;
 }
 
@@ -120,8 +120,8 @@
 
 CBC_EdifactEncoder::~CBC_EdifactEncoder() = default;
 
-int32_t CBC_EdifactEncoder::getEncodingMode() {
-  return EDIFACT_ENCODATION;
+CBC_HighLevelEncoder::Encoding CBC_EdifactEncoder::GetEncodingMode() {
+  return CBC_HighLevelEncoder::Encoding::EDIFACT;
 }
 
 bool CBC_EdifactEncoder::Encode(CBC_EncoderContext* context) {
@@ -140,10 +140,11 @@
 
       context->writeCodewords(encoded);
       buffer.Delete(0, 4);
-      int32_t newMode = CBC_HighLevelEncoder::LookAheadTest(
-          context->m_msg, context->m_pos, getEncodingMode());
-      if (newMode != getEncodingMode()) {
-        context->signalEncoderChange(ASCII_ENCODATION);
+      CBC_HighLevelEncoder::Encoding newMode =
+          CBC_HighLevelEncoder::LookAheadTest(context->m_msg, context->m_pos,
+                                              GetEncodingMode());
+      if (newMode != GetEncodingMode()) {
+        context->SignalEncoderChange(CBC_HighLevelEncoder::Encoding::ASCII);
         break;
       }
     }
diff --git a/fxbarcode/datamatrix/BC_EdifactEncoder.h b/fxbarcode/datamatrix/BC_EdifactEncoder.h
index 070e763..0bd8e57 100644
--- a/fxbarcode/datamatrix/BC_EdifactEncoder.h
+++ b/fxbarcode/datamatrix/BC_EdifactEncoder.h
@@ -15,7 +15,7 @@
   ~CBC_EdifactEncoder() override;
 
   // CBC_Encoder
-  int32_t getEncodingMode() override;
+  CBC_HighLevelEncoder::Encoding GetEncodingMode() override;
   bool Encode(CBC_EncoderContext* context) override;
 };
 
diff --git a/fxbarcode/datamatrix/BC_Encoder.h b/fxbarcode/datamatrix/BC_Encoder.h
index 27110b6..0ea22ab 100644
--- a/fxbarcode/datamatrix/BC_Encoder.h
+++ b/fxbarcode/datamatrix/BC_Encoder.h
@@ -7,7 +7,7 @@
 #ifndef FXBARCODE_DATAMATRIX_BC_ENCODER_H_
 #define FXBARCODE_DATAMATRIX_BC_ENCODER_H_
 
-#include <stdint.h>
+#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h"
 
 class CBC_EncoderContext;
 
@@ -16,7 +16,7 @@
   CBC_Encoder();
   virtual ~CBC_Encoder();
 
-  virtual int32_t getEncodingMode() = 0;
+  virtual CBC_HighLevelEncoder::Encoding GetEncodingMode() = 0;
   virtual bool Encode(CBC_EncoderContext* context) = 0;
 };
 
diff --git a/fxbarcode/datamatrix/BC_EncoderContext.cpp b/fxbarcode/datamatrix/BC_EncoderContext.cpp
index 2552ba4..85b9324 100644
--- a/fxbarcode/datamatrix/BC_EncoderContext.cpp
+++ b/fxbarcode/datamatrix/BC_EncoderContext.cpp
@@ -70,12 +70,13 @@
   return m_codewords.GetLength();
 }
 
-void CBC_EncoderContext::signalEncoderChange(int32_t encoding) {
+void CBC_EncoderContext::SignalEncoderChange(
+    CBC_HighLevelEncoder::Encoding encoding) {
   m_newEncoding = encoding;
 }
 
-void CBC_EncoderContext::resetEncoderSignal() {
-  m_newEncoding = -1;
+void CBC_EncoderContext::ResetEncoderSignal() {
+  m_newEncoding = CBC_HighLevelEncoder::Encoding::UNKNOWN;
 }
 
 bool CBC_EncoderContext::hasMoreCharacters() {
diff --git a/fxbarcode/datamatrix/BC_EncoderContext.h b/fxbarcode/datamatrix/BC_EncoderContext.h
index eeec6cf..b4cc2f6 100644
--- a/fxbarcode/datamatrix/BC_EncoderContext.h
+++ b/fxbarcode/datamatrix/BC_EncoderContext.h
@@ -9,6 +9,7 @@
 
 #include "core/fxcrt/unowned_ptr.h"
 #include "core/fxcrt/widestring.h"
+#include "fxbarcode/datamatrix/BC_HighLevelEncoder.h"
 
 class CBC_SymbolInfo;
 
@@ -24,8 +25,8 @@
   void writeCodewords(const WideString& codewords);
   void writeCodeword(wchar_t codeword);
   size_t getCodewordCount();
-  void signalEncoderChange(int32_t encoding);
-  void resetEncoderSignal();
+  void SignalEncoderChange(CBC_HighLevelEncoder::Encoding encoding);
+  void ResetEncoderSignal();
   bool hasMoreCharacters();
   size_t getRemainingCharacters();
   bool UpdateSymbolInfo();
@@ -39,7 +40,8 @@
   WideString m_msg;
   WideString m_codewords;
   size_t m_pos = 0;
-  int32_t m_newEncoding = -1;
+  CBC_HighLevelEncoder::Encoding m_newEncoding =
+      CBC_HighLevelEncoder::Encoding::UNKNOWN;
   UnownedPtr<const CBC_SymbolInfo> m_symbolInfo;
 
  private:
diff --git a/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp b/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp
index 3a35941..3ee5cd7 100644
--- a/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp
+++ b/fxbarcode/datamatrix/BC_HighLevelEncoder.cpp
@@ -22,6 +22,7 @@
 
 #include "fxbarcode/datamatrix/BC_HighLevelEncoder.h"
 
+#include <algorithm>
 #include <limits>
 #include <memory>
 #include <vector>
@@ -105,6 +106,11 @@
   return ch >= ' ' && ch <= '^';
 }
 
+size_t EncoderIndex(CBC_HighLevelEncoder::Encoding encoding) {
+  ASSERT(encoding != CBC_HighLevelEncoder::Encoding::UNKNOWN);
+  return static_cast<size_t>(encoding);
+}
+
 }  // namespace
 
 // static
@@ -134,14 +140,14 @@
   encoders.push_back(pdfium::MakeUnique<CBC_X12Encoder>());
   encoders.push_back(pdfium::MakeUnique<CBC_EdifactEncoder>());
   encoders.push_back(pdfium::MakeUnique<CBC_Base256Encoder>());
-  int32_t encodingMode = ASCII_ENCODATION;
+  Encoding encodingMode = Encoding::ASCII;
   while (context.hasMoreCharacters()) {
-    if (!encoders[encodingMode]->Encode(&context))
+    if (!encoders[EncoderIndex(encodingMode)]->Encode(&context))
       return WideString();
 
-    if (context.m_newEncoding >= 0) {
+    if (context.m_newEncoding != Encoding::UNKNOWN) {
       encodingMode = context.m_newEncoding;
-      context.resetEncoderSignal();
+      context.ResetEncoderSignal();
     }
   }
   size_t len = context.m_codewords.GetLength();
@@ -150,10 +156,8 @@
 
   size_t capacity = context.m_symbolInfo->dataCapacity();
   if (len < capacity) {
-    if (encodingMode != ASCII_ENCODATION &&
-        encodingMode != BASE256_ENCODATION) {
+    if (encodingMode != Encoding::ASCII && encodingMode != Encoding::BASE256)
       context.writeCodeword(0x00fe);
-    }
   }
   WideString codewords = context.m_codewords;
   if (codewords.GetLength() < capacity)
@@ -167,18 +171,19 @@
 }
 
 // static
-int32_t CBC_HighLevelEncoder::LookAheadTest(const WideString& msg,
-                                            size_t startpos,
-                                            int32_t currentMode) {
+CBC_HighLevelEncoder::Encoding CBC_HighLevelEncoder::LookAheadTest(
+    const WideString& msg,
+    size_t startpos,
+    CBC_HighLevelEncoder::Encoding currentMode) {
   if (startpos >= msg.GetLength())
     return currentMode;
 
   std::vector<float> charCounts;
-  if (currentMode == ASCII_ENCODATION) {
+  if (currentMode == Encoding::ASCII) {
     charCounts = {0, 1, 1, 1, 1, 1.25f};
   } else {
     charCounts = {1, 2, 2, 2, 2, 2.25f};
-    charCounts[currentMode] = 0;
+    charCounts[EncoderIndex(currentMode)] = 0;
   }
   size_t charsProcessed = 0;
   while (true) {
@@ -186,61 +191,75 @@
       std::vector<uint8_t> mins(6);
       std::vector<int32_t> intCharCounts(6);
       int32_t min = FindMinimums(charCounts, &intCharCounts, &mins);
-      int32_t minCount = GetMinimumCount(mins);
-      if (intCharCounts[ASCII_ENCODATION] == min)
-        return ASCII_ENCODATION;
-      if (minCount == 1 && mins[BASE256_ENCODATION] > 0)
-        return BASE256_ENCODATION;
-      if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0)
-        return EDIFACT_ENCODATION;
-      if (minCount == 1 && mins[TEXT_ENCODATION] > 0)
-        return TEXT_ENCODATION;
-      if (minCount == 1 && mins[X12_ENCODATION] > 0)
-        return X12_ENCODATION;
-      return C40_ENCODATION;
+      if (intCharCounts[EncoderIndex(Encoding::ASCII)] == min)
+        return Encoding::ASCII;
+      const int32_t minCount = GetMinimumCount(mins);
+      if (minCount == 1) {
+        if (mins[EncoderIndex(Encoding::BASE256)] > 0)
+          return Encoding::BASE256;
+        if (mins[EncoderIndex(Encoding::EDIFACT)] > 0)
+          return Encoding::EDIFACT;
+        if (mins[EncoderIndex(Encoding::TEXT)] > 0)
+          return Encoding::TEXT;
+        if (mins[EncoderIndex(Encoding::X12)] > 0)
+          return Encoding::X12;
+      }
+      return Encoding::C40;
     }
 
     wchar_t c = msg[startpos + charsProcessed];
     charsProcessed++;
-    if (FXSYS_IsDecimalDigit(c)) {
-      charCounts[ASCII_ENCODATION] += 0.5;
-    } else if (IsExtendedASCII(c)) {
-      charCounts[ASCII_ENCODATION] = ceilf(charCounts[ASCII_ENCODATION]);
-      charCounts[ASCII_ENCODATION] += 2;
-    } else {
-      charCounts[ASCII_ENCODATION] = ceilf(charCounts[ASCII_ENCODATION]);
-      charCounts[ASCII_ENCODATION]++;
+    {
+      auto& count = charCounts[EncoderIndex(Encoding::ASCII)];
+      if (FXSYS_IsDecimalDigit(c))
+        count += 0.5;
+      else if (IsExtendedASCII(c))
+        count = ceilf(count) + 2;
+      else
+        count = ceilf(count) + 1;
     }
 
-    if (IsNativeC40(c))
-      charCounts[C40_ENCODATION] += 2.0f / 3.0f;
-    else if (IsExtendedASCII(c))
-      charCounts[C40_ENCODATION] += 8.0f / 3.0f;
-    else
-      charCounts[C40_ENCODATION] += 4.0f / 3.0f;
+    {
+      auto& count = charCounts[EncoderIndex(Encoding::C40)];
+      if (IsNativeC40(c))
+        count += 2.0f / 3.0f;
+      else if (IsExtendedASCII(c))
+        count += 8.0f / 3.0f;
+      else
+        count += 4.0f / 3.0f;
+    }
 
-    if (IsNativeText(c))
-      charCounts[TEXT_ENCODATION] += 2.0f / 3.0f;
-    else if (IsExtendedASCII(c))
-      charCounts[TEXT_ENCODATION] += 8.0f / 3.0f;
-    else
-      charCounts[TEXT_ENCODATION] += 4.0f / 3.0f;
+    {
+      auto& count = charCounts[EncoderIndex(Encoding::TEXT)];
+      if (IsNativeText(c))
+        count += 2.0f / 3.0f;
+      else if (IsExtendedASCII(c))
+        count += 8.0f / 3.0f;
+      else
+        count += 4.0f / 3.0f;
+    }
 
-    if (IsNativeX12(c))
-      charCounts[X12_ENCODATION] += 2.0f / 3.0f;
-    else if (IsExtendedASCII(c))
-      charCounts[X12_ENCODATION] += 13.0f / 3.0f;
-    else
-      charCounts[X12_ENCODATION] += 10.0f / 3.0f;
+    {
+      auto& count = charCounts[EncoderIndex(Encoding::X12)];
+      if (IsNativeX12(c))
+        count += 2.0f / 3.0f;
+      else if (IsExtendedASCII(c))
+        count += 13.0f / 3.0f;
+      else
+        count += 10.0f / 3.0f;
+    }
 
-    if (IsNativeEDIFACT(c))
-      charCounts[EDIFACT_ENCODATION] += 3.0f / 4.0f;
-    else if (IsExtendedASCII(c))
-      charCounts[EDIFACT_ENCODATION] += 17.0f / 4.0f;
-    else
-      charCounts[EDIFACT_ENCODATION] += 13.0f / 4.0f;
+    {
+      auto& count = charCounts[EncoderIndex(Encoding::EDIFACT)];
+      if (IsNativeEDIFACT(c))
+        count += 3.0f / 4.0f;
+      else if (IsExtendedASCII(c))
+        count += 17.0f / 4.0f;
+      else
+        count += 13.0f / 4.0f;
+    }
 
-    charCounts[BASE256_ENCODATION]++;
+    charCounts[EncoderIndex(Encoding::BASE256)]++;
     if (charsProcessed < 4)
       continue;
 
@@ -248,41 +267,46 @@
     std::vector<uint8_t> mins(6);
     FindMinimums(charCounts, &intCharCounts, &mins);
     int32_t minCount = GetMinimumCount(mins);
-    if (intCharCounts[ASCII_ENCODATION] < intCharCounts[BASE256_ENCODATION] &&
-        intCharCounts[ASCII_ENCODATION] < intCharCounts[C40_ENCODATION] &&
-        intCharCounts[ASCII_ENCODATION] < intCharCounts[TEXT_ENCODATION] &&
-        intCharCounts[ASCII_ENCODATION] < intCharCounts[X12_ENCODATION] &&
-        intCharCounts[ASCII_ENCODATION] < intCharCounts[EDIFACT_ENCODATION]) {
-      return ASCII_ENCODATION;
+    int32_t ascii_count = intCharCounts[EncoderIndex(Encoding::ASCII)];
+    int32_t c40_count = intCharCounts[EncoderIndex(Encoding::C40)];
+    int32_t text_count = intCharCounts[EncoderIndex(Encoding::TEXT)];
+    int32_t x12_count = intCharCounts[EncoderIndex(Encoding::X12)];
+    int32_t editfact_count = intCharCounts[EncoderIndex(Encoding::EDIFACT)];
+    int32_t base256_count = intCharCounts[EncoderIndex(Encoding::BASE256)];
+    int32_t bet_min = std::min({base256_count, editfact_count, text_count});
+    if (ascii_count < bet_min && ascii_count < c40_count &&
+        ascii_count < x12_count) {
+      return Encoding::ASCII;
     }
-    if (intCharCounts[BASE256_ENCODATION] < intCharCounts[ASCII_ENCODATION] ||
-        (mins[C40_ENCODATION] + mins[TEXT_ENCODATION] + mins[X12_ENCODATION] +
-         mins[EDIFACT_ENCODATION]) == 0) {
-      return BASE256_ENCODATION;
+    if (base256_count < ascii_count ||
+        (mins[EncoderIndex(Encoding::C40)] +
+         mins[EncoderIndex(Encoding::TEXT)] +
+         mins[EncoderIndex(Encoding::X12)] +
+         mins[EncoderIndex(Encoding::EDIFACT)]) == 0) {
+      return Encoding::BASE256;
     }
-    if (minCount == 1 && mins[EDIFACT_ENCODATION] > 0)
-      return EDIFACT_ENCODATION;
-    if (minCount == 1 && mins[TEXT_ENCODATION] > 0)
-      return TEXT_ENCODATION;
-    if (minCount == 1 && mins[X12_ENCODATION] > 0)
-      return X12_ENCODATION;
-    if (intCharCounts[C40_ENCODATION] + 1 < intCharCounts[ASCII_ENCODATION] &&
-        intCharCounts[C40_ENCODATION] + 1 < intCharCounts[BASE256_ENCODATION] &&
-        intCharCounts[C40_ENCODATION] + 1 < intCharCounts[EDIFACT_ENCODATION] &&
-        intCharCounts[C40_ENCODATION] + 1 < intCharCounts[TEXT_ENCODATION]) {
-      if (intCharCounts[C40_ENCODATION] < intCharCounts[X12_ENCODATION])
-        return C40_ENCODATION;
-      if (intCharCounts[C40_ENCODATION] == intCharCounts[X12_ENCODATION]) {
+    if (minCount == 1) {
+      if (mins[EncoderIndex(Encoding::EDIFACT)] > 0)
+        return Encoding::EDIFACT;
+      if (mins[EncoderIndex(Encoding::TEXT)] > 0)
+        return Encoding::TEXT;
+      if (mins[EncoderIndex(Encoding::X12)] > 0)
+        return Encoding::X12;
+    }
+    if (c40_count + 1 < ascii_count && c40_count + 1 < bet_min) {
+      if (c40_count < x12_count)
+        return Encoding::C40;
+      if (c40_count == x12_count) {
         size_t p = startpos + charsProcessed + 1;
         while (p < msg.GetLength()) {
           wchar_t tc = msg[p];
           if (IsX12TermSep(tc))
-            return X12_ENCODATION;
+            return Encoding::X12;
           if (!IsNativeX12(tc))
             break;
           p++;
         }
-        return C40_ENCODATION;
+        return Encoding::C40;
       }
     }
   }
diff --git a/fxbarcode/datamatrix/BC_HighLevelEncoder.h b/fxbarcode/datamatrix/BC_HighLevelEncoder.h
index 81d5107..ec2d2f0 100644
--- a/fxbarcode/datamatrix/BC_HighLevelEncoder.h
+++ b/fxbarcode/datamatrix/BC_HighLevelEncoder.h
@@ -11,15 +11,18 @@
 
 #include "core/fxcrt/widestring.h"
 
-#define ASCII_ENCODATION 0
-#define C40_ENCODATION 1
-#define TEXT_ENCODATION 2
-#define X12_ENCODATION 3
-#define EDIFACT_ENCODATION 4
-#define BASE256_ENCODATION 5
-
 class CBC_HighLevelEncoder {
  public:
+  enum class Encoding : int8_t {
+    UNKNOWN = -1,
+    ASCII = 0,
+    C40,
+    TEXT,
+    X12,
+    EDIFACT,
+    BASE256,
+  };
+
   CBC_HighLevelEncoder() = delete;
   ~CBC_HighLevelEncoder() = delete;
 
@@ -27,9 +30,9 @@
   static WideString EncodeHighLevel(const WideString& msg,
                                     bool bAllowRectangular);
 
-  static int32_t LookAheadTest(const WideString& msg,
-                               size_t startpos,
-                               int32_t currentMode);
+  static Encoding LookAheadTest(const WideString& msg,
+                                size_t startpos,
+                                Encoding currentMode);
   static bool IsExtendedASCII(wchar_t ch);
 
   static const wchar_t LATCH_TO_C40 = 230;
diff --git a/fxbarcode/datamatrix/BC_TextEncoder.cpp b/fxbarcode/datamatrix/BC_TextEncoder.cpp
index fee45d4..8fcdb6f 100644
--- a/fxbarcode/datamatrix/BC_TextEncoder.cpp
+++ b/fxbarcode/datamatrix/BC_TextEncoder.cpp
@@ -32,8 +32,8 @@
 
 CBC_TextEncoder::~CBC_TextEncoder() = default;
 
-int32_t CBC_TextEncoder::getEncodingMode() {
-  return TEXT_ENCODATION;
+CBC_HighLevelEncoder::Encoding CBC_TextEncoder::GetEncodingMode() {
+  return CBC_HighLevelEncoder::Encoding::TEXT;
 }
 
 int32_t CBC_TextEncoder::EncodeChar(wchar_t c, WideString* sb) {
diff --git a/fxbarcode/datamatrix/BC_TextEncoder.h b/fxbarcode/datamatrix/BC_TextEncoder.h
index f0213c9..40914b3 100644
--- a/fxbarcode/datamatrix/BC_TextEncoder.h
+++ b/fxbarcode/datamatrix/BC_TextEncoder.h
@@ -15,7 +15,7 @@
   ~CBC_TextEncoder() override;
 
   // CBC_C40Encoder
-  int32_t getEncodingMode() override;
+  CBC_HighLevelEncoder::Encoding GetEncodingMode() override;
   int32_t EncodeChar(wchar_t c, WideString* sb) override;
 };
 
diff --git a/fxbarcode/datamatrix/BC_X12Encoder.cpp b/fxbarcode/datamatrix/BC_X12Encoder.cpp
index 4bbb145..37180ea 100644
--- a/fxbarcode/datamatrix/BC_X12Encoder.cpp
+++ b/fxbarcode/datamatrix/BC_X12Encoder.cpp
@@ -34,8 +34,8 @@
 
 CBC_X12Encoder::~CBC_X12Encoder() = default;
 
-int32_t CBC_X12Encoder::getEncodingMode() {
-  return X12_ENCODATION;
+CBC_HighLevelEncoder::Encoding CBC_X12Encoder::GetEncodingMode() {
+  return CBC_HighLevelEncoder::Encoding::X12;
 }
 
 bool CBC_X12Encoder::Encode(CBC_EncoderContext* context) {
@@ -49,10 +49,11 @@
     size_t count = buffer.GetLength();
     if ((count % 3) == 0) {
       WriteNextTriplet(context, &buffer);
-      int32_t newMode = CBC_HighLevelEncoder::LookAheadTest(
-          context->m_msg, context->m_pos, getEncodingMode());
-      if (newMode != getEncodingMode()) {
-        context->signalEncoderChange(newMode);
+      CBC_HighLevelEncoder::Encoding newMode =
+          CBC_HighLevelEncoder::LookAheadTest(context->m_msg, context->m_pos,
+                                              GetEncodingMode());
+      if (newMode != GetEncodingMode()) {
+        context->SignalEncoderChange(newMode);
         break;
       }
     }
@@ -71,13 +72,13 @@
   if (count == 2) {
     context->writeCodeword(CBC_HighLevelEncoder::X12_UNLATCH);
     context->m_pos -= 2;
-    context->signalEncoderChange(ASCII_ENCODATION);
+    context->SignalEncoderChange(CBC_HighLevelEncoder::Encoding::ASCII);
   } else if (count == 1) {
     context->m_pos--;
     if (available > 1) {
       context->writeCodeword(CBC_HighLevelEncoder::X12_UNLATCH);
     }
-    context->signalEncoderChange(ASCII_ENCODATION);
+    context->SignalEncoderChange(CBC_HighLevelEncoder::Encoding::ASCII);
   }
   return true;
 }
diff --git a/fxbarcode/datamatrix/BC_X12Encoder.h b/fxbarcode/datamatrix/BC_X12Encoder.h
index cf5119a..aa258a9 100644
--- a/fxbarcode/datamatrix/BC_X12Encoder.h
+++ b/fxbarcode/datamatrix/BC_X12Encoder.h
@@ -15,7 +15,7 @@
   ~CBC_X12Encoder() override;
 
   // CBC_C40Encoder
-  int32_t getEncodingMode() override;
+  CBC_HighLevelEncoder::Encoding GetEncodingMode() override;
   bool Encode(CBC_EncoderContext* context) override;
   bool HandleEOD(CBC_EncoderContext* context, WideString* buffer) override;
   int32_t EncodeChar(wchar_t c, WideString* sb) override;