• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2005, 2007 Apple Inc. All rights reserved.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public License
15  * along with this library; see the file COPYING.LIB.  If not, write to
16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  *
19  */
20 
21 #include "config.h"
22 #include "break_lines.h"
23 
24 #include "CharacterNames.h"
25 #include "TextBreakIterator.h"
26 
27 #if PLATFORM(MAC)
28 #include <CoreServices/CoreServices.h>
29 #endif
30 
31 namespace WebCore {
32 
isBreakableSpace(UChar ch,bool treatNoBreakSpaceAsBreak)33 static inline bool isBreakableSpace(UChar ch, bool treatNoBreakSpaceAsBreak)
34 {
35     switch (ch) {
36         case ' ':
37         case '\n':
38         case '\t':
39             return true;
40         case noBreakSpace:
41             return treatNoBreakSpaceAsBreak;
42         default:
43             return false;
44     }
45 }
46 
shouldBreakAfter(UChar ch)47 static inline bool shouldBreakAfter(UChar ch)
48 {
49     // Match WinIE's breaking strategy, which is to always allow breaks after hyphens and question marks.
50     // FIXME: it appears that IE behavior is more complex, see <http://bugs.webkit.org/show_bug.cgi?id=17475>.
51     switch (ch) {
52         case '-':
53         case '?':
54 #ifdef ANDROID_LAYOUT
55         // as '/' is used in uri which is always long, we would like to break it
56         case '/':
57 #endif
58         case softHyphen:
59         // FIXME: cases for ideographicComma and ideographicFullStop are a workaround for an issue in Unicode 5.0
60         // which is likely to be resolved in Unicode 5.1 <http://bugs.webkit.org/show_bug.cgi?id=17411>.
61         // We may want to remove or conditionalize this workaround at some point.
62         case ideographicComma:
63         case ideographicFullStop:
64             return true;
65         default:
66             return false;
67     }
68 }
69 
needsLineBreakIterator(UChar ch)70 static inline bool needsLineBreakIterator(UChar ch)
71 {
72     return ch > 0x7F && ch != noBreakSpace;
73 }
74 
75 #if PLATFORM(MAC) && defined(BUILDING_ON_TIGER)
lineBreakLocator()76 static inline TextBreakLocatorRef lineBreakLocator()
77 {
78     TextBreakLocatorRef locator = 0;
79     UCCreateTextBreakLocator(0, 0, kUCTextBreakLineMask, &locator);
80     return locator;
81 }
82 #endif
83 
nextBreakablePosition(const UChar * str,int pos,int len,bool treatNoBreakSpaceAsBreak)84 int nextBreakablePosition(const UChar* str, int pos, int len, bool treatNoBreakSpaceAsBreak)
85 {
86 #if !PLATFORM(MAC) || !defined(BUILDING_ON_TIGER)
87     TextBreakIterator* breakIterator = 0;
88 #endif
89     int nextBreak = -1;
90 
91     UChar lastCh = pos > 0 ? str[pos - 1] : 0;
92     for (int i = pos; i < len; i++) {
93         UChar ch = str[i];
94 
95         if (isBreakableSpace(ch, treatNoBreakSpaceAsBreak) || shouldBreakAfter(lastCh))
96             return i;
97 
98         if (needsLineBreakIterator(ch) || needsLineBreakIterator(lastCh)) {
99             if (nextBreak < i && i) {
100 #if !PLATFORM(MAC) || !defined(BUILDING_ON_TIGER)
101                 if (!breakIterator)
102                     breakIterator = lineBreakIterator(str, len);
103                 if (breakIterator)
104                     nextBreak = textBreakFollowing(breakIterator, i - 1);
105 #else
106                 static TextBreakLocatorRef breakLocator = lineBreakLocator();
107                 if (breakLocator) {
108                     UniCharArrayOffset nextUCBreak;
109                     if (UCFindTextBreak(breakLocator, kUCTextBreakLineMask, 0, str, len, i, &nextUCBreak) == 0)
110                         nextBreak = nextUCBreak;
111                 }
112 #endif
113             }
114             if (i == nextBreak && !isBreakableSpace(lastCh, treatNoBreakSpaceAsBreak))
115                 return i;
116         }
117 
118         lastCh = ch;
119     }
120 
121     return len;
122 }
123 
124 } // namespace WebCore
125