Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e05b3f4b authored by satok's avatar satok
Browse files

Support additional proximity characters

Change-Id: Ifbe0d7e4eafea1926bbce968eae4724dd5769689
parent 8ca325f4
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">

    <string-array name="additional_proximitychars">
        <!-- Empty entry terminates the proximity chars array. -->

        <!-- Additional proximity chars for a -->
        <item>a</item>
        <item>e</item>
        <item>i</item>
        <item>o</item>
        <item>u</item>
        <item></item>
        <!-- Additional proximity chars for e -->
        <item>e</item>
        <item>a</item>
        <item>i</item>
        <item>o</item>
        <item>u</item>
        <item></item>
        <!-- Additional proximity chars for i -->
        <item>i</item>
        <item>a</item>
        <item>e</item>
        <item>o</item>
        <item>u</item>
        <item></item>
        <!-- Additional proximity chars for o -->
        <item>o</item>
        <item>a</item>
        <item>e</item>
        <item>i</item>
        <item>u</item>
        <item></item>
        <!-- Additional proximity chars for u -->
        <item>u</item>
        <item>a</item>
        <item>e</item>
        <item>i</item>
        <item>o</item>
        <item></item>
    </string-array>

</resources>
 No newline at end of file
+23 −0
Original line number Diff line number Diff line
<?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 xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <string-array name="additional_proximitychars">
    </string-array>
</resources>
+38 −3
Original line number Diff line number Diff line
@@ -19,12 +19,14 @@ package com.android.inputmethod.keyboard;
import android.util.Log;

import java.util.Arrays;
import java.util.List;

public class KeyDetector {
    private static final String TAG = KeyDetector.class.getSimpleName();
    private static final boolean DEBUG = false;

    public static final int NOT_A_CODE = -1;
    private static final int ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE = 2;

    private final int mKeyHysteresisDistanceSquared;

@@ -154,8 +156,9 @@ public class KeyDetector {
        return distances.length;
    }

