Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: content/renderer/hyphenator/hyphenator.cc

Issue 10854245: In-te-grate hy-phen-ator to con-tent. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/renderer/hyphenator/hyphenator.h" 5 #include "content/renderer/hyphenator/hyphenator.h"
6 6
7 #include "base/bind.h"
7 #include "base/file_util.h" 8 #include "base/file_util.h"
8 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h" 11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop_proxy.h"
10 #include "base/string_util.h" 13 #include "base/string_util.h"
11 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
15 #include "content/common/hyphenator_messages.h"
16 #include "content/public/renderer/render_thread.h"
jam 2012/08/23 21:34:29 nit: not needed
Hironori Bono 2012/08/27 06:57:28 Done. I have removed redundant headers. (I do not
17 #include "content/renderer/render_thread_impl.h"
18 #include "ipc/ipc_channel_proxy.h"
12 #include "third_party/hyphen/hyphen.h" 19 #include "third_party/hyphen/hyphen.h"
13 #include "unicode/uscript.h" 20 #include "unicode/uscript.h"
14 21
15 namespace { 22 namespace {
16 23
17 // A class that converts a sequence of UTF-8 characters to UTF-16 ones and holds 24 // A class that converts a sequence of UTF-8 characters to UTF-16 ones and holds
18 // only the length of converted UTF-16 characters. This class is used for 25 // only the length of converted UTF-16 characters. This class is used for
19 // creating a mapping from the position of a UTF-8 string to a position of a 26 // creating a mapping from the position of a UTF-8 string to a position of a
20 // UTF-16 string without unnecessary conversions. Even though the following 27 // UTF-16 string without unnecessary conversions. Even though the following
21 // snippet produces the same mapping, it needs to convert same characters many 28 // snippet produces the same mapping, it needs to convert same characters many
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 UTF16TextLength text_length; 176 UTF16TextLength text_length;
170 hyphen_offsets->clear(); 177 hyphen_offsets->clear();
171 for (size_t i = 0; i < word_utf8_.length(); ++i) { 178 for (size_t i = 0; i < word_utf8_.length(); ++i) {
172 text_length.Append(word_utf8_[i]); 179 text_length.Append(word_utf8_[i]);
173 if (hyphen_vector_[i] & 1) 180 if (hyphen_vector_[i] & 1)
174 hyphen_offsets->push_back(text_length.utf16_length()); 181 hyphen_offsets->push_back(text_length.utf16_length());
175 } 182 }
176 return !hyphen_offsets->empty(); 183 return !hyphen_offsets->empty();
177 } 184 }
178 185
186 // A message filter that listens HyphenatorMsg_SetDictionary messages and
187 // initializes the specified Hyphenator object. This class has a weak reference
188 // to the Hyphenator object so a renderer can delete it while a browser opens a
189 // dictionary file.
190 class MessageFilter : public IPC::ChannelProxy::MessageFilter {
jam 2012/08/23 21:34:29 you don't need a message filter, since you're real
Hironori Bono 2012/08/27 06:57:28 Done. Thanks for your suggestion. The RenderProces
191 public:
192 explicit MessageFilter(base::WeakPtr<content::Hyphenator> hyphenator);
193
194 // IPC::ChannelProxy::MessageFilter implementation.
195 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
196
197 private:
198 virtual ~MessageFilter();
199
200 // Called when a browser sends a HyphenatorMsg_SetDictionary message, i.e.
jam 2012/08/23 21:34:29 nit: by convention we don't comment IPC message ha
Hironori Bono 2012/08/27 06:57:28 Done. Thanks for your comment. (I have removed com
201 // when a browser opens the hyphenation dictionary requested by the
202 // Hyphenator object.
203 void OnSetDictionary(IPC::PlatformFileForTransit rule_file);
204
205 base::WeakPtr<content::Hyphenator> hyphenator_;
206 scoped_refptr<base::MessageLoopProxy> message_loop_;
207 };
208
209 MessageFilter::MessageFilter(base::WeakPtr<content::Hyphenator> hyphenator)
210 : hyphenator_(hyphenator),
211 message_loop_(base::MessageLoopProxy::current()) {
212 }
213
214 MessageFilter::~MessageFilter() {
215 }
216
217 bool MessageFilter::OnMessageReceived(const IPC::Message& message) {
218 bool handled = true;
219 IPC_BEGIN_MESSAGE_MAP(MessageFilter, message)
220 IPC_MESSAGE_HANDLER(HyphenatorMsg_SetDictionary, OnSetDictionary)
221 IPC_MESSAGE_UNHANDLED(handled = false)
222 IPC_END_MESSAGE_MAP()
223 return handled;
224 }
225
226 void MessageFilter::OnSetDictionary(IPC::PlatformFileForTransit rule_file) {
227 base::PlatformFile file =
228 IPC::PlatformFileForTransitToPlatformFile(rule_file);
229 if (file == base::kInvalidPlatformFileValue)
230 return;
231 message_loop_->PostTask(
232 FROM_HERE,
233 base::Bind(&content::Hyphenator::SetDictionary, hyphenator_, file));
234 }
235
179 } // namespace 236 } // namespace
180 237
181 namespace content { 238 namespace content {
182 239
183 Hyphenator::Hyphenator(base::PlatformFile file) 240 Hyphenator::Hyphenator(base::PlatformFile file)
184 : dictionary_(NULL), 241 : dictionary_(NULL),
185 rule_file_(file), 242 rule_file_(file),
186 result_(0) { 243 result_(0),
244 weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
187 } 245 }
188 246
189 Hyphenator::~Hyphenator() { 247 Hyphenator::~Hyphenator() {
190 if (dictionary_) 248 if (dictionary_)
191 hnj_hyphen_free(dictionary_); 249 hnj_hyphen_free(dictionary_);
250 if (rule_file_ != base::kInvalidPlatformFileValue)
251 base::ClosePlatformFile(rule_file_);
192 } 252 }
193 253
194 bool Hyphenator::Initialize() { 254 bool Hyphenator::Initialize() {
195 if (dictionary_) 255 if (dictionary_)
196 return true; 256 return true;
197 257
258 // Attach the dictionary file to the MemoryMappedFile object. When it
259 // succeeds, this class does not have to close this file because it is closed
260 // by the MemoryMappFile class. To prevent this class from closing this file,
tony 2012/08/22 19:05:50 Nit: typo: MemoryMappFile -> MemoryMappedFile
Hironori Bono 2012/08/27 06:57:28 Done. Thanks for noticing my typo.
261 // we reset its handle.
198 rule_map_.reset(new file_util::MemoryMappedFile); 262 rule_map_.reset(new file_util::MemoryMappedFile);
199 if (!rule_map_->Initialize(rule_file_)) 263 if (!rule_map_->Initialize(rule_file_))
200 return false; 264 return false;
265 rule_file_ = base::kInvalidPlatformFileValue;
201 266
202 dictionary_ = hnj_hyphen_load(rule_map_->data(), rule_map_->length()); 267 dictionary_ = hnj_hyphen_load(rule_map_->data(), rule_map_->length());
203 return !!dictionary_; 268 return !!dictionary_;
204 } 269 }
205 270
271 bool Hyphenator::Attach(content::RenderThread* thread, const string16& locale) {
jam 2012/08/23 21:34:29 ditto
Hironori Bono 2012/08/27 06:57:28 Done. I have removed this redundant comment.
272 // Create a new message filter for Hyphenator messages and attach it to the
273 // given thread with a weak reference to this object so a renderer can delete
274 // this object while a browser opens a dictionary.
275 if (!thread)
276 return false;
277 locale_.assign(locale);
278 thread->AddFilter(new MessageFilter(weak_factory_.GetWeakPtr()));
279 return thread->Send(new HyphenatorHostMsg_OpenDictionary(locale));
280 }
281
282 bool Hyphenator::CanHyphenate(const string16& locale) {
283 return !locale_.compare(locale);
284 }
285
206 size_t Hyphenator::ComputeLastHyphenLocation(const string16& word, 286 size_t Hyphenator::ComputeLastHyphenLocation(const string16& word,
207 size_t before_index) { 287 size_t before_index) {
208 if (!dictionary_ || word.empty()) 288 if (!Initialize() || word.empty())
209 return 0; 289 return 0;
210 290
211 // Call the hyphen library to get all hyphenation points, i.e. positions where 291 // Call the hyphen library to get all hyphenation points, i.e. positions where
212 // we can insert hyphens. When WebKit finds a line-break, it calls this 292 // we can insert hyphens. When WebKit finds a line-break, it calls this
213 // function twice or more with the same word to find the best hyphenation 293 // function twice or more with the same word to find the best hyphenation
214 // point. To avoid calling the hyphen library twice or more with the same 294 // point. To avoid calling the hyphen library twice or more with the same
215 // word, we cache the last query. 295 // word, we cache the last query.
216 if (word_ != word) { 296 if (word_ != word) {
217 word_ = word; 297 word_ = word;
218 Query query(word); 298 Query query(word);
219 result_ = query.Hyphenate(dictionary_, &hyphen_offsets_); 299 result_ = query.Hyphenate(dictionary_, &hyphen_offsets_);
220 } 300 }
221 if (!result_) 301 if (!result_)
222 return 0; 302 return 0;
223 for (std::vector<int>::reverse_iterator it = hyphen_offsets_.rbegin(); 303 for (std::vector<int>::reverse_iterator it = hyphen_offsets_.rbegin();
224 it != hyphen_offsets_.rend(); ++it) { 304 it != hyphen_offsets_.rend(); ++it) {
225 if (static_cast<size_t>(*it) < before_index) 305 if (static_cast<size_t>(*it) < before_index)
226 return *it; 306 return *it;
227 } 307 }
228 return 0; 308 return 0;
229 } 309 }
230 310
311 void Hyphenator::SetDictionary(base::PlatformFile rule_file) {
312 // Delete the current dictionary and save the given file to this object. We
313 // initialize the hyphens library the first time when WebKit actually
314 // hyphenates a word, i.e. when WebKit calls the ComputeLastHyphenLocation
315 // function. (WebKit does not always hyphenate words even when it calls the
316 // CanHyphenate function, e.g. WebKit does not have to hyphenate words when it
317 // does not have to break text into lines.)
318 DCHECK(rule_file != base::kInvalidPlatformFileValue);
319 if (dictionary_) {
320 hnj_hyphen_free(dictionary_);
321 dictionary_ = NULL;
322 }
323 rule_map_.reset();
324 rule_file_ = rule_file;
325 }
326
231 } // namespace content 327 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698