Merge "Add wrapper for incremental decoder."
diff --git a/java/res/values/gesture-input.xml b/java/res/values/gesture-input.xml
new file mode 100644
index 0000000..235616f
--- /dev/null
+++ b/java/res/values/gesture-input.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+**
+** Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<resources>
+    <bool name="config_gesture_input_enabled_by_build_config">false</bool>
+</resources>
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 7714ba8..1eae2c1 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -341,10 +341,14 @@
 
         mHasDistinctMultitouch = context.getPackageManager()
                 .hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN_MULTITOUCH_DISTINCT);
+        final Resources res = getResources();
         final boolean needsPhantomSuddenMoveEventHack = Boolean.parseBoolean(
-                Utils.getDeviceOverrideValue(context.getResources(),
+                Utils.getDeviceOverrideValue(res,
                         R.array.phantom_sudden_move_event_device_list, "false"));
-        PointerTracker.init(mHasDistinctMultitouch, needsPhantomSuddenMoveEventHack);
+        final boolean gestureInputEnabledByBuildConfig = res.getBoolean(
+                R.bool.config_gesture_input_enabled_by_build_config);
+        PointerTracker.init(mHasDistinctMultitouch, needsPhantomSuddenMoveEventHack,
+                gestureInputEnabledByBuildConfig);
 
         final TypedArray a = context.obtainStyledAttributes(
                 attrs, R.styleable.LatinKeyboardView, defStyle, R.style.LatinKeyboardView);
diff --git a/java/src/com/android/inputmethod/keyboard/PointerTracker.java b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
index 4f6af98..ea4d93a 100644
--- a/java/src/com/android/inputmethod/keyboard/PointerTracker.java
+++ b/java/src/com/android/inputmethod/keyboard/PointerTracker.java
@@ -22,6 +22,7 @@
 import android.view.View;
 import android.widget.TextView;
 
+import com.android.inputmethod.accessibility.AccessibilityUtils;
 import com.android.inputmethod.keyboard.internal.GestureStroke;
 import com.android.inputmethod.keyboard.internal.PointerTrackerQueue;
 import com.android.inputmethod.latin.InputPointers;
@@ -39,8 +40,9 @@
     private static boolean DEBUG_MODE = LatinImeLogger.sDBG;
 
     // TODO: There should be an option to turn on/off the gesture input.
-    private static final boolean GESTURE_ON = true;
-    private static final int MIN_RECOGNITION_TIME = 100; // msec
+    private static boolean sIsGestureEnabled = true;
+
+    private static final int MIN_GESTURE_RECOGNITION_TIME = 100; // msec
 
     public interface KeyEventHandler {
         /**
@@ -116,9 +118,14 @@
     private static LatinKeyboardView.PointerTrackerParams sParams;
     private static int sTouchNoiseThresholdDistanceSquared;
     private static boolean sNeedsPhantomSuddenMoveEventHack;
+    private static boolean sConfigGestureInputEnabledByBuildConfig;
 
     private static final ArrayList<PointerTracker> sTrackers = new ArrayList<PointerTracker>();
     private static PointerTrackerQueue sPointerTrackerQueue;
+    // HACK: Change gesture detection criteria depending on this variable.
+    // TODO: Find more comprehensive ways to detect a gesture start.
+    // True when the previous user input was a gesture input, not a typing input.
+    private static boolean sWasInGesture;
 
     public final int mPointerId;
 
@@ -135,6 +142,7 @@
     private boolean mIsPossibleGesture = false;
     private boolean mInGesture = false;
 
+    // TODO: Remove these variables
     private int mLastRecognitionPointSize = 0;
     private long mLastRecognitionTime = 0;
 
@@ -177,15 +185,18 @@
     private final GestureStroke mGestureStroke;
 
     public static void init(boolean hasDistinctMultitouch,
-            boolean needsPhantomSuddenMoveEventHack) {
+            boolean needsPhantomSuddenMoveEventHack,
+            boolean gestureInputEnabledByBuildConfig) {
         if (hasDistinctMultitouch) {
             sPointerTrackerQueue = new PointerTrackerQueue();
         } else {
             sPointerTrackerQueue = null;
         }
         sNeedsPhantomSuddenMoveEventHack = needsPhantomSuddenMoveEventHack;
+        sConfigGestureInputEnabledByBuildConfig = gestureInputEnabledByBuildConfig;
 
         setParameters(LatinKeyboardView.PointerTrackerParams.DEFAULT);
+        updateGestureInputEnabledState(null);
     }
 
     public static void setParameters(LatinKeyboardView.PointerTrackerParams params) {
@@ -194,6 +205,16 @@
                 params.mTouchNoiseThresholdDistance * params.mTouchNoiseThresholdDistance);
     }
 
+    private static void updateGestureInputEnabledState(Keyboard keyboard) {
+        if (!sConfigGestureInputEnabledByBuildConfig
+                || AccessibilityUtils.getInstance().isTouchExplorationEnabled()
+                || (keyboard != null && keyboard.mId.passwordInput())) {
+            sIsGestureEnabled = false;
+        } else {
+            sIsGestureEnabled = true;
+        }
+    }
+
     public static PointerTracker getPointerTracker(final int id, KeyEventHandler handler) {
         final ArrayList<PointerTracker> trackers = sTrackers;
 
@@ -222,6 +243,8 @@
             // Mark that keyboard layout has been changed.
             tracker.mKeyboardLayoutHasBeenChanged = true;
         }
+        final Keyboard keyboard = keyDetector.getKeyboard();
+        updateGestureInputEnabledState(keyboard);
     }
 
     public static void dismissAllKeyPreviews() {
@@ -234,9 +257,8 @@
     // TODO: To handle multi-touch gestures we may want to move this method to
     // {@link PointerTrackerQueue}.
     private static InputPointers getIncrementalBatchPoints() {
-        final InputPointers pointers = new InputPointers();
-        // TODO: Add a default capacity parameter for the InputPointers' constructor.
         // TODO: Avoid creating a new instance here?
+        final InputPointers pointers = new InputPointers(GestureStroke.DEFAULT_CAPACITY);
         for (final PointerTracker tracker : sTrackers) {
             tracker.mGestureStroke.appendIncrementalBatchPoints(pointers);
         }
@@ -246,9 +268,8 @@
     // TODO: To handle multi-touch gestures we may want to move this method to
     // {@link PointerTrackerQueue}.
     private static InputPointers getAllBatchPoints() {
-        // TODO: Add a default capacity parameter for the InputPointers' constructor.
         // TODO: Avoid creating a new instance here?
-        final InputPointers pointers = new InputPointers();
+        final InputPointers pointers = new InputPointers(GestureStroke.DEFAULT_CAPACITY);
         for (final PointerTracker tracker : sTrackers) {
             tracker.mGestureStroke.appendAllBatchPoints(pointers);
         }
@@ -257,7 +278,7 @@
 
     // TODO: To handle multi-touch gestures we may want to move this method to
     // {@link PointerTrackerQueue}.
-    public static void clearBatchInputPoints() {
+    public static void clearBatchInputPointsOfAllPointerTrackers() {
         for (final PointerTracker tracker : sTrackers) {
             tracker.mGestureStroke.reset();
         }
@@ -534,18 +555,26 @@
             Log.d(TAG, "onEndBatchInput: batchPoints=" + batchPoints.getPointerSize());
         }
         mListener.onEndBatchInput(batchPoints);
-        mInGesture = false;
-        clearBatchInputPoints();
+        clearBatchInputRecognitionStateOfThisPointerTracker();
+        clearBatchInputPointsOfAllPointerTrackers();
+        sWasInGesture = true;
     }
 
     private void abortBatchInput() {
+        clearBatchInputRecognitionStateOfThisPointerTracker();
+        clearBatchInputPointsOfAllPointerTrackers();
+    }
+
+    private void clearBatchInputRecognitionStateOfThisPointerTracker() {
         mIsPossibleGesture = false;
         mInGesture = false;
+        mLastRecognitionPointSize = 0;
+        mLastRecognitionTime = 0;
     }
 
     private boolean updateBatchInputRecognitionState(long eventTime, int size) {
         if (size > mLastRecognitionPointSize
-                && eventTime > mLastRecognitionTime + MIN_RECOGNITION_TIME) {
+                && eventTime > mLastRecognitionTime + MIN_GESTURE_RECOGNITION_TIME) {
             mLastRecognitionPointSize = size;
             mLastRecognitionTime = eventTime;
             return true;
@@ -613,7 +642,7 @@
         if (queue != null && queue.size() == 1) {
             mIsPossibleGesture = false;
             // A gesture should start only from the letter key.
-            if (GESTURE_ON && mIsAlphabetKeyboard && key != null
+            if (sIsGestureEnabled && mIsAlphabetKeyboard && key != null
                     && Keyboard.isLetterCode(key.mCode)) {
                 mIsPossibleGesture = true;
                 mGestureStroke.addPoint(x, y, 0, false);
@@ -656,10 +685,10 @@
     private void onGestureMoveEvent(PointerTracker tracker, int x, int y, long eventTime,
             boolean isHistorical, Key key) {
         final int gestureTime = (int)(eventTime - tracker.getDownTime());
-        if (GESTURE_ON && mIsPossibleGesture) {
+        if (sIsGestureEnabled && mIsPossibleGesture) {
             final GestureStroke stroke = mGestureStroke;
             stroke.addPoint(x, y, gestureTime, isHistorical);
-            if (!mInGesture && stroke.isStartOfAGesture(gestureTime)) {
+            if (!mInGesture && stroke.isStartOfAGesture(gestureTime, sWasInGesture)) {
                 startBatchInput();
             }
         }
@@ -849,10 +878,10 @@
     }
 
     public void onShowMoreKeysPanel(int x, int y, KeyEventHandler handler) {
+        abortBatchInput();
         onLongPressed();
         onDownEvent(x, y, SystemClock.uptimeMillis(), handler);
         mIsShowingMoreKeysPanel = true;
-        abortBatchInput();
     }
 
     public void onLongPressed() {
@@ -931,6 +960,7 @@
         int code = key.mCode;
         callListenerOnCodeInput(key, code, x, y);
         callListenerOnRelease(key, code, false);
+        sWasInGesture = false;
     }
 
     private void printTouchEvent(String title, int x, int y, long eventTime) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
index 14e9948..6f392f1 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/GestureStroke.java
@@ -19,23 +19,28 @@
 import com.android.inputmethod.latin.InputPointers;
 
 public class GestureStroke {
+    public static final int DEFAULT_CAPACITY = 128;
+
     private final int mPointerId;
-    private final InputPointers mInputPointers = new InputPointers();
+    // TODO: Replace this {@link InputPointers} with a set of {@link ScalableIntArray}s.
+    private final InputPointers mInputPointers = new InputPointers(DEFAULT_CAPACITY);
     private float mLength;
     private float mAngle;
-    private int mIncrementalRecognitionPoint;
-    private boolean mHasSharpCorner;
+    private int mIncrementalRecognitionSize;
     private long mLastPointTime;
     private int mLastPointX;
     private int mLastPointY;
 
     private int mMinGestureLength;
+    private int mMinGestureLengthWhileInGesture;
     private int mMinGestureSampleLength;
 
-    // TODO: Tune these parameters.
-    private static final float MIN_GESTURE_DETECTION_RATIO_TO_KEY_WIDTH = 1.0f / 4.0f;
+    // TODO: Move some of these to resource.
+    private static final float MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH = 1.0f;
+    private static final float MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH_WHILE_IN_GESTURE = 0.5f;
+    private static final int MIN_GESTURE_DURATION = 150; // msec
+    private static final int MIN_GESTURE_DURATION_WHILE_IN_GESTURE = 75; // msec
     private static final float MIN_GESTURE_SAMPLING_RATIO_TO_KEY_HEIGHT = 1.0f / 6.0f;
-    private static final int MIN_GESTURE_DURATION = 100; // msec
     private static final float GESTURE_RECOG_SPEED_THRESHOLD = 0.4f; // dip/msec
     private static final float GESTURE_RECOG_CURVATURE_THRESHOLD = (float)(Math.PI / 4.0f);
 
@@ -47,19 +52,27 @@
     }
 
     public void setGestureSampleLength(final int keyWidth, final int keyHeight) {
-        mMinGestureLength = (int)(keyWidth * MIN_GESTURE_DETECTION_RATIO_TO_KEY_WIDTH);
+        // TODO: Find an appropriate base metric for these length. Maybe diagonal length of the key?
+        mMinGestureLength = (int)(keyWidth * MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH);
+        mMinGestureLengthWhileInGesture = (int)(
+                keyWidth * MIN_GESTURE_LENGTH_RATIO_TO_KEY_WIDTH_WHILE_IN_GESTURE);
         mMinGestureSampleLength = (int)(keyHeight * MIN_GESTURE_SAMPLING_RATIO_TO_KEY_HEIGHT);
     }
 
-    public boolean isStartOfAGesture(int downDuration) {
+    public boolean isStartOfAGesture(final int downDuration, final boolean wasInGesture) {
+        // The tolerance of the time duration and the stroke length to detect the start of a
+        // gesture stroke should be eased when the previous input was a gesture input.
+        if (wasInGesture) {
+            return downDuration > MIN_GESTURE_DURATION_WHILE_IN_GESTURE
+                    && mLength > mMinGestureLengthWhileInGesture;
+        }
         return downDuration > MIN_GESTURE_DURATION && mLength > mMinGestureLength;
     }
 
     public void reset() {
         mLength = 0;
         mAngle = 0;
-        mIncrementalRecognitionPoint = 0;
-        mHasSharpCorner = false;
+        mIncrementalRecognitionSize = 0;
         mLastPointTime = 0;
         mInputPointers.reset();
     }
@@ -90,15 +103,11 @@
             mLength += dist;
             final float angle = getAngle(lastX, lastY, x, y);
             if (size > 1) {
-                float curvature = getAngleDiff(angle, mAngle);
+                final float curvature = getAngleDiff(angle, mAngle);
                 if (curvature > GESTURE_RECOG_CURVATURE_THRESHOLD) {
-                    if (size > mIncrementalRecognitionPoint) {
-                        mIncrementalRecognitionPoint = size;
+                    if (size > mIncrementalRecognitionSize) {
+                        mIncrementalRecognitionSize = size;
                     }
-                    mHasSharpCorner = true;
-                }
-                if (!mHasSharpCorner) {
-                    mIncrementalRecognitionPoint = size;
                 }
             }
             mAngle = angle;
@@ -109,7 +118,7 @@
             if (mLastPointTime != 0 && duration > 0) {
                 final float speed = getDistance(mLastPointX, mLastPointY, x, y) / duration;
                 if (speed < GESTURE_RECOG_SPEED_THRESHOLD) {
-                    mIncrementalRecognitionPoint = size;
+                    mIncrementalRecognitionSize = size;
                 }
             }
             updateLastPoint(x, y, time);
@@ -121,7 +130,7 @@
     }
 
     public void appendIncrementalBatchPoints(final InputPointers out) {
-        out.append(mInputPointers, 0, mIncrementalRecognitionPoint);
+        out.append(mInputPointers, 0, mIncrementalRecognitionSize);
     }
 
     private static float getDistance(final int p1x, final int p1y,
diff --git a/java/src/com/android/inputmethod/latin/InputPointers.java b/java/src/com/android/inputmethod/latin/InputPointers.java
index 298e2b2..febabad 100644
--- a/java/src/com/android/inputmethod/latin/InputPointers.java
+++ b/java/src/com/android/inputmethod/latin/InputPointers.java
@@ -20,10 +20,19 @@
 
 // TODO: This class is not thread-safe.
 public class InputPointers {
-    private final ScalableIntArray mXCoordinates = new ScalableIntArray();
-    private final ScalableIntArray mYCoordinates = new ScalableIntArray();
-    private final ScalableIntArray mPointerIds = new ScalableIntArray();
-    private final ScalableIntArray mTimes = new ScalableIntArray();
+    private final int mDefaultCapacity;
+    private final ScalableIntArray mXCoordinates;
+    private final ScalableIntArray mYCoordinates;
+    private final ScalableIntArray mPointerIds;
+    private final ScalableIntArray mTimes;
+
+    public InputPointers(int defaultCapacity) {
+        mDefaultCapacity = defaultCapacity;
+        mXCoordinates = new ScalableIntArray(defaultCapacity);
+        mYCoordinates = new ScalableIntArray(defaultCapacity);
+        mPointerIds = new ScalableIntArray(defaultCapacity);
+        mTimes = new ScalableIntArray(defaultCapacity);
+    }
 
     public void addPointer(int index, int x, int y, int pointerId, int time) {
         mXCoordinates.add(index, x);
@@ -70,10 +79,11 @@
     }
 
     public void reset() {
-        mXCoordinates.reset();
-        mYCoordinates.reset();
-        mPointerIds.reset();
-        mTimes.reset();
+        final int defaultCapacity = mDefaultCapacity;
+        mXCoordinates.reset(defaultCapacity);
+        mYCoordinates.reset(defaultCapacity);
+        mPointerIds.reset(defaultCapacity);
+        mTimes.reset(defaultCapacity);
     }
 
     public int getPointerSize() {
@@ -97,12 +107,11 @@
     }
 
     private static class ScalableIntArray {
-        private static final int DEFAULT_SIZE = BinaryDictionary.MAX_WORD_LENGTH;
         private int[] mArray;
         private int mLength;
 
-        public ScalableIntArray() {
-            reset();
+        public ScalableIntArray(int capacity) {
+            reset(capacity);
         }
 
         public void add(int index, int val) {
@@ -136,8 +145,8 @@
             return mLength;
         }
 
-        public void reset() {
-            mArray = new int[DEFAULT_SIZE];
+        public void reset(int capacity) {
+            mArray = new int[capacity];
             mLength = 0;
         }
 
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index 974af25..bb39ce4 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -45,7 +45,7 @@
     public final String mCommittedWord;
     public final int mSeparatorCode;
     public final CharSequence mPrevWord;
-    public final InputPointers mInputPointers = new InputPointers();
+    public final InputPointers mInputPointers = new InputPointers(BinaryDictionary.MAX_WORD_LENGTH);
 
     private boolean mActive;
 
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index ca9dbaf..6d346d1 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -33,7 +33,7 @@
     private static final int N = BinaryDictionary.MAX_WORD_LENGTH;
 
     private int[] mPrimaryKeyCodes;
-    private final InputPointers mInputPointers = new InputPointers();
+    private final InputPointers mInputPointers = new InputPointers(N);
     private final StringBuilder mTypedWord;
     private CharSequence mAutoCorrection;
     private boolean mIsResumed;
diff --git a/tests/src/com/android/inputmethod/latin/InputPointersTests.java b/tests/src/com/android/inputmethod/latin/InputPointersTests.java
index 524921e..0ab3cb9 100644
--- a/tests/src/com/android/inputmethod/latin/InputPointersTests.java
+++ b/tests/src/com/android/inputmethod/latin/InputPointersTests.java
@@ -19,8 +19,10 @@
 import android.test.AndroidTestCase;
 
 public class InputPointersTests extends AndroidTestCase {
+    private static final int DEFAULT_CAPACITY = 48;
+
     public void testNewInstance() {
-        final InputPointers src = new InputPointers();
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         assertEquals("newInstance size", 0, src.getPointerSize());
         assertNotNull("new instance xCoordinates", src.getXCoordinates());
         assertNotNull("new instance yCoordinates", src.getYCoordinates());
@@ -29,7 +31,7 @@
     }
 
     public void testReset() {
-        final InputPointers src = new InputPointers();
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int[] xCoordinates = src.getXCoordinates();
         final int[] yCoordinates = src.getXCoordinates();
         final int[] pointerIds = src.getXCoordinates();
@@ -44,7 +46,7 @@
     }
 
     public void testAdd() {
-        final InputPointers src = new InputPointers();
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int limit = src.getXCoordinates().length * 2 + 10;
         for (int i = 0; i < limit; i++) {
             src.addPointer(i, i * 2, i * 3, i * 4);
@@ -59,7 +61,7 @@
     }
 
     public void testAddAt() {
-        final InputPointers src = new InputPointers();
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int limit = 1000, step = 100;
         for (int i = 0; i < limit; i += step) {
             src.addPointer(i, i, i * 2, i * 3, i * 4);
@@ -74,12 +76,12 @@
     }
 
     public void testSet() {
-        final InputPointers src = new InputPointers();
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int limit = src.getXCoordinates().length * 2 + 10;
         for (int i = 0; i < limit; i++) {
             src.addPointer(i, i * 2, i * 3, i * 4);
         }
-        final InputPointers dst = new InputPointers();
+        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
         dst.set(src);
         assertEquals("after set size", dst.getPointerSize(), src.getPointerSize());
         assertSame("after set xCoordinates", dst.getXCoordinates(), src.getXCoordinates());
@@ -89,12 +91,12 @@
     }
 
     public void testCopy() {
-        final InputPointers src = new InputPointers();
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int limit = 100;
         for (int i = 0; i < limit; i++) {
             src.addPointer(i, i * 2, i * 3, i * 4);
         }
-        final InputPointers dst = new InputPointers();
+        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
         dst.copy(src);
         assertEquals("after copy size", dst.getPointerSize(), src.getPointerSize());
         assertNotSame("after copy xCoordinates", dst.getXCoordinates(), src.getXCoordinates());
@@ -113,18 +115,18 @@
     }
 
     public void testAppend() {
-        final InputPointers src = new InputPointers();
+        final InputPointers src = new InputPointers(DEFAULT_CAPACITY);
         final int srcLen = 100;
         for (int i = 0; i < srcLen; i++) {
             src.addPointer(i, i * 2, i * 3, i * 4);
         }
         final int dstLen = 50;
-        final InputPointers dst = new InputPointers();
+        final InputPointers dst = new InputPointers(DEFAULT_CAPACITY);
         for (int i = 0; i < dstLen; i++) {
             final int value = -i - 1;
             dst.addPointer(value * 4, value * 3, value * 2, value);
         }
-        final InputPointers dstCopy = new InputPointers();
+        final InputPointers dstCopy = new InputPointers(DEFAULT_CAPACITY);
         dstCopy.copy(dst);
 
         dst.append(src, 0, 0);