    private void getNearbyKeyCodes(final int[] allCodes) {
    private void getNearbyKeyCodes(final int primaryCode, final int[] allCodes) {
        final Key[] neighborKeys = mNeighborKeys;
        final int maxCodesSize = allCodes.length;

        // allCodes[0] should always have the key code even if it is a non-letter key.
        if (neighborKeys[0] == null) {
@@ -164,7 +167,7 @@ public class KeyDetector {
        }

        int numCodes = 0;
        for (int j = 0; j < neighborKeys.length && numCodes < allCodes.length; j++) {
        for (int j = 0; j < neighborKeys.length && numCodes < maxCodesSize; j++) {
            final Key key = neighborKeys[j];
            if (key == null)
                break;
@@ -174,6 +177,38 @@ public class KeyDetector {
                continue;
            allCodes[numCodes++] = code;
        }
        if (maxCodesSize <= numCodes) {
            return;
        }
        if (primaryCode != NOT_A_CODE) {
            final List<Integer> additionalChars =
                    mKeyboard.getAdditionalProximityChars().get(primaryCode);
            if (additionalChars == null || additionalChars.size() == 0) {
                return;
            }
            int currentCodesSize = numCodes;
            allCodes[numCodes++] = ADDITIONAL_PROXIMITY_CHAR_DELIMITER_CODE;
            if (maxCodesSize <= numCodes) {
                return;
            }
            // TODO: This is O(N^2). Assuming additionalChars.size() is up to 4 or 5.
            for (int i = 0; i < additionalChars.size(); ++i) {
                final int additionalChar = additionalChars.get(i);
                boolean contains = false;
                for (int j = 0; j < currentCodesSize; ++j) {
                    if (additionalChar == allCodes[j]) {
                        contains = true;
                        break;
                    }
                }
                if (!contains) {
                    allCodes[numCodes++] = additionalChar;
                    if (maxCodesSize <= numCodes) {
                        return;
                    }
                }
            }
        }
    }

    /**
@@ -205,7 +240,7 @@ public class KeyDetector {
        }

        if (allCodes != null && allCodes.length > 0) {
            getNearbyKeyCodes(allCodes);
            getNearbyKeyCodes(primaryKey != null ? primaryKey.mCode : NOT_A_CODE, allCodes);
            if (DEBUG) {
                Log.d(TAG, "x=" + x + " y=" + y
                        + " primary=" + printableCode(primaryKey)
+35 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
@@ -38,10 +39,12 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@@ -130,6 +133,8 @@ public class Keyboard {

    private final ProximityInfo mProximityInfo;

    public final Map<Integer, List<Integer>> mAdditionalProximityChars;

    public Keyboard(Params params) {
        mId = params.mId;
        mThemeId = params.mThemeId;
@@ -146,10 +151,12 @@ public class Keyboard {
        mKeys = Collections.unmodifiableSet(params.mKeys);
        mShiftKeys = Collections.unmodifiableSet(params.mShiftKeys);
        mIconsSet = params.mIconsSet;
        mAdditionalProximityChars = params.mAdditionalProximityChars;

        mProximityInfo = new ProximityInfo(
                params.GRID_WIDTH, params.GRID_HEIGHT, mOccupiedWidth, mOccupiedHeight,
                mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection);
                mMostCommonKeyWidth, mMostCommonKeyHeight, mKeys, params.mTouchPositionCorrection,
                params.mAdditionalProximityChars);
    }

    public ProximityInfo getProximityInfo() {
@@ -227,6 +234,9 @@ public class Keyboard {
        public final Set<Key> mKeys = new HashSet<Key>();
        public final Set<Key> mShiftKeys = new HashSet<Key>();
        public final KeyboardIconsSet mIconsSet = new KeyboardIconsSet();
        // TODO: Should be in Key instead of Keyboard.Params?
        public final Map<Integer, List<Integer>> mAdditionalProximityChars =
                new HashMap<Integer, List<Integer>>();

        public KeyboardSet.KeysCache mKeysCache;

@@ -358,6 +368,10 @@ public class Keyboard {
        return mProximityInfo.getNearestKeys(adjustedX, adjustedY);
    }

    public Map<Integer, List<Integer>> getAdditionalProximityChars() {
        return mAdditionalProximityChars;
    }

    public static String printableCode(int code) {
        switch (code) {
        case CODE_SHIFT: return "shift";
@@ -614,6 +628,7 @@ public class Keyboard {
            mParams = params;

            setTouchPositionCorrectionData(context, params);
            setAdditionalProximityChars(context, params);

            params.GRID_WIDTH = res.getInteger(R.integer.config_keyboard_grid_width);
            params.GRID_HEIGHT = res.getInteger(R.integer.config_keyboard_grid_height);
@@ -636,6 +651,25 @@ public class Keyboard {
            params.mTouchPositionCorrection.load(data);
        }

        private static void setAdditionalProximityChars(Context context, Params params) {
            final String[] additionalChars =
                    context.getResources().getStringArray(R.array.additional_proximitychars);
            int currentPrimaryIndex = 0;
            for (int i = 0; i < additionalChars.length; ++i) {
                final String additionalChar = additionalChars[i];
                if (TextUtils.isEmpty(additionalChar)) {
                    currentPrimaryIndex = 0;
                } else if (currentPrimaryIndex == 0) {
                    currentPrimaryIndex = additionalChar.charAt(0);
                    params.mAdditionalProximityChars.put(
                            currentPrimaryIndex, new ArrayList<Integer>());
                } else if (currentPrimaryIndex != 0) {
                    final int c = additionalChar.charAt(0);
                    params.mAdditionalProximityChars.get(currentPrimaryIndex).add(c);
                }
            }
        }

        public void setAutoGenerate(KeyboardSet.KeysCache keysCache) {
            mParams.mKeysCache = keysCache;
        }
+41 −9
Original line number Diff line number Diff line
@@ -24,6 +24,9 @@ import com.android.inputmethod.latin.spellcheck.SpellCheckerProximityInfo;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class ProximityInfo {
@@ -44,7 +47,8 @@ public class ProximityInfo {
    private final Key[][] mGridNeighbors;

    ProximityInfo(int gridWidth, int gridHeight, int minWidth, int height, int keyWidth,
            int keyHeight, Set<Key> keys, TouchPositionCorrection touchPositionCorrection) {
            int keyHeight, Set<Key> keys, TouchPositionCorrection touchPositionCorrection,
            Map<Integer, List<Integer>> additionalProximityChars) {
        mGridWidth = gridWidth;
        mGridHeight = gridHeight;
        mGridSize = mGridWidth * mGridHeight;
@@ -58,20 +62,20 @@ public class ProximityInfo {
            // No proximity required. Keyboard might be mini keyboard.
            return;
        }
        computeNearestNeighbors(keyWidth, keys, touchPositionCorrection);
        computeNearestNeighbors(keyWidth, keys, touchPositionCorrection, additionalProximityChars);
    }

    public static ProximityInfo createDummyProximityInfo() {
        return new ProximityInfo(1, 1, 1, 1, 1, 1, Collections.<Key>emptySet(), null);
        return new ProximityInfo(1, 1, 1, 1, 1, 1, Collections.<Key> emptySet(),
                null, Collections.<Integer, List<Integer>> emptyMap());
    }

    public static ProximityInfo createSpellCheckerProximityInfo(final int[] proximity) {
        final ProximityInfo spellCheckerProximityInfo = createDummyProximityInfo();
        spellCheckerProximityInfo.mNativeProximityInfo =
                spellCheckerProximityInfo.setProximityInfoNative(
                        SpellCheckerProximityInfo.ROW_SIZE,
                        480, 300, 11, 3, proximity,
                        0, null, null, null, null, null, null, null, null);
                        SpellCheckerProximityInfo.ROW_SIZE, 480, 300, 11, 3, proximity, 0,
                        null, null, null, null, null, null, null, null);
        return spellCheckerProximityInfo;
    }

@@ -79,11 +83,13 @@ public class ProximityInfo {
    static {
        Utils.loadNativeLibrary();
    }

    private native long setProximityInfoNative(int maxProximityCharsSize, int displayWidth,
            int displayHeight, int gridWidth, int gridHeight, int[] proximityCharsArray,
            int keyCount, int[] keyXCoordinates, int[] keyYCoordinates,
            int[] keyWidths, int[] keyHeights, int[] keyCharCodes,
            float[] sweetSpotCenterX, float[] sweetSpotCenterY, float[] sweetSpotRadii);

    private native void releaseProximityInfoNative(long nativeProximityInfo);

    private final void setProximityInfo(Key[][] gridNeighborKeys, int keyboardWidth,
@@ -168,7 +174,12 @@ public class ProximityInfo {
    }

    private void computeNearestNeighbors(int defaultWidth, Set<Key> keys,
            TouchPositionCorrection touchPositionCorrection) {
            TouchPositionCorrection touchPositionCorrection,
            Map<Integer, List<Integer>> additionalProximityChars) {
        final Map<Integer, Key> keyCodeMap = new HashMap<Integer, Key>();
        for (final Key key : keys) {
            keyCodeMap.put(key.mCode, key);
        }
        final int thresholdBase = (int) (defaultWidth * SEARCH_DISTANCE);
        final int threshold = thresholdBase * thresholdBase;
        // Round-up so we don't have any pixels outside the grid
@@ -186,6 +197,27 @@ public class ProximityInfo {
                        neighborKeys[count++] = key;
                    }
                }
                int currentCodesSize = count;
                for (int i = 0; i < currentCodesSize; ++i) {
                    final int c = neighborKeys[i].mCode;
                    final List<Integer> additionalChars = additionalProximityChars.get(c);
                    if (additionalChars == null || additionalChars.size() == 0) {
                        continue;
                    }
                    for (int j = 0; j < additionalChars.size(); ++j) {
                        final int additionalChar = additionalChars.get(j);
                        boolean contains = false;
                        for (int k = 0; k < count; ++k) {
                            if(additionalChar == neighborKeys[k].mCode) {
                                contains = true;
                                break;
                            }
                        }
                        if (!contains) {
                            neighborKeys[count++] = keyCodeMap.get(additionalChar);
                        }
                    }
                }
                mGridNeighbors[(y / mCellHeight) * mGridWidth + (x / mCellWidth)] =
                        Arrays.copyOfRange(neighborKeys, 0, count);
            }
Loading