1 /* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26 #include "config.h" 27 #include "Hyphenation.h" 28 29 // For external hyphenation library. 30 #include "hyphen.h" 31 #include <androidfw/AssetManager.h> 32 #include <wtf/text/CString.h> 33 #include <wtf/text/WTFString.h> 34 35 extern android::AssetManager* globalAssetManager(); 36 37 using namespace WTF; 38 39 namespace WebCore { 40 41 static HyphenDict* loadHyphenationDictionary() 42 { 43 android::AssetManager* am = globalAssetManager(); 44 // Only support English for now. 45 android::Asset* a = am->open("webkit/hyph_en_US.dic", 46 android::Asset::ACCESS_BUFFER); 47 if (!a) { 48 // Asset webkit/hyph_en_US.dic not found! 49 return 0; 50 } 51 const CString dictContents = String(static_cast<const char*>(a->getBuffer(false)), 52 a->getLength()).utf8(); 53 HyphenDict* dict = hnj_hyphen_load_from_buffer(dictContents.data(), 54 dictContents.length()); 55 delete a; 56 57 return dict; 58 } 59 60 bool canHyphenate(const AtomicString& /* localeIdentifier */) 61 { 62 // FIXME: Check that the locale identifier matches the available dictionary. 63 return true; 64 } 65 66 size_t lastHyphenLocation(const UChar* characters, size_t length, size_t beforeIndex, const AtomicString& /* localeIdentifier */) 67 { 68 static const size_t minWordLen = 5; 69 static const size_t maxWordLen = 100; 70 if (beforeIndex <= 0 || length < minWordLen || length > maxWordLen) 71 return 0; 72 73 static HyphenDict* dict = loadHyphenationDictionary(); 74 if (!dict) 75 return 0; 76 77 char word[maxWordLen]; 78 size_t wordLength = 0; 79 for (size_t i = 0; i < length; ++i) { 80 const UChar ch = characters[i]; 81 // Only English for now. 82 // To really make it language aware, we need something like language 83 // detection or rely on the langAttr in the html element. Though 84 // seems right now the langAttr is not used or quite implemented in 85 // webkit. 86 if (!isASCIIAlpha(ch)) { 87 // Bypass leading spaces. 88 if (isASCIISpace(ch) && !wordLength) 89 continue; 90 return 0; 91 } 92 word[wordLength++] = ch; 93 } 94 if (wordLength < minWordLen) 95 return 0; 96 97 static const int extraBuffer = 5; 98 const int leadingSpacesCount = length - wordLength; 99 char hyphens[maxWordLen + extraBuffer]; 100 if (!hnj_hyphen_hyphenate(dict, word, wordLength, hyphens)) { 101 for (size_t i = beforeIndex - 2 - leadingSpacesCount; i > 0; --i) { 102 if (hyphens[i] & 1) 103 return i + 1 + leadingSpacesCount; 104 } 105 } 106 107 return 0; 108 } 109 110 } // namespace WebCore 111