1/* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.im.app; 19 20import com.android.im.plugin.BrandingResourceIDs; 21 22import android.graphics.drawable.Drawable; 23import android.text.Spannable; 24import android.text.SpannableString; 25import android.text.style.ImageSpan; 26import android.text.util.Linkify; 27 28public class Markup { 29 private BrandingResources mRes; 30 private IntTrie mSmileys; 31 32 public Markup(BrandingResources res) { 33 mRes = res; 34 mSmileys = new IntTrie( 35 res.getStringArray(BrandingResourceIDs.STRING_ARRAY_SMILEY_TEXTS), res.getSmileyIcons()); 36 } 37 38 public final CharSequence markup(CharSequence text) { 39 SpannableString result; 40 41 if (text instanceof SpannableString) { 42 result = (SpannableString) text; 43 } else { 44 result = new SpannableString(text); 45 } 46 47 Linkify.addLinks(result, Linkify.ALL); 48 applyEmoticons(result); 49 50 return result; 51 } 52 53 public final CharSequence applyEmoticons(CharSequence text) { 54 int offset = 0; 55 final int len = text.length(); 56 SpannableString result = null; 57 58 while (offset < len) { 59 int index = offset; 60 IntTrie.Node n = mSmileys.getNode(text.charAt(index++)); 61 int candidate = 0; 62 int lastMatchEnd = -1; 63 64 // Search the trie until we stop matching 65 while (n != null) { 66 // Record the value and position of the longest match 67 if (n.mValue != 0) { 68 candidate = n.mValue; 69 lastMatchEnd = index; 70 } 71 72 // Let's not run off the end of the input 73 if (index >= len) { 74 break; 75 } 76 77 n = n.getNode(text.charAt(index++)); 78 } 79 80 // If we matched a smiley, apply its image over the text 81 if (candidate != 0) { 82 // Lazy-convert the result text to a SpannableString if we have to 83 if (result == null) { 84 if (text instanceof SpannableString) { 85 result = (SpannableString) text; 86 } else { 87 result = new SpannableString(text); 88 text = result; 89 } 90 } 91 Drawable smiley = mRes.getSmileyIcon(candidate); 92 smiley.setBounds(0, 0, smiley.getIntrinsicWidth(), smiley.getIntrinsicHeight()); 93 result.setSpan(new ImageSpan(smiley, ImageSpan.ALIGN_BASELINE), 94 offset, lastMatchEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 95 96 candidate = 0; 97 } 98 99 // if there was a match, start searching for the next one after it 100 // if no match, start at the next character 101 if (lastMatchEnd != -1) { 102 offset = lastMatchEnd; 103 lastMatchEnd = -1; 104 } else { 105 offset++; 106 } 107 } 108 109 // If there were no modifications, return the original string 110 if (result == null) { 111 return text; 112 } 113 114 return result; 115 } 116} 117