[Java] make it possible to set modes (generic, text, font) (#887)

* [Java] make it possible to set modes (generic, text, font)
diff --git a/java/org/brotli/wrapper/enc/Encoder.java b/java/org/brotli/wrapper/enc/Encoder.java
index 1fde8d6..af579a3 100644
--- a/java/org/brotli/wrapper/enc/Encoder.java
+++ b/java/org/brotli/wrapper/enc/Encoder.java
@@ -23,17 +23,46 @@
   boolean closed;
 
   /**
+   * https://www.brotli.org/encode.html#aa6f
+   * See encode.h, typedef enum BrotliEncoderMode
+   *
+   * <strong>Important</strong>: The ordinal value of the
+   * modes should be the same as the constant values in encode.h
+   */
+  public enum Mode {
+    /**
+     * Default compression mode.
+     * In this mode compressor does not know anything in advance about the properties of the input.
+     */
+    GENERIC,
+    /**
+     * Compression mode for UTF-8 formatted text input.
+     */
+    TEXT,
+    /**
+     * Compression mode used in WOFF 2.0.
+     */
+    FONT;
+
+    public static Mode of(int value) {
+      return values()[value];
+    }
+  }
+
+  /**
    * Brotli encoder settings.
    */
   public static final class Parameters {
     private int quality = -1;
     private int lgwin = -1;
+    private Mode mode;
 
     public Parameters() { }
 
     private Parameters(Parameters other) {
       this.quality = other.quality;
       this.lgwin = other.lgwin;
+      this.mode = other.mode;
     }
 
     /**
@@ -57,6 +86,14 @@
       this.lgwin = lgwin;
       return this;
     }
+
+    /**
+     * @param mode compression mode, or {@code null} for default
+     */
+    public Parameters setMode(Mode mode) {
+      this.mode = mode;
+      return this;
+    }
   }
 
   /**
@@ -75,7 +112,7 @@
       throw new NullPointerException("destination can not be null");
     }
     this.destination = destination;
-    this.encoder = new EncoderJNI.Wrapper(inputBufferSize, params.quality, params.lgwin);
+    this.encoder = new EncoderJNI.Wrapper(inputBufferSize, params.quality, params.lgwin, params.mode);
     this.inputBuffer = this.encoder.getInputBuffer();
   }
 
@@ -163,7 +200,7 @@
       return empty;
     }
     /* data.length > 0 */
-    EncoderJNI.Wrapper encoder = new EncoderJNI.Wrapper(data.length, params.quality, params.lgwin);
+    EncoderJNI.Wrapper encoder = new EncoderJNI.Wrapper(data.length, params.quality, params.lgwin, params.mode);
     ArrayList<byte[]> output = new ArrayList<byte[]>();
     int totalOutputSize = 0;
     try {
diff --git a/java/org/brotli/wrapper/enc/EncoderJNI.java b/java/org/brotli/wrapper/enc/EncoderJNI.java
index 5013629..d0c5fac 100644
--- a/java/org/brotli/wrapper/enc/EncoderJNI.java
+++ b/java/org/brotli/wrapper/enc/EncoderJNI.java
@@ -29,7 +29,7 @@
     private final ByteBuffer inputBuffer;
     private boolean fresh = true;
 
-    Wrapper(int inputBufferSize, int quality, int lgwin)
+    Wrapper(int inputBufferSize, int quality, int lgwin, Encoder.Mode mode)
         throws IOException {
       if (inputBufferSize <= 0) {
         throw new IOException("buffer size must be positive");
@@ -37,6 +37,7 @@
       this.context[1] = inputBufferSize;
       this.context[2] = quality;
       this.context[3] = lgwin;
+      this.context[4] = mode != null ? mode.ordinal() : -1;
       this.inputBuffer = nativeCreate(this.context);
       if (this.context[0] == 0) {
         throw new IOException("failed to initialize native brotli encoder");
@@ -44,6 +45,7 @@
       this.context[1] = 1;
       this.context[2] = 0;
       this.context[3] = 0;
+      this.context[4] = 0;
     }
 
     void push(Operation op, int length) {
diff --git a/java/org/brotli/wrapper/enc/encoder_jni.cc b/java/org/brotli/wrapper/enc/encoder_jni.cc
index 5cde6df..e69f719 100644
--- a/java/org/brotli/wrapper/enc/encoder_jni.cc
+++ b/java/org/brotli/wrapper/enc/encoder_jni.cc
@@ -79,6 +79,10 @@
     if (lgwin >= 0) {
       BrotliEncoderSetParameter(handle->state, BROTLI_PARAM_LGWIN, lgwin);
     }
+    int mode = context[4];
+    if (mode >= 0) {
+      BrotliEncoderSetParameter(handle->state, BROTLI_PARAM_MODE, mode);
+    }
   }
 
   if (ok) {