1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30 #include "renderer/win32/win32_renderer_util.h"
31
32 #define _ATL_NO_AUTOMATIC_NAMESPACE
33 #define _WTL_NO_AUTOMATIC_NAMESPACE
34 #include <atlbase.h>
35 #include <atlapp.h>
36 #include <atlgdi.h>
37 #include <atlmisc.h>
38
39 #include "base/logging.h"
40 #include "base/mmap.h"
41 #include "base/util.h"
42 #include "base/win_font_test_helper.h"
43 #include "protocol/renderer_command.pb.h"
44 #include "renderer/win32/win32_font_util.h"
45 #include "testing/base/public/gunit.h"
46
47 // Following functions should be placed in global namespace for Koenig look-up
48 // trick used in GTest.
PrintTo(const POINT & point,::std::ostream * os)49 void PrintTo(const POINT &point, ::std::ostream* os) {
50 *os << "(" << point.x << ", " << point.y << ")";
51 }
PrintTo(const RECT & rect,::std::ostream * os)52 void PrintTo(const RECT &rect, ::std::ostream* os) {
53 *os << "(" << rect.left << ", " << rect.top << ", " << rect.right << ", "
54 << rect.bottom << ")";
55 }
56
57 namespace WTL {
58
59 // These functions should be placed in WTL namespace for Koenig look-up
60 // trick used in GTest.
PrintTo(const CPoint & point,::std::ostream * os)61 void PrintTo(const CPoint &point, ::std::ostream* os) {
62 *os << "(" << point.x << ", " << point.y << ")";
63 }
PrintTo(const CRect & rect,::std::ostream * os)64 void PrintTo(const CRect &rect, ::std::ostream* os) {
65 *os << "(" << rect.left << ", " << rect.top << ", " << rect.right << ", "
66 << rect.bottom << ")";
67 }
68
69 } // namespace WTL
70
71 namespace mozc {
72 namespace renderer {
73 namespace win32 {
74 typedef mozc::commands::Annotation Annotation;
75 typedef mozc::commands::CandidateList CandidateList;
76 typedef mozc::commands::CandidateWord CandidateWord;
77 typedef mozc::commands::Candidates Candidates;
78 typedef mozc::commands::Candidates::Candidate Candidate;
79 typedef mozc::commands::Footer Footer;
80 typedef mozc::commands::Output Output;
81 typedef mozc::commands::Preedit Preedit;
82 typedef mozc::commands::Preedit_Segment Segment;
83 typedef mozc::commands::RendererCommand RendererCommand;
84 typedef mozc::commands::RendererCommand_ApplicationInfo ApplicationInfo;
85 typedef mozc::commands::RendererCommand_CandidateForm CandidateForm;
86 typedef mozc::commands::RendererCommand_CaretInfo CaretInfo;
87 typedef mozc::commands::RendererCommand_CharacterPosition CharacterPosition;
88 typedef mozc::commands::RendererCommand_CompositionForm CompositionForm;
89 typedef mozc::commands::RendererCommand_Point Point;
90 typedef mozc::commands::RendererCommand_Rectangle Rectangle;
91 typedef mozc::commands::RendererCommand_WinLogFont WinLogFont;
92 typedef mozc::commands::Status Status;
93
94 namespace {
95
96 using WTL::CDC;
97 using WTL::CFont;
98 using WTL::CFontHandle;
99 using WTL::CLogFont;
100 using WTL::CPoint;
101 using WTL::CRect;
102 using WTL::CSize;
103 using WTL::PrintTo;
104
105 const int kDefaultFontHeightInPixel = 18;
106 const wchar_t kWindowClassName[] = L"Mozc: Default Window Class Name";
107
108 #define EXPECT_COMPOSITION_WINDOW_LAYOUT( \
109 window_pos_left, window_pos_top, window_pos_right, window_pos_bottom, \
110 text_left, text_top, text_right, text_bottom, base_x, base_y, \
111 caret_left, caret_top, caret_right, caret_bottom, font, window_layout) \
112 do { \
113 EXPECT_EQ(CRect((window_pos_left), (window_pos_top), \
114 (window_pos_right), (window_pos_bottom)), \
115 (window_layout).window_position_in_screen_coordinate); \
116 EXPECT_EQ((font), layout.log_font); \
117 EXPECT_EQ(CRect((text_left), (text_top), \
118 (text_right), (text_bottom)), \
119 (window_layout).text_area); \
120 EXPECT_EQ(CPoint((base_x), (base_y)), (window_layout).base_position); \
121 EXPECT_EQ(CRect((caret_left), (caret_top), \
122 (caret_right), (caret_bottom)), \
123 (window_layout).caret_rect); \
124 } while (false)
125
126 #define EXPECT_NON_EXCLUDE_CANDIDATE_WINDOW_LAYOUT( \
127 target_x, target_y, layout) \
128 do { \
129 EXPECT_TRUE((layout).initialized()); \
130 EXPECT_FALSE((layout).has_exclude_region()); \
131 EXPECT_EQ(CPoint((target_x), (target_y)), (layout).position()); \
132 } while (false)
133
134 #define EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT( \
135 target_x, target_y, exclude_rect_left, exclude_rect_top, \
136 exclude_rect_right, exclude_rect_bottom, layout) \
137 do { \
138 EXPECT_TRUE((layout).initialized()); \
139 EXPECT_TRUE((layout).has_exclude_region()); \
140 EXPECT_EQ(CPoint((target_x), (target_y)), (layout).position()); \
141 EXPECT_EQ(CRect((exclude_rect_left), (exclude_rect_top), \
142 (exclude_rect_right), (exclude_rect_bottom)), \
143 (layout).exclude_region()); \
144 } while (false)
145
CreateWindowEmulator(const std::wstring & class_name,const RECT & window_rect,const POINT & client_area_offset,const SIZE & client_area_size,double scale_factor,HWND * hwnd)146 WindowPositionEmulator *CreateWindowEmulator(
147 const std::wstring &class_name, const RECT &window_rect,
148 const POINT &client_area_offset, const SIZE &client_area_size,
149 double scale_factor, HWND *hwnd) {
150 WindowPositionEmulator *emulator = WindowPositionEmulator::Create();
151 *hwnd = emulator->RegisterWindow(
152 class_name, window_rect, client_area_offset,
153 client_area_size, scale_factor);
154 return emulator;
155 }
156
CreateWindowEmulatorWithDPIScaling(double scale_factor,HWND * hwnd)157 WindowPositionEmulator *CreateWindowEmulatorWithDPIScaling(
158 double scale_factor, HWND *hwnd) {
159 const CPoint kClientOffset(8, 42);
160 const CSize kClientSize(2000, 1000);
161 const CRect kWindowRect(500, 500, 2516, 1550);
162
163 return CreateWindowEmulator(kWindowClassName, kWindowRect,
164 kClientOffset, kClientSize, scale_factor, hwnd);
165 }
166
CreateWindowEmulatorWithClassName(const std::wstring & class_name,HWND * hwnd)167 WindowPositionEmulator *CreateWindowEmulatorWithClassName(
168 const std::wstring &class_name, HWND *hwnd) {
169 const CPoint kClientOffset(8, 42);
170 const CSize kClientSize(2000, 1000);
171 const CRect kWindowRect(500, 500, 2516, 1550);
172 const double kScaleFactor = 1.0;
173
174 return CreateWindowEmulator(class_name, kWindowRect,
175 kClientOffset, kClientSize, kScaleFactor, hwnd);
176 }
177
178 class AppInfoUtil {
179 public:
SetBasicApplicationInfo(ApplicationInfo * app_info,HWND hwnd,int visibility)180 static void SetBasicApplicationInfo(
181 ApplicationInfo *app_info, HWND hwnd, int visibility) {
182 app_info->set_ui_visibilities(visibility);
183 app_info->set_process_id(1234);
184 app_info->set_thread_id(5678);
185 app_info->set_target_window_handle(
186 reinterpret_cast<uint32>(hwnd));
187 app_info->set_input_framework(ApplicationInfo::IMM32);
188 }
189
SetCompositionFont(ApplicationInfo * app_info,int height,int width,int escapement,int orientation,int weight,int char_set,int out_precision,int clip_precision,int quality,int pitch_and_family,const char * face_name)190 static void SetCompositionFont(
191 ApplicationInfo *app_info, int height, int width, int escapement,
192 int orientation, int weight, int char_set, int out_precision,
193 int clip_precision, int quality, int pitch_and_family,
194 const char *face_name) {
195 WinLogFont *font = app_info->mutable_composition_font();
196 font->set_height(height);
197 font->set_width(width);
198 font->set_escapement(escapement);
199 font->set_orientation(orientation);
200 font->set_weight(weight);
201 font->set_italic(false);
202 font->set_underline(false);
203 font->set_strike_out(false);
204 font->set_char_set(char_set);
205 font->set_out_precision(out_precision);
206 font->set_clip_precision(clip_precision);
207 font->set_quality(quality);
208 font->set_pitch_and_family(pitch_and_family);
209 font->set_face_name(face_name);
210 }
211
SetCompositionForm(ApplicationInfo * app_info,uint32 style_bits,int x,int y,int left,int top,int right,int bottom)212 static void SetCompositionForm(
213 ApplicationInfo *app_info, uint32 style_bits,
214 int x, int y, int left, int top, int right, int bottom) {
215 CompositionForm *form = app_info->mutable_composition_form();
216 form->set_style_bits(style_bits);
217 Point *current_position = form->mutable_current_position();
218 Rectangle *area = form->mutable_area();
219 current_position->set_x(x);
220 current_position->set_y(y);
221 area->set_left(left);
222 area->set_top(top);
223 area->set_right(right);
224 area->set_bottom(bottom);
225 }
226
SetCandidateForm(ApplicationInfo * app_info,uint32 style_bits,int x,int y,int left,int top,int right,int bottom)227 static void SetCandidateForm(
228 ApplicationInfo *app_info, uint32 style_bits,
229 int x, int y, int left, int top, int right, int bottom) {
230 CandidateForm *form = app_info->mutable_candidate_form();
231 form->set_style_bits(style_bits);
232 Point *current_pos = form->mutable_current_position();
233 current_pos->set_x(x);
234 current_pos->set_y(y);
235 Rectangle *area = form->mutable_area();
236 area->set_left(left);
237 area->set_top(top);
238 area->set_right(right);
239 area->set_bottom(bottom);
240 }
241
SetCaretInfo(ApplicationInfo * app_info,bool blinking,int left,int top,int right,int bottom,HWND target_window_handle)242 static void SetCaretInfo(
243 ApplicationInfo *app_info, bool blinking, int left, int top,
244 int right, int bottom, HWND target_window_handle) {
245 CaretInfo *info = app_info->mutable_caret_info();
246 info->set_blinking(blinking);
247 info->set_target_window_handle(
248 reinterpret_cast<uint32>(target_window_handle));
249 Rectangle *rect = info->mutable_caret_rect();
250 rect->set_left(left);
251 rect->set_top(top);
252 rect->set_right(right);
253 rect->set_bottom(bottom);
254 }
255
SetCompositionTarget(ApplicationInfo * app_info,int position,int x,int y,uint32 line_height,int left,int top,int right,int bottom)256 static void SetCompositionTarget(
257 ApplicationInfo *app_info, int position, int x, int y,
258 uint32 line_height, int left, int top, int right, int bottom) {
259 CharacterPosition *char_pos = app_info->mutable_composition_target();
260 char_pos->set_position(position);
261 char_pos->mutable_top_left()->set_x(x);
262 char_pos->mutable_top_left()->set_y(y);
263 char_pos->set_line_height(line_height);
264 Rectangle *area = char_pos->mutable_document_area();
265 area->set_left(left);
266 area->set_top(top);
267 area->set_right(right);
268 area->set_bottom(bottom);
269 }
270
271 private:
272 DISALLOW_IMPLICIT_CONSTRUCTORS(AppInfoUtil);
273 };
274
275 } // namespace
276
277 class Win32RendererUtilTest : public testing::Test {
278 public:
GetMonospacedFontFaceForTest()279 static string GetMonospacedFontFaceForTest() {
280 return WinFontTestHelper::GetIPAexGothicFontName();
281 }
282
GetPropotionalFontFaceForTest()283 static string GetPropotionalFontFaceForTest() {
284 return WinFontTestHelper::GetIPAexMinchoFontName();
285 }
286
GetFont(bool is_proportional,bool is_vertical)287 static CLogFont GetFont(bool is_proportional, bool is_vertical) {
288 std::wstring font_face;
289 Util::UTF8ToWide((is_proportional ? GetPropotionalFontFaceForTest()
290 : GetMonospacedFontFaceForTest()),
291 &font_face);
292 if (is_vertical) {
293 font_face = L"@" + font_face;
294 }
295
296 CLogFont font;
297 font.lfWeight = FW_NORMAL;
298 font.lfCharSet = DEFAULT_CHARSET;
299
300 // We use negative value here to specify absolute font height in pixel,
301 // assuming the mapping mode is MM_TEXT.
302 // http://msdn.microsoft.com/en-us/library/ms901140.aspx
303 font.lfHeight = -kDefaultFontHeightInPixel;
304
305 const errno_t error = wcscpy_s(font.lfFaceName, font_face.c_str());
306 CHECK_EQ(0, error) << "wcscpy_s failed";
307
308 if (is_vertical) {
309 // 2700 means the text grows from top to bottom.
310 font.lfEscapement = 2700;
311 font.lfOrientation = 2700;
312 }
313
314 return font;
315 }
316
CreateDefaultGUIFontEmulator()317 static SystemPreferenceInterface *CreateDefaultGUIFontEmulator() {
318 CLogFont font = GetFont(true, false);
319 font.lfHeight = 18;
320 font.lfWidth = 0;
321 return SystemPreferenceFactory::CreateMock(font);
322 }
323
GetTestMessageWithCompositeGlyph(int num_repeat)324 static std::wstring GetTestMessageWithCompositeGlyph(int num_repeat) {
325 std::wstring message;
326 for (size_t i = 0; i < num_repeat; ++i) {
327 // "ぱ"
328 message += L'\u3071';
329 message += L'\u309a';
330 }
331 return message;
332 }
333
GetTestMessageForMonospaced()334 static std::wstring GetTestMessageForMonospaced() {
335 std::wstring w_path;
336 const char kMessage[] = "熊本県阿蘇郡南阿蘇村大字中松南阿蘇水の生まれる里白水高原駅";
337 std::wstring w_message;
338 Util::UTF8ToWide(kMessage, &w_message);
339 return w_message;
340 }
341
GetTestMessageForProportional()342 static std::wstring GetTestMessageForProportional() {
343 std::wstring w_path;
344 const char kMessage[] =
345 "This open-source project originates from Google 日本語入力.";
346 std::wstring w_message;
347 Util::UTF8ToWide(kMessage, &w_message);
348 return w_message;
349 }
350
351 // Initializes |command| for unit test. Parameters to be set are based on
352 // an actual application which supports both horizontal and vertical writing.
SetRenderereCommandForTest(bool use_proportional_font,bool has_candidates,bool is_vertical,int cursor_offset,HWND hwnd,RendererCommand * command)353 static void SetRenderereCommandForTest(
354 bool use_proportional_font, bool has_candidates,
355 bool is_vertical, int cursor_offset, HWND hwnd,
356 RendererCommand *command) {
357 command->Clear();
358 command->set_type(RendererCommand::UPDATE);
359 command->set_visible(true);
360 {
361 Output *output = command->mutable_output();
362 output->set_id(123456789);
363 output->set_mode(commands::HIRAGANA);
364 output->set_consumed(true);
365 Preedit *preedit = output->mutable_preedit();
366 preedit->set_cursor(22);
367 {
368 Segment *segment = preedit->add_segment();
369 segment->set_annotation(Segment::UNDERLINE);
370 segment->set_value("これは");
371 segment->set_value_length(3);
372 segment->set_key("これは");
373 }
374 {
375 Segment *segment = preedit->add_segment();
376 segment->set_annotation(Segment::UNDERLINE);
377 segment->set_value("、");
378 segment->set_value_length(1);
379 segment->set_key("、");
380 }
381 {
382 Segment *segment = preedit->add_segment();
383 segment->set_annotation(Segment::HIGHLIGHT);
384 segment->set_value("Google");
385 segment->set_value_length(6);
386 segment->set_key("Google");
387 }
388 {
389 Segment *segment = preedit->add_segment();
390 segment->set_annotation(Segment::UNDERLINE);
391 segment->set_value("日本語入力の");
392 segment->set_value_length(6);
393 segment->set_key("にほんごにゅうりょくの");
394 }
395 {
396 Segment *segment = preedit->add_segment();
397 segment->set_annotation(Segment::UNDERLINE);
398 segment->set_value("Testです");
399 segment->set_value_length(6);
400 segment->set_key("Testです");
401 }
402 preedit->set_highlighted_position(3);
403
404 if (has_candidates) {
405 Candidates *candidates = output->mutable_candidates();
406 candidates->set_focused_index(0);
407 candidates->set_size(2);
408 {
409 Candidate *candidate = candidates->add_candidate();
410 candidate->set_index(0);
411 candidate->set_value("Google");
412 Annotation *annotation = candidate->mutable_annotation();
413 annotation->set_description("[半] アルファベット");
414 annotation->set_shortcut("1");
415 candidate->set_id(0);
416 }
417 {
418 Candidate *candidate = candidates->add_candidate();
419 candidate->set_index(1);
420 candidate->set_value("そのほかの文字種");
421 Annotation *annotation = candidate->mutable_annotation();
422 annotation->set_shortcut("2");
423 candidate->set_id(-11);
424 }
425 candidates->set_position(4);
426 candidates->set_category(commands::CONVERSION);
427 candidates->set_display_type(commands::MAIN);
428 Footer *footer = candidates->mutable_footer();
429 footer->set_index_visible(true);
430 footer->set_logo_visible(true);
431 footer->set_sub_label("build 000");
432 }
433 }
434
435 SetApplicationInfoForTest(
436 use_proportional_font, is_vertical, cursor_offset, hwnd, command);
437 }
438
439 // Initializes |command| for unit test. Parameters to be set are based on
440 // an actual application which supports both horizontal and vertical writing.
SetRenderereCommandForSuggestTest(bool use_proportional_font,bool is_vertical,int cursor_offset,HWND hwnd,RendererCommand * command)441 static void SetRenderereCommandForSuggestTest(
442 bool use_proportional_font, bool is_vertical, int cursor_offset,
443 HWND hwnd, RendererCommand *command) {
444 command->Clear();
445 command->set_type(RendererCommand::UPDATE);
446 command->set_visible(true);
447 {
448 Output *output = command->mutable_output();
449 output->set_id(123456789);
450 output->set_mode(commands::HIRAGANA);
451 output->set_consumed(true);
452 {
453 Preedit *preedit = output->mutable_preedit();
454 preedit->set_cursor(7);
455 {
456 Segment *segment = preedit->add_segment();
457 segment->set_annotation(Segment::UNDERLINE);
458 segment->set_value("ねこをかいたい");
459 segment->set_value_length(7);
460 segment->set_key("ねこをかいたい");
461 }
462 }
463 {
464 Candidates *candidates = output->mutable_candidates();
465 candidates->set_size(1);
466 {
467 Candidate *candidate = candidates->add_candidate();
468 candidate->set_index(0);
469 candidate->set_value("猫を飼いたい");
470 {
471 Annotation *annotation = candidate->mutable_annotation();
472 annotation->set_description("Real-time Conversion");
473 candidate->set_id(0);
474 }
475 }
476 candidates->set_position(0);
477 candidates->set_category(commands::SUGGESTION);
478 candidates->set_display_type(commands::MAIN);
479 {
480 Footer *footer = candidates->mutable_footer();
481 footer->set_sub_label("build 754");
482 }
483 }
484 }
485
486 SetApplicationInfoForTest(
487 use_proportional_font, is_vertical, cursor_offset, hwnd, command);
488 }
489
490 // Initializes |command| for unit tests of caret. Parameters to be set are
491 // based on an actual application which supports both horizontal and vertical
492 // writing.
SetRenderereCommandForCaretTest(bool use_proportional_font,bool is_vertical,int num_characters,int cursor_position_in_preedit,int cursor_offset,HWND hwnd,RendererCommand * command)493 static void SetRenderereCommandForCaretTest(
494 bool use_proportional_font, bool is_vertical, int num_characters,
495 int cursor_position_in_preedit, int cursor_offset, HWND hwnd,
496 RendererCommand *command) {
497 command->Clear();
498 command->set_type(RendererCommand::UPDATE);
499 command->set_visible(true);
500 {
501 Output *output = command->mutable_output();
502 output->set_id(123456789);
503 output->set_mode(commands::HIRAGANA);
504 output->set_consumed(true);
505 Preedit *preedit = output->mutable_preedit();
506 preedit->set_cursor(cursor_position_in_preedit);
507 {
508 Segment *segment = preedit->add_segment();
509 segment->set_annotation(Segment::UNDERLINE);
510 string value;
511 for (size_t i = 0; i < num_characters; ++i) {
512 value.append("あ");
513 }
514 segment->set_value(value);
515 segment->set_value_length(num_characters);
516 segment->set_key(value);
517 }
518 }
519
520 SetApplicationInfoForTest(
521 use_proportional_font, is_vertical, cursor_offset, hwnd, command);
522 }
523
524 // Initializes |command| for unit tests of caret. Parameters to be set are
525 // based on an actual application which supports both horizontal and vertical
526 // writing.
SetRenderereCommandForSurrogatePair(bool use_proportional_font,bool is_vertical,int cursor_offset,HWND hwnd,RendererCommand * command)527 static void SetRenderereCommandForSurrogatePair(bool use_proportional_font,
528 bool is_vertical,
529 int cursor_offset, HWND hwnd,
530 RendererCommand *command) {
531 command->Clear();
532 command->set_type(RendererCommand::UPDATE);
533 command->set_visible(true);
534 {
535 Output *output = command->mutable_output();
536 output->set_id(123456789);
537 output->set_mode(commands::HIRAGANA);
538 output->set_consumed(true);
539 {
540 Preedit *preedit = output->mutable_preedit();
541 preedit->set_cursor(8);
542 {
543 Segment *segment = preedit->add_segment();
544 segment->set_annotation(Segment::UNDERLINE);
545 segment->set_value("咤");
546 segment->set_value_length(2);
547 segment->set_key("しった");
548 }
549 {
550 Segment *segment = preedit->add_segment();
551 segment->set_annotation(Segment::UNDERLINE);
552 segment->set_value("咤");
553 segment->set_value_length(2);
554 segment->set_key("しった");
555 }
556 {
557 Segment *segment = preedit->add_segment();
558 segment->set_annotation(Segment::HIGHLIGHT);
559 segment->set_value("咤");
560 segment->set_value_length(2);
561 segment->set_key("しった");
562 }
563 {
564 Segment *segment = preedit->add_segment();
565 segment->set_annotation(Segment::UNDERLINE);
566 segment->set_value("咤");
567 segment->set_value_length(2);
568 segment->set_key("しった");
569 }
570 preedit->set_highlighted_position(4);
571 }
572 {
573 Candidates *candidates = output->mutable_candidates();
574 candidates->set_focused_index(0);
575 candidates->set_size(5);
576 {
577 Candidate *candidate = candidates->add_candidate();
578 candidate->set_index(0);
579 candidate->set_value("咤");
580 {
581 Annotation *annotation = candidate->mutable_annotation();
582 annotation->set_shortcut("1");
583 }
584 candidate->set_id(0);
585 }
586 {
587 Candidate *candidate = candidates->add_candidate();
588 candidate->set_index(1);
589 candidate->set_value("知った");
590 {
591 Annotation *annotation = candidate->mutable_annotation();
592 annotation->set_shortcut("2");
593 }
594 candidate->set_id(1);
595 }
596 {
597 Candidate *candidate = candidates->add_candidate();
598 candidate->set_index(2);
599 candidate->set_value("知った");
600 {
601 Annotation *annotation = candidate->mutable_annotation();
602 annotation->set_description("ひらがな");
603 annotation->set_shortcut("3");
604 }
605 candidate->set_id(2);
606 }
607 {
608 Candidate *candidate = candidates->add_candidate();
609 candidate->set_index(3);
610 candidate->set_value("知った");
611 {
612 Annotation *annotation = candidate->mutable_annotation();
613 annotation->set_description("[全] カタカナ");
614 annotation->set_shortcut("4");
615 }
616 candidate->set_id(4);
617 }
618 {
619 Candidate *candidate = candidates->add_candidate();
620 candidate->set_index(4);
621 candidate->set_value("そのほかの文字種");
622 {
623 Annotation *annotation = candidate->mutable_annotation();
624 annotation->set_shortcut("5");
625 }
626 candidate->set_id(-1);
627 }
628 candidates->set_position(4);
629 candidates->set_category(commands::CONVERSION);
630 candidates->set_display_type(commands::MAIN);
631 {
632 Footer *footer = candidates->mutable_footer();
633 footer->set_index_visible(true);
634 footer->set_logo_visible(true);
635 footer->set_sub_label("build 670");
636 }
637 }
638 {
639 Status *status = output->mutable_status();
640 status->set_activated(true);
641 status->set_mode(commands::HIRAGANA);
642 }
643 {
644 CandidateList *all_candidate_words =
645 output->mutable_all_candidate_words();
646 all_candidate_words->set_focused_index(0);
647 {
648 CandidateWord *candidate_word = all_candidate_words->add_candidates();
649 candidate_word->set_id(0);
650 candidate_word->set_index(0);
651 candidate_word->set_value("咤");
652 }
653 {
654 CandidateWord *candidate_word = all_candidate_words->add_candidates();
655 candidate_word->set_id(1);
656 candidate_word->set_index(1);
657 candidate_word->set_value("知った");
658 }
659 {
660 CandidateWord *candidate_word = all_candidate_words->add_candidates();
661 candidate_word->set_id(2);
662 candidate_word->set_index(2);
663 candidate_word->set_key("しっ");
664 candidate_word->set_value("しった");
665 }
666 {
667 CandidateWord *candidate_word = all_candidate_words->add_candidates();
668 candidate_word->set_id(4);
669 candidate_word->set_index(3);
670 candidate_word->set_value("シッタ");
671 }
672 {
673 CandidateWord *candidate_word = all_candidate_words->add_candidates();
674 candidate_word->set_id(-1);
675 candidate_word->set_index(4);
676 candidate_word->set_value("しった");
677 }
678 {
679 CandidateWord *candidate_word = all_candidate_words->add_candidates();
680 candidate_word->set_id(-2);
681 candidate_word->set_index(5);
682 candidate_word->set_value("シッタ");
683 }
684 {
685 CandidateWord *candidate_word = all_candidate_words->add_candidates();
686 candidate_word->set_id(-3);
687 candidate_word->set_index(6);
688 candidate_word->set_value("shitta");
689 }
690 {
691 CandidateWord *candidate_word = all_candidate_words->add_candidates();
692 candidate_word->set_id(-4);
693 candidate_word->set_index(7);
694 candidate_word->set_value("SHITTA");
695 }
696 {
697 CandidateWord *candidate_word = all_candidate_words->add_candidates();
698 candidate_word->set_id(-6);
699 candidate_word->set_index(8);
700 candidate_word->set_value("Shitta");
701 }
702 {
703 CandidateWord *candidate_word = all_candidate_words->add_candidates();
704 candidate_word->set_id(-7);
705 candidate_word->set_index(9);
706 candidate_word->set_value("shitta");
707 }
708 {
709 CandidateWord *candidate_word = all_candidate_words->add_candidates();
710 candidate_word->set_id(-8);
711 candidate_word->set_index(10);
712 candidate_word->set_value("SHITTA");
713 }
714 {
715 CandidateWord *candidate_word = all_candidate_words->add_candidates();
716 candidate_word->set_id(-10);
717 candidate_word->set_index(11);
718 candidate_word->set_value("Shitta");
719 }
720 {
721 CandidateWord *candidate_word = all_candidate_words->add_candidates();
722 candidate_word->set_id(-11);
723 candidate_word->set_index(12);
724 candidate_word->set_value("シッタ");
725 }
726 all_candidate_words->set_category(commands::CONVERSION);
727 }
728 }
729
730 SetApplicationInfoForTest(
731 use_proportional_font, is_vertical, cursor_offset, hwnd, command);
732 }
733
734 protected:
SetUpTestCase()735 static void SetUpTestCase() {
736 // On Windows XP, the availability of typical Japanese fonts such are as
737 // MS Gothic depends on the language edition and language packs.
738 // So we will register a private font for unit test.
739 EXPECT_TRUE(WinFontTestHelper::Initialize());
740 }
741
TearDownTestCase()742 static void TearDownTestCase() {
743 // Free private fonts although the system automatically frees them when
744 // this process is terminated.
745 WinFontTestHelper::Uninitialize();
746 }
747
748 private:
SetApplicationInfoForTest(bool use_proportional_font,bool is_vertical,int cursor_offset,HWND hwnd,RendererCommand * command)749 static void SetApplicationInfoForTest(
750 bool use_proportional_font, bool is_vertical, int cursor_offset,
751 HWND hwnd, RendererCommand *command) {
752 ApplicationInfo *app = command->mutable_application_info();
753 app->set_process_id(1234);
754 app->set_thread_id(5678);
755 app->set_target_window_handle(reinterpret_cast<uint32>(hwnd));
756 WinLogFont *font = app->mutable_composition_font();
757 font->set_height(-45);
758 font->set_width(0);
759 font->set_escapement(0);
760 font->set_orientation(0);
761 font->set_weight(FW_NORMAL);
762 font->set_italic(false);
763 font->set_underline(false);
764 font->set_strike_out(false);
765 font->set_char_set(SHIFTJIS_CHARSET);
766 font->set_out_precision(0);
767 font->set_clip_precision(0);
768 font->set_quality(0);
769 if (use_proportional_font) {
770 // Use proportional font
771 font->set_pitch_and_family(VARIABLE_PITCH | FF_ROMAN | FF_SWISS);
772 font->set_face_name(GetPropotionalFontFaceForTest());
773 } else {
774 // Use monospaced font
775 font->set_pitch_and_family(FIXED_PITCH | FF_ROMAN | FF_SWISS);
776 font->set_face_name(GetMonospacedFontFaceForTest());
777 }
778
779 if (is_vertical) {
780 font->set_escapement(2700);
781 font->set_face_name("@" + font->face_name());
782 }
783
784 app->set_input_framework(ApplicationInfo::IMM32);
785 {
786 CompositionForm *composition_form = app->mutable_composition_form();
787 composition_form->set_style_bits(CompositionForm::RECT);
788 Point *current_position = composition_form->mutable_current_position();
789 Rectangle *area = composition_form->mutable_area();
790 if (is_vertical) {
791 current_position->set_x(1526);
792 current_position->set_y(385 + cursor_offset);
793 area->set_left(567);
794 area->set_top(170);
795 area->set_right(1540);
796 area->set_bottom(563);
797 } else {
798 current_position->set_x(1360 + cursor_offset);
799 current_position->set_y(57);
800 area->set_left(685);
801 area->set_top(47);
802 area->set_right(1523);
803 area->set_bottom(580);
804 }
805 }
806
807 {
808 CandidateForm *candidate_layout = app->mutable_candidate_form();
809 candidate_layout->set_style_bits(CandidateForm::CANDIDATEPOS);
810 Rectangle *area = candidate_layout->mutable_area();
811 area->set_left(567);
812 area->set_top(67);
813 area->set_right(1983755732);
814 area->set_bottom(-781021488);
815 }
816 }
817 };
818
TEST_F(Win32RendererUtilTest,GetPointInPhysicalCoordsTest)819 TEST_F(Win32RendererUtilTest, GetPointInPhysicalCoordsTest) {
820 const CPoint kClientOffset(8, 42);
821 const CSize kClientSize(100, 200);
822 const CRect kWindowRect(1000, 500, 1116, 750);
823
824 const CPoint kInnerPoint(1100, 600);
825 const CPoint kOuterPoint(10, 300);
826
827 // Check DPI scale: 100%
828 {
829 HWND hwnd = nullptr;
830 LayoutManager layout_mgr(
831 CreateDefaultGUIFontEmulator(),
832 CreateWindowEmulator(kWindowClassName, kWindowRect,
833 kClientOffset, kClientSize, 1.0, &hwnd));
834
835 // Conversion from an outer point should be calculated by emulation.
836 CPoint dest;
837 layout_mgr.GetPointInPhysicalCoords(hwnd, kOuterPoint, &dest);
838
839 // Should be the same position because DPI scaling is 100%.
840 EXPECT_EQ(kOuterPoint, dest);
841
842 // Conversion from an inner point should be calculated by API.
843 layout_mgr.GetPointInPhysicalCoords(hwnd, kInnerPoint, &dest);
844
845 // Should be the same position because DPI scaling is 100%.
846 EXPECT_EQ(kInnerPoint, dest);
847 }
848
849 // Check DPI scale: 200%
850 {
851 HWND hwnd = nullptr;
852 LayoutManager layout_mgr(
853 CreateDefaultGUIFontEmulator(),
854 CreateWindowEmulator(kWindowClassName, kWindowRect, kClientOffset,
855 kClientSize, 2.0, &hwnd));
856
857 // Conversion from an outer point should be calculated by emulation.
858 CPoint dest;
859 layout_mgr.GetPointInPhysicalCoords(hwnd, kOuterPoint, &dest);
860
861 // Should be doubled because DPI scaling is 200%.
862 EXPECT_EQ(CPoint(20, 600), dest);
863
864 // Conversion from an inner point should be calculated by API.
865 layout_mgr.GetPointInPhysicalCoords(hwnd, kInnerPoint, &dest);
866
867 // Should be doubled because DPI scaling is 200%.
868 EXPECT_EQ(CPoint(2200, 1200), dest);
869 }
870 }
871
TEST_F(Win32RendererUtilTest,GetRectInPhysicalCoordsTest)872 TEST_F(Win32RendererUtilTest, GetRectInPhysicalCoordsTest) {
873 const CPoint kClientOffset(8, 42);
874 const CSize kClientSize(100, 200);
875 const CRect kWindowRect(1000, 500, 1116, 750);
876
877 const CRect kInnerRect(1100, 600, 1070, 630);
878 const CRect kOuterRect(10, 300, 1110, 630);
879
880 // Check DPI scale: 100%
881 {
882 HWND hwnd = nullptr;
883 LayoutManager layout_mgr(
884 CreateDefaultGUIFontEmulator(),
885 CreateWindowEmulator(kWindowClassName, kWindowRect,
886 kClientOffset, kClientSize, 1.0, &hwnd));
887
888 // Conversion from an outer rectangle should be calculated by emulation.
889 CRect dest;
890 layout_mgr.GetRectInPhysicalCoords(hwnd, kOuterRect, &dest);
891
892 // Should be the same rectangle because DPI scaling is 100%.
893 EXPECT_EQ(kOuterRect, dest);
894
895 // Conversion from an inner rectangle should be calculated by API.
896 layout_mgr.GetRectInPhysicalCoords(hwnd, kInnerRect, &dest);
897
898 // Should be the same rectangle because DPI scaling is 100%.
899 EXPECT_EQ(kInnerRect, dest);
900 }
901
902 // Check DPI scale: 200%
903 {
904 HWND hwnd = nullptr;
905 LayoutManager layout_mgr(
906 CreateDefaultGUIFontEmulator(),
907 CreateWindowEmulator(kWindowClassName, kWindowRect,
908 kClientOffset, kClientSize, 2.0, &hwnd));
909
910 // Conversion from an outer rectangle should be calculated by emulation.
911 CRect dest;
912 layout_mgr.GetRectInPhysicalCoords(hwnd, kOuterRect, &dest);
913
914 // Should be doubled because DPI scaling is 200%.
915 EXPECT_EQ(CRect(20, 600, 2220, 1260), dest);
916
917 // Conversion from an inner rectangle should be calculated by API.
918 layout_mgr.GetRectInPhysicalCoords(hwnd, kInnerRect, &dest);
919
920 // Should be doubled because DPI scaling is 200%.
921 EXPECT_EQ(CRect(2200, 1200, 2140, 1260), dest);
922 }
923 }
924
TEST_F(Win32RendererUtilTest,GetScalingFactorTest)925 TEST_F(Win32RendererUtilTest, GetScalingFactorTest) {
926 const double kScalingFactor = 1.5;
927
928 {
929 const CPoint kClientOffset(0, 0);
930 const CSize kClientSize(100, 200);
931 const CRect kWindowRect(1000, 500, 1100, 700);
932 HWND hwnd = nullptr;
933 LayoutManager layout_mgr(
934 CreateDefaultGUIFontEmulator(),
935 CreateWindowEmulator(kWindowClassName, kWindowRect,
936 kClientOffset, kClientSize,
937 kScalingFactor, &hwnd));
938
939 ASSERT_DOUBLE_EQ(kScalingFactor, layout_mgr.GetScalingFactor(hwnd));
940 }
941
942 // Zero Width
943 {
944 const CPoint kClientOffset(0, 0);
945 const CSize kClientSize(0, 200);
946 const CRect kWindowRect(1000, 500, 1000, 700);
947
948 HWND hwnd = nullptr;
949 LayoutManager layout_mgr(
950 CreateDefaultGUIFontEmulator(),
951 CreateWindowEmulator(kWindowClassName, kWindowRect,
952 kClientOffset, kClientSize,
953 kScalingFactor, &hwnd));
954
955 ASSERT_DOUBLE_EQ(kScalingFactor, layout_mgr.GetScalingFactor(hwnd));
956 }
957
958 // Zero Height
959 {
960 const CPoint kClientOffset(0, 0);
961 const CSize kClientSize(100, 0);
962 const CRect kWindowRect(1000, 500, 1100, 500);
963 HWND hwnd = nullptr;
964 LayoutManager layout_mgr(
965 CreateDefaultGUIFontEmulator(),
966 CreateWindowEmulator(kWindowClassName, kWindowRect,
967 kClientOffset, kClientSize,
968 kScalingFactor, &hwnd));
969
970 ASSERT_DOUBLE_EQ(kScalingFactor, layout_mgr.GetScalingFactor(hwnd));
971 }
972
973 // Zero Size
974 {
975 const CPoint kClientOffset(0, 0);
976 const CSize kClientSize(0, 0);
977 const CRect kWindowRect(1000, 500, 1000, 500);
978 HWND hwnd = nullptr;
979 LayoutManager layout_mgr(
980 CreateDefaultGUIFontEmulator(),
981 CreateWindowEmulator(kWindowClassName, kWindowRect,
982 kClientOffset, kClientSize,
983 kScalingFactor, &hwnd));
984
985 // If the window size is zero, the result should be fallen back 1.0.
986 ASSERT_DOUBLE_EQ(1.0, layout_mgr.GetScalingFactor(hwnd));
987 }
988 }
989
TEST_F(Win32RendererUtilTest,WindowPositionEmulatorTest)990 TEST_F(Win32RendererUtilTest, WindowPositionEmulatorTest) {
991 const CPoint kClientOffset(8, 42);
992 const CSize kClientSize(100, 200);
993 const CRect kWindowRect(1000, 500, 1116, 750);
994
995 const CPoint kInnerPoint(1100, 600);
996 const CPoint kOuterPoint(10, 300);
997 const CRect kInnerRect(1100, 600, 1070, 630);
998 const CRect kOuterRect(10, 300, 1110, 630);
999
1000 // Check DPI scale: 100%
1001 {
1002 std::unique_ptr<WindowPositionEmulator> emulator(
1003 WindowPositionEmulator::Create());
1004 const HWND hwnd = emulator->RegisterWindow(
1005 kWindowClassName, kWindowRect, kClientOffset, kClientSize, 1.0);
1006
1007 CRect rect;
1008 CPoint point;
1009
1010 // You cannot pass nullptr to |window_handle|.
1011 EXPECT_FALSE(emulator->IsWindow(nullptr));
1012 EXPECT_FALSE(emulator->GetWindowRect(nullptr, &rect));
1013 EXPECT_FALSE(emulator->GetClientRect(nullptr, &rect));
1014 EXPECT_FALSE(emulator->ClientToScreen(nullptr, &point));
1015
1016 EXPECT_TRUE(emulator->GetWindowRect(hwnd, &rect));
1017 EXPECT_EQ(kWindowRect, rect);
1018
1019 EXPECT_TRUE(emulator->GetClientRect(hwnd, &rect));
1020 EXPECT_EQ(CRect(CPoint(0, 0), kClientSize), rect);
1021
1022 point = CPoint(0, 0);
1023 EXPECT_TRUE(emulator->ClientToScreen(hwnd, &point));
1024 EXPECT_EQ(kWindowRect.TopLeft() + kClientOffset, point);
1025
1026 std::wstring class_name;
1027 EXPECT_TRUE(emulator->GetWindowClassName(hwnd, &class_name));
1028 EXPECT_EQ(kWindowClassName, class_name);
1029 }
1030
1031 // Interestingly, the following results are independent of DPI scaling.
1032 {
1033 std::unique_ptr<WindowPositionEmulator> emulator(
1034 WindowPositionEmulator::Create());
1035 const HWND hwnd = emulator->RegisterWindow(
1036 kWindowClassName, kWindowRect, kClientOffset, kClientSize, 10.0);
1037
1038 CRect rect;
1039 CPoint point;
1040
1041 // You cannot pass nullptr to |window_handle|.
1042 EXPECT_FALSE(emulator->IsWindow(nullptr));
1043 EXPECT_FALSE(emulator->GetWindowRect(nullptr, &rect));
1044 EXPECT_FALSE(emulator->GetClientRect(nullptr, &rect));
1045 EXPECT_FALSE(emulator->ClientToScreen(nullptr, &point));
1046
1047 EXPECT_TRUE(emulator->GetWindowRect(hwnd, &rect));
1048 EXPECT_EQ(kWindowRect, rect);
1049
1050 EXPECT_TRUE(emulator->GetClientRect(hwnd, &rect));
1051 EXPECT_EQ(CRect(CPoint(0, 0), kClientSize), rect);
1052
1053 point = CPoint(0, 0);
1054 EXPECT_TRUE(emulator->ClientToScreen(hwnd, &point));
1055 EXPECT_EQ(kWindowRect.TopLeft() + kClientOffset, point);
1056
1057 std::wstring class_name;
1058 EXPECT_TRUE(emulator->GetWindowClassName(hwnd, &class_name));
1059 EXPECT_EQ(kWindowClassName, class_name);
1060 }
1061 }
1062
TEST_F(Win32RendererUtilTest,HorizontalProportional)1063 TEST_F(Win32RendererUtilTest, HorizontalProportional) {
1064 const CLogFont &logfont = GetFont(true, false);
1065
1066 std::vector<mozc::renderer::win32::LineLayout> line_layouts;
1067 bool result = true;
1068
1069 const std::wstring &message = GetTestMessageForProportional();
1070
1071 // Check if the |initial_offset| works as expected.
1072 result = LayoutManager::CalcLayoutWithTextWrapping(
1073 logfont, message, 200, 100, &line_layouts);
1074 EXPECT_TRUE(result);
1075 EXPECT_EQ(4, line_layouts.size());
1076 EXPECT_EQ(line_layouts[0].line_width, line_layouts[1].line_width);
1077 EXPECT_EQ(line_layouts[1].line_width, line_layouts[2].line_width);
1078 EXPECT_EQ(line_layouts[2].line_width, line_layouts[3].line_width);
1079
1080 // Check if the text wrapping occurs in the first line when
1081 // |initial_offset| > 0. In this case, the line height of first line is
1082 // expected to be the same to that of the second line.
1083 result = LayoutManager::CalcLayoutWithTextWrapping(
1084 logfont, message, 200, 199, &line_layouts);
1085 EXPECT_TRUE(result);
1086 EXPECT_EQ(4, line_layouts.size());
1087 EXPECT_EQ(0, line_layouts[0].line_length);
1088 EXPECT_EQ(0, line_layouts[0].text.size());
1089 EXPECT_EQ(0, line_layouts[0].character_positions.size());
1090 EXPECT_EQ(line_layouts[0].line_width, line_layouts[1].line_width);
1091 EXPECT_EQ(line_layouts[1].line_width, line_layouts[2].line_width);
1092 EXPECT_EQ(line_layouts[2].line_width, line_layouts[3].line_width);
1093
1094 // Check if this function fails when there is no enough space for text
1095 // wrapping.
1096 result = LayoutManager::CalcLayoutWithTextWrapping(
1097 logfont, message, 2, 1, &line_layouts);
1098 EXPECT_FALSE(result);
1099
1100 // Check if an invalid |initial_offset| is detected as expected.
1101 result = LayoutManager::CalcLayoutWithTextWrapping(
1102 logfont, message, 200, -100, &line_layouts);
1103 EXPECT_FALSE(result);
1104
1105 // Check if an invalid |initial_offset| is detected as expected.
1106 result = LayoutManager::CalcLayoutWithTextWrapping(
1107 logfont, message, 200, 201, &line_layouts);
1108 EXPECT_FALSE(result);
1109
1110 // Check if an invalid |maximum_line_length| is detected as expected.
1111 result = LayoutManager::CalcLayoutWithTextWrapping(
1112 logfont, message, -1, 0, &line_layouts);
1113 EXPECT_FALSE(result);
1114
1115 // Check if an invalid |maximum_line_length| is detected as expected.
1116 result = LayoutManager::CalcLayoutWithTextWrapping(
1117 logfont, message, 0, 0, &line_layouts);
1118 EXPECT_FALSE(result);
1119 }
1120
TEST_F(Win32RendererUtilTest,VerticalProportional)1121 TEST_F(Win32RendererUtilTest, VerticalProportional) {
1122 const CLogFont &logfont = GetFont(true, true);
1123
1124 std::vector<mozc::renderer::win32::LineLayout> line_layouts;
1125 bool result = true;
1126
1127 const std::wstring &message = GetTestMessageForProportional();
1128
1129 // Check if the |initial_offset| works as expected.
1130 result = LayoutManager::CalcLayoutWithTextWrapping(
1131 logfont, message, 200, 100, &line_layouts);
1132 EXPECT_TRUE(result);
1133 EXPECT_EQ(4, line_layouts.size());
1134 EXPECT_EQ(line_layouts[0].line_width, line_layouts[1].line_width);
1135 EXPECT_EQ(line_layouts[1].line_width, line_layouts[2].line_width);
1136 EXPECT_EQ(line_layouts[2].line_width, line_layouts[3].line_width);
1137
1138 // Check if the text wrapping occurs in the first line when
1139 // |initial_offset| > 0. In this case, the line height of first line is
1140 // expected to be the same to that of the second line.
1141 result = LayoutManager::CalcLayoutWithTextWrapping(
1142 logfont, message, 200, 199, &line_layouts);
1143 EXPECT_TRUE(result);
1144 EXPECT_EQ(4, line_layouts.size());
1145 EXPECT_EQ(0, line_layouts[0].line_length);
1146 EXPECT_EQ(0, line_layouts[0].text.size());
1147 EXPECT_EQ(0, line_layouts[0].character_positions.size());
1148 EXPECT_EQ(line_layouts[0].line_width, line_layouts[1].line_width);
1149 EXPECT_EQ(line_layouts[1].line_width, line_layouts[2].line_width);
1150 EXPECT_EQ(line_layouts[2].line_width, line_layouts[3].line_width);
1151
1152 // Check if this function fails when there is no enough space for text
1153 // wrapping.
1154 result = LayoutManager::CalcLayoutWithTextWrapping(
1155 logfont, message, 2, 1, &line_layouts);
1156 EXPECT_FALSE(result);
1157
1158 // Check if an invalid |initial_offset| is detected as expected.
1159 result = LayoutManager::CalcLayoutWithTextWrapping(
1160 logfont, message, 200, -100, &line_layouts);
1161 EXPECT_FALSE(result);
1162
1163 // Check if an invalid |initial_offset| is detected as expected.
1164 result = LayoutManager::CalcLayoutWithTextWrapping(
1165 logfont, message, 200, 201, &line_layouts);
1166 EXPECT_FALSE(result);
1167
1168 // Check if an invalid |maximum_line_length| is detected as expected.
1169 result = LayoutManager::CalcLayoutWithTextWrapping(
1170 logfont, message, -1, 0, &line_layouts);
1171 EXPECT_FALSE(result);
1172
1173 // Check if an invalid |maximum_line_length| is detected as expected.
1174 result = LayoutManager::CalcLayoutWithTextWrapping(
1175 logfont, message, 0, 0, &line_layouts);
1176 EXPECT_FALSE(result);
1177 }
1178
TEST_F(Win32RendererUtilTest,HorizontalMonospaced)1179 TEST_F(Win32RendererUtilTest, HorizontalMonospaced) {
1180 const CLogFont &logfont = GetFont(false, false);
1181
1182 std::vector<mozc::renderer::win32::LineLayout> line_layouts;
1183 bool result = true;
1184
1185 const std::wstring &message = GetTestMessageForMonospaced();
1186
1187 // Check if the |initial_offset| works as expected.
1188 result = LayoutManager::CalcLayoutWithTextWrapping(
1189 logfont, message, 200, 100, &line_layouts);
1190 EXPECT_TRUE(result);
1191 EXPECT_EQ(4, line_layouts.size());
1192 EXPECT_EQ(line_layouts[0].line_width, line_layouts[1].line_width);
1193 EXPECT_EQ(line_layouts[1].line_width, line_layouts[2].line_width);
1194 EXPECT_EQ(line_layouts[2].line_width, line_layouts[3].line_width);
1195
1196 // Check if the text wrapping occurs in the first line when
1197 // |initial_offset| > 0. In this case, the line height of first line is
1198 // expected to be the same to that of the second line.
1199 result = LayoutManager::CalcLayoutWithTextWrapping(
1200 logfont, message, 200, 199, &line_layouts);
1201 EXPECT_TRUE(result);
1202 EXPECT_EQ(4, line_layouts.size());
1203 EXPECT_EQ(0, line_layouts[0].line_length);
1204 EXPECT_EQ(0, line_layouts[0].text.size());
1205 EXPECT_EQ(0, line_layouts[0].character_positions.size());
1206 EXPECT_EQ(line_layouts[0].line_width, line_layouts[1].line_width);
1207 EXPECT_EQ(line_layouts[1].line_width, line_layouts[2].line_width);
1208 EXPECT_EQ(line_layouts[2].line_width, line_layouts[3].line_width);
1209
1210 // Check if this function fails when there is no enough space for text
1211 // wrapping.
1212 result = LayoutManager::CalcLayoutWithTextWrapping(
1213 logfont, message, 2, 1, &line_layouts);
1214 EXPECT_FALSE(result);
1215
1216 // Check if an invalid |initial_offset| is detected as expected.
1217 result = LayoutManager::CalcLayoutWithTextWrapping(
1218 logfont, message, 200, -100, &line_layouts);
1219 EXPECT_FALSE(result);
1220
1221 // Check if an invalid |initial_offset| is detected as expected.
1222 result = LayoutManager::CalcLayoutWithTextWrapping(
1223 logfont, message, 200, 201, &line_layouts);
1224 EXPECT_FALSE(result);
1225
1226 // Check if an invalid |maximum_line_length| is detected as expected.
1227 result = LayoutManager::CalcLayoutWithTextWrapping(
1228 logfont, message, -1, 0, &line_layouts);
1229 EXPECT_FALSE(result);
1230
1231 // Check if an invalid |maximum_line_length| is detected as expected.
1232 result = LayoutManager::CalcLayoutWithTextWrapping(
1233 logfont, message, 0, 0, &line_layouts);
1234 EXPECT_FALSE(result);
1235 }
1236
TEST_F(Win32RendererUtilTest,VerticalMonospaced)1237 TEST_F(Win32RendererUtilTest, VerticalMonospaced) {
1238 const CLogFont &logfont = GetFont(false, true);
1239
1240 std::vector<mozc::renderer::win32::LineLayout> line_layouts;
1241 bool result = true;
1242
1243 const std::wstring &message = GetTestMessageForMonospaced();
1244
1245 // Check if the |initial_offset| works as expected.
1246 result = LayoutManager::CalcLayoutWithTextWrapping(
1247 logfont, message, 200, 100, &line_layouts);
1248 EXPECT_TRUE(result);
1249 EXPECT_EQ(4, line_layouts.size());
1250 EXPECT_EQ(line_layouts[0].line_width, line_layouts[1].line_width);
1251 EXPECT_EQ(line_layouts[1].line_width, line_layouts[2].line_width);
1252 EXPECT_EQ(line_layouts[2].line_width, line_layouts[3].line_width);
1253
1254 // Check if the text wrapping occurs in the first line when
1255 // |initial_offset| > 0. In this case, the line height of first line is
1256 // expected to be the same to that of the second line.
1257 result = LayoutManager::CalcLayoutWithTextWrapping(
1258 logfont, message, 200, 199, &line_layouts);
1259 EXPECT_TRUE(result);
1260 EXPECT_EQ(4, line_layouts.size());
1261 EXPECT_EQ(0, line_layouts[0].line_length);
1262 EXPECT_EQ(0, line_layouts[0].text.size());
1263 EXPECT_EQ(0, line_layouts[0].character_positions.size());
1264 EXPECT_EQ(line_layouts[0].line_width, line_layouts[1].line_width);
1265 EXPECT_EQ(line_layouts[1].line_width, line_layouts[2].line_width);
1266 EXPECT_EQ(line_layouts[2].line_width, line_layouts[3].line_width);
1267
1268 // Check if this function fails when there is no enough space for text
1269 // wrapping.
1270 result = LayoutManager::CalcLayoutWithTextWrapping(
1271 logfont, message, 2, 1, &line_layouts);
1272 EXPECT_FALSE(result);
1273
1274 // Check if an invalid |initial_offset| is detected as expected.
1275 result = LayoutManager::CalcLayoutWithTextWrapping(
1276 logfont, message, 200, -100, &line_layouts);
1277 EXPECT_FALSE(result);
1278
1279 // Check if an invalid |initial_offset| is detected as expected.
1280 result = LayoutManager::CalcLayoutWithTextWrapping(
1281 logfont, message, 200, 201, &line_layouts);
1282 EXPECT_FALSE(result);
1283
1284 // Check if an invalid |maximum_line_length| is detected as expected.
1285 result = LayoutManager::CalcLayoutWithTextWrapping(
1286 logfont, message, -1, 0, &line_layouts);
1287 EXPECT_FALSE(result);
1288
1289 // Check if an invalid |maximum_line_length| is detected as expected.
1290 result = LayoutManager::CalcLayoutWithTextWrapping(
1291 logfont, message, 0, 0, &line_layouts);
1292 EXPECT_FALSE(result);
1293 }
1294
TEST_F(Win32RendererUtilTest,HorizontalProportionalCompositeGlyph)1295 TEST_F(Win32RendererUtilTest, HorizontalProportionalCompositeGlyph) {
1296 const CLogFont &logfont = GetFont(true, false);
1297
1298 std::vector<mozc::renderer::win32::LineLayout> line_layouts;
1299 bool result = true;
1300
1301 const std::wstring &message = GetTestMessageWithCompositeGlyph(1);
1302
1303 result = LayoutManager::CalcLayoutWithTextWrapping(
1304 logfont, message, 200, 100, &line_layouts);
1305 EXPECT_TRUE(result);
1306 EXPECT_EQ(1, line_layouts.size());
1307
1308 // CalcLayoutWithTextWrapping does not support composition glyph.
1309 EXPECT_GT(line_layouts[0].character_positions[0].length, 0);
1310 EXPECT_EQ(line_layouts[0].character_positions[1].begin +
1311 line_layouts[0].character_positions[1].length,
1312 line_layouts[0].line_length);
1313 }
1314
TEST_F(Win32RendererUtilTest,VerticalProportionalCompositeGlyph)1315 TEST_F(Win32RendererUtilTest, VerticalProportionalCompositeGlyph) {
1316 const CLogFont &logfont = GetFont(true, true);
1317
1318 std::vector<mozc::renderer::win32::LineLayout> line_layouts;
1319 bool result = true;
1320
1321 const std::wstring &message = GetTestMessageWithCompositeGlyph(1);
1322 result = LayoutManager::CalcLayoutWithTextWrapping(
1323 logfont, message, 200, 100, &line_layouts);
1324 EXPECT_TRUE(result);
1325 EXPECT_EQ(1, line_layouts.size());
1326
1327 // CalcLayoutWithTextWrapping does not support composition glyph.
1328 EXPECT_GT(line_layouts[0].character_positions[0].length, 0);
1329 EXPECT_EQ(line_layouts[0].character_positions[1].begin +
1330 line_layouts[0].character_positions[1].length,
1331 line_layouts[0].line_length);
1332 }
1333
TEST_F(Win32RendererUtilTest,HorizontalMonospacedCompositeGlyph)1334 TEST_F(Win32RendererUtilTest, HorizontalMonospacedCompositeGlyph) {
1335 const CLogFont &logfont = GetFont(false, false);
1336
1337 std::vector<mozc::renderer::win32::LineLayout> line_layouts;
1338 bool result = true;
1339
1340 const std::wstring &message = GetTestMessageWithCompositeGlyph(1);
1341
1342 result = LayoutManager::CalcLayoutWithTextWrapping(
1343 logfont, message, 200, 100, &line_layouts);
1344 EXPECT_TRUE(result);
1345 EXPECT_EQ(1, line_layouts.size());
1346
1347 // CalcLayoutWithTextWrapping does not support composition glyph.
1348 EXPECT_GT(line_layouts[0].character_positions[0].length, 0);
1349 EXPECT_EQ(line_layouts[0].character_positions[1].begin +
1350 line_layouts[0].character_positions[1].length,
1351 line_layouts[0].line_length);
1352 }
1353
TEST_F(Win32RendererUtilTest,VerticalMonospacedCompositeGlyph)1354 TEST_F(Win32RendererUtilTest, VerticalMonospacedCompositeGlyph) {
1355 const CLogFont &logfont = GetFont(false, true);
1356
1357 std::vector<mozc::renderer::win32::LineLayout> line_layouts;
1358 bool result = true;
1359
1360 const std::wstring &message = GetTestMessageWithCompositeGlyph(1);
1361
1362 result = LayoutManager::CalcLayoutWithTextWrapping(
1363 logfont, message, 200, 100, &line_layouts);
1364 EXPECT_TRUE(result);
1365 EXPECT_EQ(1, line_layouts.size());
1366
1367 // CalcLayoutWithTextWrapping does not support composition glyph.
1368 EXPECT_GT(line_layouts[0].character_positions[0].length, 0);
1369 EXPECT_EQ(line_layouts[0].character_positions[1].begin +
1370 line_layouts[0].character_positions[1].length,
1371 line_layouts[0].line_length);
1372 }
1373
TEST_F(Win32RendererUtilTest,CompositionHorizontalNoAdditionalSegmentationWithMonospacedFont)1374 TEST_F(Win32RendererUtilTest,
1375 CompositionHorizontalNoAdditionalSegmentationWithMonospacedFont) {
1376 const int kCursorOffsetX = 0;
1377
1378 RendererCommand command;
1379
1380 HWND hwnd = nullptr;
1381 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
1382 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
1383 std::vector<CompositionWindowLayout> layouts;
1384 CandidateWindowLayout candidate_layout;
1385
1386 CLogFont logfont;
1387
1388 bool result = false;
1389
1390 // w/ candidates, monospaced, horizontal
1391 SetRenderereCommandForTest(
1392 false, true, false, kCursorOffsetX, hwnd, &command);
1393 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1394 command.application_info().composition_font(), &logfont));
1395 layouts.clear();
1396 candidate_layout.Clear();
1397 result = layout_mgr.LayoutCompositionWindow(
1398 command, &layouts, &candidate_layout);
1399 EXPECT_TRUE(result);
1400
1401 ASSERT_EQ(2, layouts.size());
1402
1403 // The first line
1404 {
1405 const CompositionWindowLayout &layout = layouts.at(0);
1406 EXPECT_COMPOSITION_WINDOW_LAYOUT(1868, 599, 2003, 648, 0, 0, 135, 49,
1407 0, 0, 0, 0, 0, 0, logfont, layout);
1408 {
1409 const char kMsg[] = "これは";
1410 std::wstring msg;
1411 mozc::Util::UTF8ToWide(kMsg, &msg);
1412 EXPECT_EQ(msg, layout.text);
1413 }
1414 ASSERT_EQ(1, layout.marker_layouts.size());
1415
1416 EXPECT_EQ(CPoint(0, 48), layout.marker_layouts[0].from);
1417 EXPECT_EQ(CPoint(126, 48), layout.marker_layouts[0].to);
1418 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1419 }
1420
1421 // The second line
1422 {
1423 const CompositionWindowLayout &layout = layouts.at(1);
1424 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 648, 1840, 697, 0, 0, 646, 49,
1425 0, 0, 646, 0, 647, 49, logfont, layout);
1426 {
1427 const char kMsg[] = "、Google日本語入力のTestです";
1428 std::wstring msg;
1429 mozc::Util::UTF8ToWide(kMsg, &msg);
1430 EXPECT_EQ(msg, layout.text);
1431 }
1432 ASSERT_EQ(4, layout.marker_layouts.size());
1433
1434 EXPECT_EQ(CPoint(0, 48), layout.marker_layouts[0].from);
1435 EXPECT_EQ(CPoint(36, 48), layout.marker_layouts[0].to);
1436 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1437 EXPECT_EQ(CPoint(45, 48), layout.marker_layouts[1].from);
1438 EXPECT_EQ(CPoint(190, 48), layout.marker_layouts[1].to);
1439 EXPECT_TRUE(layout.marker_layouts[1].highlighted);
1440 EXPECT_EQ(CPoint(196, 48), layout.marker_layouts[2].from);
1441 EXPECT_EQ(CPoint(457, 48), layout.marker_layouts[2].to);
1442 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
1443 EXPECT_EQ(CPoint(466, 48), layout.marker_layouts[3].from);
1444 EXPECT_EQ(CPoint(646, 48), layout.marker_layouts[3].to);
1445 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
1446 }
1447 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1448 1238, 697, 1238, 648, 1839, 697, candidate_layout);
1449
1450 // Check other candidate positions.
1451 command.mutable_output()->mutable_candidates()->set_position(0);
1452 layouts.clear();
1453 candidate_layout.Clear();
1454 result = layout_mgr.LayoutCompositionWindow(
1455 command, &layouts, &candidate_layout);
1456 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1457 1868, 648, 1868, 599, 2003, 648, candidate_layout);
1458
1459 command.mutable_output()->mutable_candidates()->set_position(3);
1460 layouts.clear();
1461 candidate_layout.Clear();
1462 result = layout_mgr.LayoutCompositionWindow(
1463 command, &layouts, &candidate_layout);
1464 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1465 1193, 697, 1193, 648, 1839, 697, candidate_layout);
1466
1467 command.mutable_output()->mutable_candidates()->set_position(10);
1468 layouts.clear();
1469 candidate_layout.Clear();
1470 result = layout_mgr.LayoutCompositionWindow(
1471 command, &layouts, &candidate_layout);
1472 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1473 1389, 697, 1389, 648, 1839, 697, candidate_layout);
1474
1475 command.mutable_output()->mutable_candidates()->set_position(16);
1476 layouts.clear();
1477 candidate_layout.Clear();
1478 result = layout_mgr.LayoutCompositionWindow(
1479 command, &layouts, &candidate_layout);
1480 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1481 1659, 697, 1659, 648, 1839, 697, candidate_layout);
1482
1483 // w/o candidates, monospaced, horizontal
1484 SetRenderereCommandForTest(false, false, false, 0, hwnd, &command);
1485 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1486 command.application_info().composition_font(), &logfont));
1487 layouts.clear();
1488 candidate_layout.Clear();
1489 result = layout_mgr.LayoutCompositionWindow(
1490 command, &layouts, &candidate_layout);
1491 EXPECT_TRUE(result);
1492 EXPECT_FALSE(candidate_layout.initialized());
1493 }
1494
TEST_F(Win32RendererUtilTest,CompositionHorizontalAdditionalSegmentationWithMonospacedFont)1495 TEST_F(Win32RendererUtilTest,
1496 CompositionHorizontalAdditionalSegmentationWithMonospacedFont) {
1497 const int kCursorOffsetX = -90;
1498
1499 RendererCommand command;
1500
1501 HWND hwnd = nullptr;
1502 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
1503 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
1504 std::vector<CompositionWindowLayout> layouts;
1505 CandidateWindowLayout candidate_layout;
1506 CLogFont logfont;
1507
1508 bool result = false;
1509
1510 // w/ candidates, monospaced, horizontal
1511 SetRenderereCommandForTest(
1512 false, true, false, kCursorOffsetX, hwnd, &command);
1513 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1514 command.application_info().composition_font(), &logfont));
1515 layouts.clear();
1516 candidate_layout.Clear();
1517 result = layout_mgr.LayoutCompositionWindow(
1518 command, &layouts, &candidate_layout);
1519 EXPECT_TRUE(result);
1520
1521 ASSERT_EQ(2, layouts.size());
1522
1523 // The first line
1524 {
1525 const CompositionWindowLayout &layout = layouts.at(0);
1526 EXPECT_COMPOSITION_WINDOW_LAYOUT(1778, 599, 2019, 648, 0, 0, 241, 49,
1527 0, 0, 0, 0, 0, 0, logfont, layout);
1528 {
1529 const char kMsg[] = "これは、Go";
1530 std::wstring msg;
1531 mozc::Util::UTF8ToWide(kMsg, &msg);
1532 EXPECT_EQ(msg, layout.text);
1533 }
1534 ASSERT_EQ(3, layout.marker_layouts.size());
1535
1536 EXPECT_EQ(CPoint(0, 48), layout.marker_layouts[0].from);
1537 EXPECT_EQ(CPoint(126, 48), layout.marker_layouts[0].to);
1538 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1539 EXPECT_EQ(CPoint(135, 48), layout.marker_layouts[1].from);
1540 EXPECT_EQ(CPoint(171, 48), layout.marker_layouts[1].to);
1541 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
1542 EXPECT_EQ(CPoint(180, 48), layout.marker_layouts[2].from);
1543 EXPECT_EQ(CPoint(241, 48), layout.marker_layouts[2].to);
1544 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
1545 }
1546
1547 // The second line
1548 {
1549 const CompositionWindowLayout &layout = layouts.at(1);
1550 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 648, 1734, 697, 0, 0, 540, 49,
1551 0, 0, 540, 0, 541, 49, logfont, layout);
1552 {
1553 const char kMsg[] = "ogle日本語入力のTestです";
1554 std::wstring msg;
1555 mozc::Util::UTF8ToWide(kMsg, &msg);
1556 EXPECT_EQ(msg, layout.text);
1557 }
1558 ASSERT_EQ(3, layout.marker_layouts.size());
1559
1560 EXPECT_EQ(CPoint(0, 48), layout.marker_layouts[0].from);
1561 EXPECT_EQ(CPoint(84, 48), layout.marker_layouts[0].to);
1562 EXPECT_TRUE(layout.marker_layouts[0].highlighted);
1563 EXPECT_EQ(CPoint(90, 48), layout.marker_layouts[1].from);
1564 EXPECT_EQ(CPoint(351, 48), layout.marker_layouts[1].to);
1565 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
1566 EXPECT_EQ(CPoint(360, 48), layout.marker_layouts[2].from);
1567 EXPECT_EQ(CPoint(540, 48), layout.marker_layouts[2].to);
1568 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
1569 }
1570
1571 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1572 1958, 648, 1958, 599, 2019, 648, candidate_layout);
1573
1574 // Check other candidate positions.
1575 command.mutable_output()->mutable_candidates()->set_position(0);
1576 layouts.clear();
1577 candidate_layout.Clear();
1578 result = layout_mgr.LayoutCompositionWindow(
1579 command, &layouts, &candidate_layout);
1580 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1581 1778, 648, 1778, 599, 2019, 648, candidate_layout);
1582
1583 command.mutable_output()->mutable_candidates()->set_position(3);
1584 layouts.clear();
1585 candidate_layout.Clear();
1586 result = layout_mgr.LayoutCompositionWindow(
1587 command, &layouts, &candidate_layout);
1588 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1589 1913, 648, 1913, 599, 2019, 648, candidate_layout);
1590
1591 command.mutable_output()->mutable_candidates()->set_position(10);
1592 layouts.clear();
1593 candidate_layout.Clear();
1594 result = layout_mgr.LayoutCompositionWindow(
1595 command, &layouts, &candidate_layout);
1596 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1597 1283, 697, 1283, 648, 1733, 697, candidate_layout);
1598
1599 command.mutable_output()->mutable_candidates()->set_position(16);
1600 layouts.clear();
1601 candidate_layout.Clear();
1602 result = layout_mgr.LayoutCompositionWindow(
1603 command, &layouts, &candidate_layout);
1604 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1605 1553, 697, 1553, 648, 1733, 697, candidate_layout);
1606
1607 // w/o candidates, monospaced, horizontal
1608 SetRenderereCommandForTest(false, false, false, 0, hwnd, &command);
1609 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1610 command.application_info().composition_font(), &logfont));
1611 layouts.clear();
1612 candidate_layout.Clear();
1613 result = layout_mgr.LayoutCompositionWindow(
1614 command, &layouts, &candidate_layout);
1615 EXPECT_TRUE(result);
1616 EXPECT_FALSE(candidate_layout.initialized());
1617 }
1618
TEST_F(Win32RendererUtilTest,CompositionVerticalNoAdditionalSegmentationWithMonospacedFont)1619 TEST_F(Win32RendererUtilTest,
1620 CompositionVerticalNoAdditionalSegmentationWithMonospacedFont) {
1621 const int kCursorOffsetY = 0;
1622
1623 RendererCommand command;
1624
1625 HWND hwnd = nullptr;
1626 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
1627 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
1628 std::vector<CompositionWindowLayout> layouts;
1629 CandidateWindowLayout candidate_layout;
1630 CLogFont logfont;
1631
1632 bool result = false;
1633
1634 // w/ candidates, monospaced, vertical
1635 SetRenderereCommandForTest(
1636 false, true, true, kCursorOffsetY, hwnd, &command);
1637 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1638 command.application_info().composition_font(), &logfont));
1639 logfont.lfOrientation = 2700;
1640
1641 layouts.clear();
1642 candidate_layout.Clear();
1643 result = layout_mgr.LayoutCompositionWindow(
1644 command, &layouts, &candidate_layout);
1645 EXPECT_TRUE(result);
1646
1647 ASSERT_EQ(3, layouts.size());
1648
1649 // The first line
1650 {
1651 const CompositionWindowLayout &layout = layouts.at(0);
1652 EXPECT_COMPOSITION_WINDOW_LAYOUT(1983, 927, 2034, 1062, 0, 0, 51, 135,
1653 51, 0, 0, 0, 0, 0, logfont, layout);
1654 {
1655 const char kMsg[] = "これは";
1656 std::wstring msg;
1657 mozc::Util::UTF8ToWide(kMsg, &msg);
1658 EXPECT_EQ(msg, layout.text);
1659 }
1660 ASSERT_EQ(1, layout.marker_layouts.size());
1661
1662 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
1663 EXPECT_EQ(CPoint(50, 126), layout.marker_layouts[0].to);
1664 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1665 }
1666
1667 // The second line
1668 {
1669 const CompositionWindowLayout &layout = layouts.at(1);
1670 EXPECT_COMPOSITION_WINDOW_LAYOUT(1932, 712, 1983, 1088, 0, 0, 51, 376,
1671 51, 0, 0, 0, 0, 0, logfont, layout);
1672 {
1673 const char kMsg[] = "、Google日本語入";
1674 std::wstring msg;
1675 mozc::Util::UTF8ToWide(kMsg, &msg);
1676 EXPECT_EQ(msg, layout.text);
1677 }
1678 ASSERT_EQ(3, layout.marker_layouts.size());
1679
1680 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
1681 EXPECT_EQ(CPoint(50, 36), layout.marker_layouts[0].to);
1682 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1683 EXPECT_EQ(CPoint(50, 45), layout.marker_layouts[1].from);
1684 EXPECT_EQ(CPoint(50, 190), layout.marker_layouts[1].to);
1685 EXPECT_TRUE(layout.marker_layouts[1].highlighted);
1686 EXPECT_EQ(CPoint(50, 196), layout.marker_layouts[2].from);
1687 EXPECT_EQ(CPoint(50, 376), layout.marker_layouts[2].to);
1688 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
1689 }
1690
1691 // The third line
1692 {
1693 const CompositionWindowLayout &layout = layouts.at(2);
1694 EXPECT_COMPOSITION_WINDOW_LAYOUT(1881, 712, 1932, 983, 0, 0, 51, 270,
1695 51, 0, 0, 270, 51, 271, logfont, layout);
1696 {
1697 const char kMsg[] = "力のTestです";
1698 std::wstring msg;
1699 mozc::Util::UTF8ToWide(kMsg, &msg);
1700 EXPECT_EQ(msg, layout.text);
1701 }
1702 ASSERT_EQ(2, layout.marker_layouts.size());
1703
1704 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
1705 EXPECT_EQ(CPoint(50, 81), layout.marker_layouts[0].to);
1706 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1707 EXPECT_EQ(CPoint(50, 90), layout.marker_layouts[1].from);
1708 EXPECT_EQ(CPoint(50, 270), layout.marker_layouts[1].to);
1709 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
1710 }
1711
1712 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1713 1932, 757, 1932, 757, 1983, 1088, candidate_layout);
1714
1715 // Check other candidate positions.
1716 command.mutable_output()->mutable_candidates()->set_position(0);
1717 layouts.clear();
1718 candidate_layout.Clear();
1719 result = layout_mgr.LayoutCompositionWindow(
1720 command, &layouts, &candidate_layout);
1721 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1722 1983, 927, 1983, 927, 2034, 1062, candidate_layout);
1723
1724 command.mutable_output()->mutable_candidates()->set_position(3);
1725 layouts.clear();
1726 candidate_layout.Clear();
1727 result = layout_mgr.LayoutCompositionWindow(
1728 command, &layouts, &candidate_layout);
1729 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1730 1932, 712, 1932, 712, 1983, 1088, candidate_layout);
1731
1732 command.mutable_output()->mutable_candidates()->set_position(10);
1733 layouts.clear();
1734 candidate_layout.Clear();
1735 result = layout_mgr.LayoutCompositionWindow(
1736 command, &layouts, &candidate_layout);
1737 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1738 1932, 908, 1932, 908, 1983, 1088, candidate_layout);
1739
1740 command.mutable_output()->mutable_candidates()->set_position(16);
1741 layouts.clear();
1742 candidate_layout.Clear();
1743 result = layout_mgr.LayoutCompositionWindow(
1744 command, &layouts, &candidate_layout);
1745 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1746 1881, 802, 1881, 802, 1932, 982, candidate_layout);
1747
1748 // w/o candidates, monospaced, vertical
1749 SetRenderereCommandForTest(false, false, true, 0, hwnd, &command);
1750 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1751 command.application_info().composition_font(), &logfont));
1752 layouts.clear();
1753 candidate_layout.Clear();
1754 result = layout_mgr.LayoutCompositionWindow(
1755 command, &layouts, &candidate_layout);
1756 EXPECT_TRUE(result);
1757 EXPECT_FALSE(candidate_layout.initialized());
1758 }
1759
TEST_F(Win32RendererUtilTest,CompositionVerticalAdditionalSegmentationWithMonospacedFont)1760 TEST_F(Win32RendererUtilTest,
1761 CompositionVerticalAdditionalSegmentationWithMonospacedFont) {
1762 const int kCursorOffsetY = -90;
1763
1764 RendererCommand command;
1765
1766 HWND hwnd = nullptr;
1767 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
1768 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
1769 std::vector<CompositionWindowLayout> layouts;
1770 CandidateWindowLayout candidate_layout;
1771 CLogFont logfont;
1772
1773 bool result = false;
1774
1775 // w/ candidates, monospaced, vertical
1776 SetRenderereCommandForTest(
1777 false, true, true, kCursorOffsetY, hwnd, &command);
1778 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1779 command.application_info().composition_font(), &logfont));
1780 logfont.lfOrientation = 2700;
1781
1782 layouts.clear();
1783 candidate_layout.Clear();
1784 result = layout_mgr.LayoutCompositionWindow(
1785 command, &layouts, &candidate_layout);
1786 EXPECT_TRUE(result);
1787
1788 ASSERT_EQ(3, layouts.size());
1789
1790 // The first line
1791 {
1792 const CompositionWindowLayout &layout = layouts.at(0);
1793 EXPECT_COMPOSITION_WINDOW_LAYOUT(1983, 837, 2034, 1105, 0, 0, 51, 268,
1794 51, 0, 0, 0, 0, 0, logfont, layout);
1795 {
1796 const char kMsg[] = "これは、Goo";
1797 std::wstring msg;
1798 mozc::Util::UTF8ToWide(kMsg, &msg);
1799 EXPECT_EQ(msg, layout.text);
1800 }
1801 ASSERT_EQ(3, layout.marker_layouts.size());
1802
1803 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
1804 EXPECT_EQ(CPoint(50, 126), layout.marker_layouts[0].to);
1805 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1806 EXPECT_EQ(CPoint(50, 135), layout.marker_layouts[1].from);
1807 EXPECT_EQ(CPoint(50, 171), layout.marker_layouts[1].to);
1808 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
1809 EXPECT_EQ(CPoint(50, 180), layout.marker_layouts[2].from);
1810 EXPECT_EQ(CPoint(50, 268), layout.marker_layouts[2].to);
1811 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
1812 }
1813
1814 // The second line
1815 {
1816 const CompositionWindowLayout &layout = layouts.at(1);
1817 EXPECT_COMPOSITION_WINDOW_LAYOUT(1932, 712, 1983, 1098, 0, 0, 51, 386,
1818 51, 0, 0, 0, 0, 0, logfont, layout);
1819 {
1820 const char kMsg[] = "gle日本語入力のTe";
1821 std::wstring msg;
1822 mozc::Util::UTF8ToWide(kMsg, &msg);
1823 EXPECT_EQ(msg, layout.text);
1824 }
1825 ASSERT_EQ(3, layout.marker_layouts.size());
1826
1827 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
1828 EXPECT_EQ(CPoint(50, 57), layout.marker_layouts[0].to);
1829 EXPECT_TRUE(layout.marker_layouts[0].highlighted);
1830 EXPECT_EQ(CPoint(50, 63), layout.marker_layouts[1].from);
1831 EXPECT_EQ(CPoint(50, 324), layout.marker_layouts[1].to);
1832 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
1833 EXPECT_EQ(CPoint(50, 333), layout.marker_layouts[2].from);
1834 EXPECT_EQ(CPoint(50, 386), layout.marker_layouts[2].to);
1835 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
1836 }
1837
1838 // The third line
1839 {
1840 const CompositionWindowLayout &layout = layouts.at(2);
1841 EXPECT_COMPOSITION_WINDOW_LAYOUT(1881, 712, 1932, 840, 0, 0, 51, 127,
1842 51, 0, 0, 127, 51, 128, logfont, layout);
1843 {
1844 const char kMsg[] = "stです";
1845 std::wstring msg;
1846 mozc::Util::UTF8ToWide(kMsg, &msg);
1847 EXPECT_EQ(msg, layout.text);
1848 }
1849 ASSERT_EQ(1, layout.marker_layouts.size());
1850
1851 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
1852 EXPECT_EQ(CPoint(50, 127), layout.marker_layouts[0].to);
1853 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1854 }
1855
1856 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1857 1983, 1017, 1983, 1017, 2034, 1105, candidate_layout);
1858
1859 // Check other candidate positions.
1860 command.mutable_output()->mutable_candidates()->set_position(0);
1861 layouts.clear();
1862 candidate_layout.Clear();
1863 result = layout_mgr.LayoutCompositionWindow(
1864 command, &layouts, &candidate_layout);
1865 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1866 1983, 837, 1983, 837, 2034, 1105, candidate_layout);
1867
1868 command.mutable_output()->mutable_candidates()->set_position(3);
1869 layouts.clear();
1870 candidate_layout.Clear();
1871 result = layout_mgr.LayoutCompositionWindow(
1872 command, &layouts, &candidate_layout);
1873 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1874 1983, 972, 1983, 972, 2034, 1105, candidate_layout);
1875
1876 command.mutable_output()->mutable_candidates()->set_position(10);
1877 layouts.clear();
1878 candidate_layout.Clear();
1879 result = layout_mgr.LayoutCompositionWindow(
1880 command, &layouts, &candidate_layout);
1881 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1882 1932, 775, 1932, 775, 1983, 1098, candidate_layout);
1883
1884 command.mutable_output()->mutable_candidates()->set_position(16);
1885 layouts.clear();
1886 candidate_layout.Clear();
1887 result = layout_mgr.LayoutCompositionWindow(
1888 command, &layouts, &candidate_layout);
1889 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1890 1932, 1045, 1932, 1045, 1983, 1098, candidate_layout);
1891
1892 // w/o candidates, monospaced, vertical
1893 SetRenderereCommandForTest(false, false, true, 0, hwnd, &command);
1894 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1895 command.application_info().composition_font(), &logfont));
1896 layouts.clear();
1897 candidate_layout.Clear();
1898 result = layout_mgr.LayoutCompositionWindow(
1899 command, &layouts, &candidate_layout);
1900 EXPECT_TRUE(result);
1901 EXPECT_FALSE(candidate_layout.initialized());
1902 }
1903
TEST_F(Win32RendererUtilTest,CompositionHorizontalNoAdditionalSegmentationWithProportionalFont)1904 TEST_F(Win32RendererUtilTest,
1905 CompositionHorizontalNoAdditionalSegmentationWithProportionalFont) {
1906 const int kCursorOffsetX = 0;
1907
1908 RendererCommand command;
1909
1910 HWND hwnd = nullptr;
1911 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
1912 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
1913 std::vector<CompositionWindowLayout> layouts;
1914 CandidateWindowLayout candidate_layout;
1915 CLogFont logfont;
1916
1917 bool result = false;
1918
1919 // w/ candidates, proportional, horizontal
1920 SetRenderereCommandForTest(
1921 true, true, false, kCursorOffsetX, hwnd, &command);
1922 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
1923 command.application_info().composition_font(), &logfont));
1924 layouts.clear();
1925 candidate_layout.Clear();
1926 result = layout_mgr.LayoutCompositionWindow(
1927 command, &layouts, &candidate_layout);
1928 EXPECT_TRUE(result);
1929
1930 ASSERT_EQ(2, layouts.size());
1931
1932 // The first line
1933 {
1934 const CompositionWindowLayout &layout = layouts.at(0);
1935 EXPECT_COMPOSITION_WINDOW_LAYOUT(1868, 599, 2003, 653, 0, 0, 135, 54,
1936 0, 0, 0, 0, 0, 0, logfont, layout);
1937 {
1938 const char kMsg[] = "これは";
1939 std::wstring msg;
1940 mozc::Util::UTF8ToWide(kMsg, &msg);
1941 EXPECT_EQ(msg, layout.text);
1942 }
1943 ASSERT_EQ(1, layout.marker_layouts.size());
1944
1945 EXPECT_EQ(CPoint(0, 53), layout.marker_layouts[0].from);
1946 EXPECT_EQ(CPoint(126, 53), layout.marker_layouts[0].to);
1947 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1948 }
1949
1950 // The second line
1951 {
1952 const CompositionWindowLayout &layout = layouts.at(1);
1953 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 653, 1840, 707, 0, 0, 646, 54,
1954 0, 0, 646, 0, 647, 54, logfont, layout);
1955 {
1956 const char kMsg[] = "、Google日本語入力のTestです";
1957 std::wstring msg;
1958 mozc::Util::UTF8ToWide(kMsg, &msg);
1959 EXPECT_EQ(msg, layout.text);
1960 }
1961 ASSERT_EQ(4, layout.marker_layouts.size());
1962
1963 EXPECT_EQ(CPoint(0, 53), layout.marker_layouts[0].from);
1964 EXPECT_EQ(CPoint(36, 53), layout.marker_layouts[0].to);
1965 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
1966 EXPECT_EQ(CPoint(45, 53), layout.marker_layouts[1].from);
1967 EXPECT_EQ(CPoint(192, 53), layout.marker_layouts[1].to);
1968 EXPECT_TRUE(layout.marker_layouts[1].highlighted);
1969 EXPECT_EQ(CPoint(197, 53), layout.marker_layouts[2].from);
1970 EXPECT_EQ(CPoint(458, 53), layout.marker_layouts[2].to);
1971 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
1972 EXPECT_EQ(CPoint(467, 53), layout.marker_layouts[3].from);
1973 EXPECT_EQ(CPoint(646, 53), layout.marker_layouts[3].to);
1974 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
1975 }
1976
1977 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1978 1238, 707, 1238, 653, 1839, 707, candidate_layout);
1979
1980 // Check other candidate positions.
1981 command.mutable_output()->mutable_candidates()->set_position(0);
1982 layouts.clear();
1983 candidate_layout.Clear();
1984 result = layout_mgr.LayoutCompositionWindow(
1985 command, &layouts, &candidate_layout);
1986 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1987 1868, 653, 1868, 599, 2003, 653, candidate_layout);
1988
1989 command.mutable_output()->mutable_candidates()->set_position(3);
1990 layouts.clear();
1991 candidate_layout.Clear();
1992 result = layout_mgr.LayoutCompositionWindow(
1993 command, &layouts, &candidate_layout);
1994 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
1995 1193, 707, 1193, 653, 1839, 707, candidate_layout);
1996
1997 command.mutable_output()->mutable_candidates()->set_position(10);
1998 layouts.clear();
1999 candidate_layout.Clear();
2000 result = layout_mgr.LayoutCompositionWindow(
2001 command, &layouts, &candidate_layout);
2002 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2003 1390, 707, 1390, 653, 1839, 707, candidate_layout);
2004
2005 command.mutable_output()->mutable_candidates()->set_position(16);
2006 layouts.clear();
2007 candidate_layout.Clear();
2008 result = layout_mgr.LayoutCompositionWindow(
2009 command, &layouts, &candidate_layout);
2010 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2011 1660, 707, 1660, 653, 1839, 707, candidate_layout);
2012
2013 // w/o candidates, proportional, horizontal
2014 SetRenderereCommandForTest(true, false, false, 0, hwnd, &command);
2015 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2016 command.application_info().composition_font(), &logfont));
2017 layouts.clear();
2018 candidate_layout.Clear();
2019 result = layout_mgr.LayoutCompositionWindow(
2020 command, &layouts, &candidate_layout);
2021 EXPECT_TRUE(result);
2022 EXPECT_FALSE(candidate_layout.initialized());
2023 }
2024
TEST_F(Win32RendererUtilTest,CompositionHorizontalAdditionalSegmentationWithProportionalFont)2025 TEST_F(Win32RendererUtilTest,
2026 CompositionHorizontalAdditionalSegmentationWithProportionalFont) {
2027 const int kCursorOffsetX = -90;
2028
2029 RendererCommand command;
2030
2031 HWND hwnd = nullptr;
2032 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2033 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2034 std::vector<CompositionWindowLayout> layouts;
2035 CandidateWindowLayout candidate_layout;
2036 CLogFont logfont;
2037
2038 bool result = false;
2039
2040 // w/ candidates, proportional, horizontal
2041 SetRenderereCommandForTest(
2042 true, true, false, kCursorOffsetX, hwnd, &command);
2043 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2044 command.application_info().composition_font(), &logfont));
2045 layouts.clear();
2046 candidate_layout.Clear();
2047 result = layout_mgr.LayoutCompositionWindow(
2048 command, &layouts, &candidate_layout);
2049 EXPECT_TRUE(result);
2050
2051 ASSERT_EQ(2, layouts.size());
2052
2053 // The first line
2054 {
2055 const CompositionWindowLayout &layout = layouts.at(0);
2056 EXPECT_COMPOSITION_WINDOW_LAYOUT(1778, 599, 2020, 653, 0, 0, 242, 54,
2057 0, 0, 0, 0, 0, 0, logfont, layout);
2058 {
2059 const char kMsg[] = "これは、Go";
2060 std::wstring msg;
2061 mozc::Util::UTF8ToWide(kMsg, &msg);
2062 EXPECT_EQ(msg, layout.text);
2063 }
2064 ASSERT_EQ(3, layout.marker_layouts.size());
2065
2066 EXPECT_EQ(CPoint(0, 53), layout.marker_layouts[0].from);
2067 EXPECT_EQ(CPoint(126, 53), layout.marker_layouts[0].to);
2068 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2069 EXPECT_EQ(CPoint(135, 53), layout.marker_layouts[1].from);
2070 EXPECT_EQ(CPoint(171, 53), layout.marker_layouts[1].to);
2071 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2072 EXPECT_EQ(CPoint(180, 53), layout.marker_layouts[2].from);
2073 EXPECT_EQ(CPoint(242, 53), layout.marker_layouts[2].to);
2074 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
2075 }
2076
2077 // The second line
2078 {
2079 const CompositionWindowLayout &layout = layouts.at(1);
2080 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 653, 1733, 707, 0, 0, 539, 54,
2081 0, 0, 539, 0, 540, 54, logfont, layout);
2082 {
2083 const char kMsg[] = "ogle日本語入力のTestです";
2084 std::wstring msg;
2085 mozc::Util::UTF8ToWide(kMsg, &msg);
2086 EXPECT_EQ(msg, layout.text);
2087 }
2088 ASSERT_EQ(3, layout.marker_layouts.size());
2089
2090 EXPECT_EQ(CPoint(0, 53), layout.marker_layouts[0].from);
2091 EXPECT_EQ(CPoint(85, 53), layout.marker_layouts[0].to);
2092 EXPECT_TRUE(layout.marker_layouts[0].highlighted);
2093 EXPECT_EQ(CPoint(90, 53), layout.marker_layouts[1].from);
2094 EXPECT_EQ(CPoint(351, 53), layout.marker_layouts[1].to);
2095 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2096 EXPECT_EQ(CPoint(360, 53), layout.marker_layouts[2].from);
2097 EXPECT_EQ(CPoint(539, 53), layout.marker_layouts[2].to);
2098 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
2099 }
2100
2101 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2102 1958, 653, 1958, 599, 2020, 653, candidate_layout);
2103
2104 // Check other candidate positions.
2105 command.mutable_output()->mutable_candidates()->set_position(0);
2106 layouts.clear();
2107 candidate_layout.Clear();
2108 result = layout_mgr.LayoutCompositionWindow(
2109 command, &layouts, &candidate_layout);
2110 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2111 1778, 653, 1778, 599, 2020, 653, candidate_layout);
2112
2113 command.mutable_output()->mutable_candidates()->set_position(3);
2114 layouts.clear();
2115 candidate_layout.Clear();
2116 result = layout_mgr.LayoutCompositionWindow(
2117 command, &layouts, &candidate_layout);
2118 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2119 1913, 653, 1913, 599, 2020, 653, candidate_layout);
2120
2121 command.mutable_output()->mutable_candidates()->set_position(10);
2122 layouts.clear();
2123 candidate_layout.Clear();
2124 result = layout_mgr.LayoutCompositionWindow(
2125 command, &layouts, &candidate_layout);
2126 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2127 1283, 707, 1283, 653, 1732, 707, candidate_layout);
2128
2129 command.mutable_output()->mutable_candidates()->set_position(16);
2130 layouts.clear();
2131 candidate_layout.Clear();
2132 result = layout_mgr.LayoutCompositionWindow(
2133 command, &layouts, &candidate_layout);
2134 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2135 1553, 707, 1553, 653, 1732, 707, candidate_layout);
2136
2137 // w/o candidates, proportional, horizontal
2138 SetRenderereCommandForTest(true, false, false, 0, hwnd, &command);
2139 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2140 command.application_info().composition_font(), &logfont));
2141 layouts.clear();
2142 candidate_layout.Clear();
2143 result = layout_mgr.LayoutCompositionWindow(
2144 command, &layouts, &candidate_layout);
2145 EXPECT_TRUE(result);
2146 EXPECT_FALSE(candidate_layout.initialized());
2147 }
2148
TEST_F(Win32RendererUtilTest,CompositionVerticalNoAdditionalSegmentationWithProportionalFont)2149 TEST_F(Win32RendererUtilTest,
2150 CompositionVerticalNoAdditionalSegmentationWithProportionalFont) {
2151 const int kCursorOffsetY = 0;
2152
2153 RendererCommand command;
2154
2155 HWND hwnd = nullptr;
2156 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2157 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2158 std::vector<CompositionWindowLayout> layouts;
2159 CandidateWindowLayout candidate_layout;
2160 CLogFont logfont;
2161
2162 bool result = false;
2163
2164 // w/ candidates, proportional, vertical
2165 SetRenderereCommandForTest(
2166 true, true, true, kCursorOffsetY, hwnd, &command);
2167 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2168 command.application_info().composition_font(), &logfont));
2169 logfont.lfOrientation = 2700;
2170
2171 layouts.clear();
2172 candidate_layout.Clear();
2173 result = layout_mgr.LayoutCompositionWindow(
2174 command, &layouts, &candidate_layout);
2175 EXPECT_TRUE(result);
2176
2177 ASSERT_EQ(3, layouts.size());
2178
2179 // The first line
2180 {
2181 const CompositionWindowLayout &layout = layouts.at(0);
2182 EXPECT_COMPOSITION_WINDOW_LAYOUT(1978, 927, 2034, 1062, 0, 0, 56, 135,
2183 56, 0, 0, 0, 0, 0, logfont, layout);
2184 {
2185 const char kMsg[] = "これは";
2186 std::wstring msg;
2187 mozc::Util::UTF8ToWide(kMsg, &msg);
2188 EXPECT_EQ(msg, layout.text);
2189 }
2190 ASSERT_EQ(1, layout.marker_layouts.size());
2191
2192 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2193 EXPECT_EQ(CPoint(55, 126), layout.marker_layouts[0].to);
2194 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2195 }
2196
2197 // The second line
2198 {
2199 const CompositionWindowLayout &layout = layouts.at(1);
2200 EXPECT_COMPOSITION_WINDOW_LAYOUT(1922, 712, 1978, 1089, 0, 0, 56, 377,
2201 56, 0, 0, 0, 0, 0, logfont, layout);
2202 {
2203 const char kMsg[] = "、Google日本語入";
2204 std::wstring msg;
2205 mozc::Util::UTF8ToWide(kMsg, &msg);
2206 EXPECT_EQ(msg, layout.text);
2207 }
2208 ASSERT_EQ(3, layout.marker_layouts.size());
2209
2210 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2211 EXPECT_EQ(CPoint(55, 36), layout.marker_layouts[0].to);
2212 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2213 EXPECT_EQ(CPoint(55, 45), layout.marker_layouts[1].from);
2214 EXPECT_EQ(CPoint(55, 192), layout.marker_layouts[1].to);
2215 EXPECT_TRUE(layout.marker_layouts[1].highlighted);
2216 EXPECT_EQ(CPoint(55, 197), layout.marker_layouts[2].from);
2217 EXPECT_EQ(CPoint(55, 377), layout.marker_layouts[2].to);
2218 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
2219 }
2220
2221 // The third line
2222 {
2223 const CompositionWindowLayout &layout = layouts.at(2);
2224 EXPECT_COMPOSITION_WINDOW_LAYOUT(1866, 712, 1922, 982, 0, 0, 56, 269,
2225 56, 0, 0, 269, 56, 270, logfont, layout);
2226 {
2227 const char kMsg[] = "力のTestです";
2228 std::wstring msg;
2229 mozc::Util::UTF8ToWide(kMsg, &msg);
2230 EXPECT_EQ(msg, layout.text);
2231 }
2232 ASSERT_EQ(2, layout.marker_layouts.size());
2233
2234 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2235 EXPECT_EQ(CPoint(55, 81), layout.marker_layouts[0].to);
2236 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2237 EXPECT_EQ(CPoint(55, 90), layout.marker_layouts[1].from);
2238 EXPECT_EQ(CPoint(55, 269), layout.marker_layouts[1].to);
2239 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2240 }
2241
2242 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2243 1922, 757, 1922, 757, 1978, 1089, candidate_layout);
2244
2245 // Check other candidate positions.
2246 command.mutable_output()->mutable_candidates()->set_position(0);
2247 layouts.clear();
2248 candidate_layout.Clear();
2249 result = layout_mgr.LayoutCompositionWindow(
2250 command, &layouts, &candidate_layout);
2251 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2252 1978, 927, 1978, 927, 2034, 1062, candidate_layout);
2253
2254 command.mutable_output()->mutable_candidates()->set_position(3);
2255 layouts.clear();
2256 candidate_layout.Clear();
2257 result = layout_mgr.LayoutCompositionWindow(
2258 command, &layouts, &candidate_layout);
2259 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2260 1922, 712, 1922, 712, 1978, 1089, candidate_layout);
2261
2262 command.mutable_output()->mutable_candidates()->set_position(10);
2263 layouts.clear();
2264 candidate_layout.Clear();
2265 result = layout_mgr.LayoutCompositionWindow(
2266 command, &layouts, &candidate_layout);
2267 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2268 1922, 909, 1922, 909, 1978, 1089, candidate_layout);
2269
2270 command.mutable_output()->mutable_candidates()->set_position(16);
2271 layouts.clear();
2272 candidate_layout.Clear();
2273 result = layout_mgr.LayoutCompositionWindow(
2274 command, &layouts, &candidate_layout);
2275 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2276 1866, 802, 1866, 802, 1922, 981, candidate_layout);
2277
2278 // w/o candidates, proportional, vertical
2279 SetRenderereCommandForTest(true, false, true, 0, hwnd, &command);
2280 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2281 command.application_info().composition_font(), &logfont));
2282 layouts.clear();
2283 candidate_layout.Clear();
2284 result = layout_mgr.LayoutCompositionWindow(
2285 command, &layouts, &candidate_layout);
2286 EXPECT_TRUE(result);
2287 EXPECT_FALSE(candidate_layout.initialized());
2288 }
2289
TEST_F(Win32RendererUtilTest,CompositionVerticalAdditionalSegmentationWithProportionalFont)2290 TEST_F(Win32RendererUtilTest,
2291 CompositionVerticalAdditionalSegmentationWithProportionalFont) {
2292 const int kCursorOffsetY = -90;
2293
2294 RendererCommand command;
2295
2296 HWND hwnd = nullptr;
2297 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2298 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2299 std::vector<CompositionWindowLayout> layouts;
2300 CandidateWindowLayout candidate_layout;
2301 CLogFont logfont;
2302
2303 bool result = false;
2304
2305 // w/ candidates, proportional, vertical
2306 SetRenderereCommandForTest(
2307 true, true, true, kCursorOffsetY, hwnd, &command);
2308 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2309 command.application_info().composition_font(), &logfont));
2310 logfont.lfOrientation = 2700;
2311
2312 layouts.clear();
2313 candidate_layout.Clear();
2314 result = layout_mgr.LayoutCompositionWindow(
2315 command, &layouts, &candidate_layout);
2316 EXPECT_TRUE(result);
2317
2318 ASSERT_EQ(3, layouts.size());
2319
2320 // The first line
2321 {
2322 const CompositionWindowLayout &layout = layouts.at(0);
2323 EXPECT_COMPOSITION_WINDOW_LAYOUT(1978, 837, 2034, 1079, 0, 0, 56, 242,
2324 56, 0, 0, 0, 0, 0, logfont, layout);
2325 {
2326 const char kMsg[] = "これは、Go";
2327 std::wstring msg;
2328 mozc::Util::UTF8ToWide(kMsg, &msg);
2329 EXPECT_EQ(msg, layout.text);
2330 }
2331 ASSERT_EQ(3, layout.marker_layouts.size());
2332
2333 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2334 EXPECT_EQ(CPoint(55, 126), layout.marker_layouts[0].to);
2335 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2336 EXPECT_EQ(CPoint(55, 135), layout.marker_layouts[1].from);
2337 EXPECT_EQ(CPoint(55, 171), layout.marker_layouts[1].to);
2338 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2339 EXPECT_EQ(CPoint(55, 180), layout.marker_layouts[2].from);
2340 EXPECT_EQ(CPoint(55, 242), layout.marker_layouts[2].to);
2341 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
2342 }
2343
2344 // The second line
2345 {
2346 const CompositionWindowLayout &layout = layouts.at(1);
2347 EXPECT_COMPOSITION_WINDOW_LAYOUT(1922, 712, 1978, 1100, 0, 0, 56, 388,
2348 56, 0, 0, 0, 0, 0, logfont, layout);
2349 {
2350 const char kMsg[] = "ogle日本語入力のT";
2351 std::wstring msg;
2352 mozc::Util::UTF8ToWide(kMsg, &msg);
2353 EXPECT_EQ(msg, layout.text);
2354 }
2355 ASSERT_EQ(3, layout.marker_layouts.size());
2356
2357 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2358 EXPECT_EQ(CPoint(55, 85), layout.marker_layouts[0].to);
2359 EXPECT_TRUE(layout.marker_layouts[0].highlighted);
2360 EXPECT_EQ(CPoint(55, 90), layout.marker_layouts[1].from);
2361 EXPECT_EQ(CPoint(55, 351), layout.marker_layouts[1].to);
2362 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2363 EXPECT_EQ(CPoint(55, 360), layout.marker_layouts[2].from);
2364 EXPECT_EQ(CPoint(55, 388), layout.marker_layouts[2].to);
2365 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
2366 }
2367
2368 // The third line
2369 {
2370 const CompositionWindowLayout &layout = layouts.at(2);
2371 EXPECT_COMPOSITION_WINDOW_LAYOUT(1866, 712, 1922, 864, 0, 0, 56, 151,
2372 56, 0, 0, 151, 56, 152, logfont, layout);
2373 {
2374 const char kMsg[] = "estです";
2375 std::wstring msg;
2376 mozc::Util::UTF8ToWide(kMsg, &msg);
2377 EXPECT_EQ(msg, layout.text);
2378 }
2379 ASSERT_EQ(1, layout.marker_layouts.size());
2380
2381 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2382 EXPECT_EQ(CPoint(55, 151), layout.marker_layouts[0].to);
2383 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2384 }
2385
2386 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2387 1978, 1017, 1978, 1017, 2034, 1079, candidate_layout);
2388
2389 // Check other candidate positions.
2390 command.mutable_output()->mutable_candidates()->set_position(0);
2391 layouts.clear();
2392 candidate_layout.Clear();
2393 result = layout_mgr.LayoutCompositionWindow(
2394 command, &layouts, &candidate_layout);
2395 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2396 1978, 837, 1978, 837, 2034, 1079, candidate_layout);
2397
2398 command.mutable_output()->mutable_candidates()->set_position(3);
2399 layouts.clear();
2400 candidate_layout.Clear();
2401 result = layout_mgr.LayoutCompositionWindow(
2402 command, &layouts, &candidate_layout);
2403 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2404 1978, 972, 1978, 972, 2034, 1079, candidate_layout);
2405
2406 command.mutable_output()->mutable_candidates()->set_position(10);
2407 layouts.clear();
2408 candidate_layout.Clear();
2409 result = layout_mgr.LayoutCompositionWindow(
2410 command, &layouts, &candidate_layout);
2411 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2412 1922, 802, 1922, 802, 1978, 1100, candidate_layout);
2413
2414 command.mutable_output()->mutable_candidates()->set_position(16);
2415 layouts.clear();
2416 candidate_layout.Clear();
2417 result = layout_mgr.LayoutCompositionWindow(
2418 command, &layouts, &candidate_layout);
2419 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
2420 1922, 1072, 1922, 1072, 1978, 1100, candidate_layout);
2421
2422 // w/o candidates, proportional, vertical
2423 SetRenderereCommandForTest(false, false, true, 0, hwnd, &command);
2424 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2425 command.application_info().composition_font(), &logfont));
2426 layouts.clear();
2427 candidate_layout.Clear();
2428 result = layout_mgr.LayoutCompositionWindow(
2429 command, &layouts, &candidate_layout);
2430 EXPECT_TRUE(result);
2431 EXPECT_FALSE(candidate_layout.initialized());
2432 }
2433
TEST_F(Win32RendererUtilTest,CompositionHorizontalFirstLineIsEmptyWithMonospacedFont)2434 TEST_F(Win32RendererUtilTest,
2435 CompositionHorizontalFirstLineIsEmptyWithMonospacedFont) {
2436 const int kCursorOffsetX = 120;
2437
2438 RendererCommand command;
2439
2440 HWND hwnd = nullptr;
2441 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2442 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2443 std::vector<CompositionWindowLayout> layouts;
2444 CandidateWindowLayout candidate_layout;
2445 CLogFont logfont;
2446
2447 bool result = false;
2448
2449 // w/ candidates, monospaced, horizontal
2450 SetRenderereCommandForTest(
2451 false, true, false, kCursorOffsetX, hwnd, &command);
2452 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2453 command.application_info().composition_font(), &logfont));
2454 layouts.clear();
2455 candidate_layout.Clear();
2456 result = layout_mgr.LayoutCompositionWindow(
2457 command, &layouts, &candidate_layout);
2458 EXPECT_TRUE(result);
2459
2460 ASSERT_EQ(1, layouts.size());
2461
2462 // The first line
2463 {
2464 const CompositionWindowLayout &layout = layouts.at(0);
2465 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 648, 1975, 697, 0, 0, 781, 49,
2466 0, 0, 781, 0, 782, 49, logfont, layout);
2467 {
2468 const char kMsg[] = "これは、Google日本語入力のTestです";
2469 std::wstring msg;
2470 mozc::Util::UTF8ToWide(kMsg, &msg);
2471 EXPECT_EQ(msg, layout.text);
2472 }
2473 ASSERT_EQ(5, layout.marker_layouts.size());
2474
2475 EXPECT_EQ(CPoint(0, 48), layout.marker_layouts[0].from);
2476 EXPECT_EQ(CPoint(126, 48), layout.marker_layouts[0].to);
2477 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2478 EXPECT_EQ(CPoint(135, 48), layout.marker_layouts[1].from);
2479 EXPECT_EQ(CPoint(171, 48), layout.marker_layouts[1].to);
2480 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2481 EXPECT_EQ(CPoint(180, 48), layout.marker_layouts[2].from);
2482 EXPECT_EQ(CPoint(325, 48), layout.marker_layouts[2].to);
2483 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
2484 EXPECT_EQ(CPoint(331, 48), layout.marker_layouts[3].from);
2485 EXPECT_EQ(CPoint(592, 48), layout.marker_layouts[3].to);
2486 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
2487 EXPECT_EQ(CPoint(601, 48), layout.marker_layouts[4].from);
2488 EXPECT_EQ(CPoint(781, 48), layout.marker_layouts[4].to);
2489 EXPECT_FALSE(layout.marker_layouts[4].highlighted);
2490 }
2491 }
2492
TEST_F(Win32RendererUtilTest,CompositionHorizontalFirstLineIsEmptyWithProportionalFont)2493 TEST_F(Win32RendererUtilTest,
2494 CompositionHorizontalFirstLineIsEmptyWithProportionalFont) {
2495 const int kCursorOffsetX = 120;
2496
2497 RendererCommand command;
2498
2499 HWND hwnd = nullptr;
2500 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2501 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2502 std::vector<CompositionWindowLayout> layouts;
2503 CandidateWindowLayout candidate_layout;
2504 CLogFont logfont;
2505
2506 bool result = false;
2507
2508 // w/ candidates, proportional, horizontal
2509 SetRenderereCommandForTest(
2510 true, true, false, kCursorOffsetX, hwnd, &command);
2511 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2512 command.application_info().composition_font(), &logfont));
2513 layouts.clear();
2514 candidate_layout.Clear();
2515 result = layout_mgr.LayoutCompositionWindow(
2516 command, &layouts, &candidate_layout);
2517 EXPECT_TRUE(result);
2518
2519 ASSERT_EQ(1, layouts.size());
2520
2521 // The first line
2522 {
2523 const CompositionWindowLayout &layout = layouts.at(0);
2524 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 653, 1975, 707, 0, 0, 781, 54,
2525 0, 0, 781, 0, 782, 54, logfont, layout);
2526 {
2527 const char kMsg[] = "これは、Google日本語入力のTestです";
2528 std::wstring msg;
2529 mozc::Util::UTF8ToWide(kMsg, &msg);
2530 EXPECT_EQ(msg, layout.text);
2531 }
2532 ASSERT_EQ(5, layout.marker_layouts.size());
2533
2534 EXPECT_EQ(CPoint(0, 53), layout.marker_layouts[0].from);
2535 EXPECT_EQ(CPoint(126, 53), layout.marker_layouts[0].to);
2536 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2537 EXPECT_EQ(CPoint(135, 53), layout.marker_layouts[1].from);
2538 EXPECT_EQ(CPoint(171, 53), layout.marker_layouts[1].to);
2539 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2540 EXPECT_EQ(CPoint(180, 53), layout.marker_layouts[2].from);
2541 EXPECT_EQ(CPoint(327, 53), layout.marker_layouts[2].to);
2542 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
2543 EXPECT_EQ(CPoint(332, 53), layout.marker_layouts[3].from);
2544 EXPECT_EQ(CPoint(593, 53), layout.marker_layouts[3].to);
2545 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
2546 EXPECT_EQ(CPoint(602, 53), layout.marker_layouts[4].from);
2547 EXPECT_EQ(CPoint(781, 53), layout.marker_layouts[4].to);
2548 EXPECT_FALSE(layout.marker_layouts[4].highlighted);
2549 }
2550 }
2551
TEST_F(Win32RendererUtilTest,CompositionVerticalFirstLineIsEmptyWithMonospacedFont)2552 TEST_F(Win32RendererUtilTest,
2553 CompositionVerticalFirstLineIsEmptyWithMonospacedFont) {
2554 const int kCursorOffsetY = 170;
2555
2556 RendererCommand command;
2557
2558 HWND hwnd = nullptr;
2559 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2560 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2561 std::vector<CompositionWindowLayout> layouts;
2562 CandidateWindowLayout candidate_layout;
2563 CLogFont logfont;
2564
2565 bool result = false;
2566
2567 // w/ candidates, monospaced, vertical
2568 SetRenderereCommandForTest(
2569 false, true, true, kCursorOffsetY, hwnd, &command);
2570 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2571 command.application_info().composition_font(), &logfont));
2572 logfont.lfOrientation = 2700;
2573
2574 layouts.clear();
2575 candidate_layout.Clear();
2576 result = layout_mgr.LayoutCompositionWindow(
2577 command, &layouts, &candidate_layout);
2578 EXPECT_TRUE(result);
2579
2580 ASSERT_EQ(3, layouts.size());
2581
2582 // The first line
2583 {
2584 const CompositionWindowLayout &layout = layouts.at(0);
2585 EXPECT_COMPOSITION_WINDOW_LAYOUT(1932, 712, 1983, 1088, 0, 0, 51, 376,
2586 51, 0, 0, 0, 0, 0, logfont, layout);
2587 {
2588 const char kMsg[] = "これは、Google日";
2589 std::wstring msg;
2590 mozc::Util::UTF8ToWide(kMsg, &msg);
2591 EXPECT_EQ(msg, layout.text);
2592 }
2593 ASSERT_EQ(4, layout.marker_layouts.size());
2594
2595 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
2596 EXPECT_EQ(CPoint(50, 126), layout.marker_layouts[0].to);
2597 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2598 EXPECT_EQ(CPoint(50, 135), layout.marker_layouts[1].from);
2599 EXPECT_EQ(CPoint(50, 171), layout.marker_layouts[1].to);
2600 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2601 EXPECT_EQ(CPoint(50, 180), layout.marker_layouts[2].from);
2602 EXPECT_EQ(CPoint(50, 325), layout.marker_layouts[2].to);
2603 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
2604 EXPECT_EQ(CPoint(50, 331), layout.marker_layouts[3].from);
2605 EXPECT_EQ(CPoint(50, 376), layout.marker_layouts[3].to);
2606 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
2607 }
2608
2609 // The second line
2610 {
2611 const CompositionWindowLayout &layout = layouts.at(1);
2612 EXPECT_COMPOSITION_WINDOW_LAYOUT(1881, 712, 1932, 1072, 0, 0, 51, 360,
2613 51, 0, 0, 0, 0, 0, logfont, layout);
2614 {
2615 const char kMsg[] = "本語入力のTestで";
2616 std::wstring msg;
2617 mozc::Util::UTF8ToWide(kMsg, &msg);
2618 EXPECT_EQ(msg, layout.text);
2619 }
2620 ASSERT_EQ(2, layout.marker_layouts.size());
2621
2622 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
2623 EXPECT_EQ(CPoint(50, 216), layout.marker_layouts[0].to);
2624 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2625 EXPECT_EQ(CPoint(50, 225), layout.marker_layouts[1].from);
2626 EXPECT_EQ(CPoint(50, 360), layout.marker_layouts[1].to);
2627 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2628 }
2629
2630 // The third line
2631 {
2632 const CompositionWindowLayout &layout = layouts.at(2);
2633 EXPECT_COMPOSITION_WINDOW_LAYOUT(1830, 712, 1881, 758, 0, 0, 51, 45,
2634 51, 0, 0, 45, 51, 46, logfont, layout);
2635 {
2636 const char kMsg[] = "す";
2637 std::wstring msg;
2638 mozc::Util::UTF8ToWide(kMsg, &msg);
2639 EXPECT_EQ(msg, layout.text);
2640 }
2641 ASSERT_EQ(1, layout.marker_layouts.size());
2642
2643 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
2644 EXPECT_EQ(CPoint(50, 45), layout.marker_layouts[0].to);
2645 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2646 }
2647 }
2648
TEST_F(Win32RendererUtilTest,CompositionVerticalFirstLineIsEmptyWithProportionalFont)2649 TEST_F(Win32RendererUtilTest,
2650 CompositionVerticalFirstLineIsEmptyWithProportionalFont) {
2651 const int kCursorOffsetY = 170;
2652
2653 RendererCommand command;
2654
2655 HWND hwnd = nullptr;
2656 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2657 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2658 std::vector<CompositionWindowLayout> layouts;
2659 CandidateWindowLayout candidate_layout;
2660 CLogFont logfont;
2661
2662 bool result = false;
2663
2664 // w/ candidates, proportional, vertical
2665 SetRenderereCommandForTest(
2666 true, true, true, kCursorOffsetY, hwnd, &command);
2667 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2668 command.application_info().composition_font(), &logfont));
2669 logfont.lfOrientation = 2700;
2670
2671 layouts.clear();
2672 candidate_layout.Clear();
2673 result = layout_mgr.LayoutCompositionWindow(
2674 command, &layouts, &candidate_layout);
2675 EXPECT_TRUE(result);
2676
2677 ASSERT_EQ(3, layouts.size());
2678
2679 // The first line
2680 {
2681 const CompositionWindowLayout &layout = layouts.at(0);
2682 EXPECT_COMPOSITION_WINDOW_LAYOUT(1922, 712, 1978, 1089, 0, 0, 56, 377,
2683 56, 0, 0, 0, 0, 0, logfont, layout);
2684 {
2685 const char kMsg[] = "これは、Google日";
2686 std::wstring msg;
2687 mozc::Util::UTF8ToWide(kMsg, &msg);
2688 EXPECT_EQ(msg, layout.text);
2689 }
2690 ASSERT_EQ(4, layout.marker_layouts.size());
2691
2692 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2693 EXPECT_EQ(CPoint(55, 126), layout.marker_layouts[0].to);
2694 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2695 EXPECT_EQ(CPoint(55, 135), layout.marker_layouts[1].from);
2696 EXPECT_EQ(CPoint(55, 171), layout.marker_layouts[1].to);
2697 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2698 EXPECT_EQ(CPoint(55, 180), layout.marker_layouts[2].from);
2699 EXPECT_EQ(CPoint(55, 327), layout.marker_layouts[2].to);
2700 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
2701 EXPECT_EQ(CPoint(55, 332), layout.marker_layouts[3].from);
2702 EXPECT_EQ(CPoint(55, 377), layout.marker_layouts[3].to);
2703 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
2704 }
2705
2706 // The second line
2707 {
2708 const CompositionWindowLayout &layout = layouts.at(1);
2709 EXPECT_COMPOSITION_WINDOW_LAYOUT(1866, 712, 1922, 1071, 0, 0, 56, 359,
2710 56, 0, 0, 0, 0, 0, logfont, layout);
2711 {
2712 const char kMsg[] = "本語入力のTestで";
2713 std::wstring msg;
2714 mozc::Util::UTF8ToWide(kMsg, &msg);
2715 EXPECT_EQ(msg, layout.text);
2716 }
2717 ASSERT_EQ(2, layout.marker_layouts.size());
2718
2719 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2720 EXPECT_EQ(CPoint(55, 216), layout.marker_layouts[0].to);
2721 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2722 EXPECT_EQ(CPoint(55, 225), layout.marker_layouts[1].from);
2723 EXPECT_EQ(CPoint(55, 359), layout.marker_layouts[1].to);
2724 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
2725 }
2726
2727 // The third line
2728 {
2729 const CompositionWindowLayout &layout = layouts.at(2);
2730 EXPECT_COMPOSITION_WINDOW_LAYOUT(1810, 712, 1866, 758, 0, 0, 56, 45,
2731 56, 0, 0, 45, 56, 46, logfont, layout);
2732 {
2733 const char kMsg[] = "す";
2734 std::wstring msg;
2735 mozc::Util::UTF8ToWide(kMsg, &msg);
2736 EXPECT_EQ(msg, layout.text);
2737 }
2738 ASSERT_EQ(1, layout.marker_layouts.size());
2739
2740 EXPECT_EQ(CPoint(55, 0), layout.marker_layouts[0].from);
2741 EXPECT_EQ(CPoint(55, 45), layout.marker_layouts[0].to);
2742 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
2743 }
2744 }
2745
TEST_F(Win32RendererUtilTest,CheckCaretPosInHorizontalComposition)2746 TEST_F(Win32RendererUtilTest, CheckCaretPosInHorizontalComposition) {
2747 // Check the caret points the first character.
2748 {
2749 const int kCursorOffsetX = -300;
2750 HWND hwnd = nullptr;
2751 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2752 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2753 std::vector<CompositionWindowLayout> layouts;
2754
2755 RendererCommand command;
2756 CandidateWindowLayout candidate_layout;
2757 CLogFont logfont;
2758 bool result = false;
2759 SetRenderereCommandForCaretTest(
2760 false, false, 10, 0, kCursorOffsetX, hwnd, &command);
2761 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2762 command.application_info().composition_font(), &logfont));
2763 layouts.clear();
2764 candidate_layout.Clear();
2765 result = layout_mgr.LayoutCompositionWindow(
2766 command, &layouts, &candidate_layout);
2767 EXPECT_TRUE(result);
2768
2769 ASSERT_EQ(1, layouts.size());
2770
2771 {
2772 const CompositionWindowLayout &layout = layouts.at(0);
2773 EXPECT_COMPOSITION_WINDOW_LAYOUT(1568, 599, 2018, 648, 0, 0, 450, 49,
2774 0, 0, 0, 0, 1, 49, logfont, layout);
2775 }
2776 }
2777
2778 // Check the caret points the middle character.
2779 {
2780 const int kCursorOffsetX = -300;
2781 HWND hwnd = nullptr;
2782 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2783 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2784 std::vector<CompositionWindowLayout> layouts;
2785
2786 RendererCommand command;
2787 CandidateWindowLayout candidate_layout;
2788 CLogFont logfont;
2789 bool result = false;
2790 SetRenderereCommandForCaretTest(
2791 false, false, 10, 5, kCursorOffsetX, hwnd, &command);
2792 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2793 command.application_info().composition_font(), &logfont));
2794 layouts.clear();
2795 candidate_layout.Clear();
2796 result = layout_mgr.LayoutCompositionWindow(
2797 command, &layouts, &candidate_layout);
2798 EXPECT_TRUE(result);
2799
2800 ASSERT_EQ(1, layouts.size());
2801
2802 {
2803 const CompositionWindowLayout &layout = layouts.at(0);
2804 EXPECT_COMPOSITION_WINDOW_LAYOUT(1568, 599, 2018, 648, 0, 0, 450, 49,
2805 0, 0, 225, 0, 226, 49, logfont, layout);
2806 }
2807 }
2808
2809 // Check the caret points the next to the last character.
2810 // In this case, composition window should have an extra space to draw the
2811 // caret except that there is no room to extend.
2812 {
2813 const int kCursorOffsetX = -300;
2814 HWND hwnd = nullptr;
2815 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2816 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2817 std::vector<CompositionWindowLayout> layouts;
2818
2819 RendererCommand command;
2820 CandidateWindowLayout candidate_layout;
2821 CLogFont logfont;
2822 bool result = false;
2823 SetRenderereCommandForCaretTest(
2824 false, false, 10, 10, kCursorOffsetX, hwnd, &command);
2825 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2826 command.application_info().composition_font(), &logfont));
2827 layouts.clear();
2828 candidate_layout.Clear();
2829 result = layout_mgr.LayoutCompositionWindow(
2830 command, &layouts, &candidate_layout);
2831 EXPECT_TRUE(result);
2832
2833 ASSERT_EQ(1, layouts.size());
2834
2835 {
2836 const CompositionWindowLayout &layout = layouts.at(0);
2837 EXPECT_COMPOSITION_WINDOW_LAYOUT(1568, 599, 2019, 648, 0, 0, 450, 49,
2838 0, 0, 450, 0, 451, 49, logfont, layout);
2839 }
2840 }
2841
2842 // To emulate built-in edit control, we will adjust caret position to be
2843 // inside of the line if it exceeds the end of line.
2844 {
2845 const int kCursorOffsetX = -287;
2846 HWND hwnd = nullptr;
2847 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2848 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2849 std::vector<CompositionWindowLayout> layouts;
2850
2851 RendererCommand command;
2852 CandidateWindowLayout candidate_layout;
2853 CLogFont logfont;
2854 bool result = false;
2855 SetRenderereCommandForCaretTest(
2856 false, false, 10, 10, kCursorOffsetX, hwnd, &command);
2857 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2858 command.application_info().composition_font(), &logfont));
2859 layouts.clear();
2860 candidate_layout.Clear();
2861 result = layout_mgr.LayoutCompositionWindow(
2862 command, &layouts, &candidate_layout);
2863 EXPECT_TRUE(result);
2864
2865 ASSERT_EQ(1, layouts.size());
2866
2867 {
2868 const CompositionWindowLayout &layout = layouts.at(0);
2869 EXPECT_COMPOSITION_WINDOW_LAYOUT(1581, 599, 2031, 648, 0, 0, 450, 49,
2870 0, 0, 449, 0, 450, 49, logfont, layout);
2871 }
2872 }
2873
2874 // If there exists other characters in the next line, caret position should
2875 // not be adjusted.
2876 {
2877 const int kCursorOffsetX = -287;
2878 HWND hwnd = nullptr;
2879 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2880 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2881 std::vector<CompositionWindowLayout> layouts;
2882
2883 RendererCommand command;
2884 CandidateWindowLayout candidate_layout;
2885 CLogFont logfont;
2886 bool result = false;
2887 SetRenderereCommandForCaretTest(
2888 false, false, 11, 10, kCursorOffsetX, hwnd, &command);
2889 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2890 command.application_info().composition_font(), &logfont));
2891 layouts.clear();
2892 candidate_layout.Clear();
2893 result = layout_mgr.LayoutCompositionWindow(
2894 command, &layouts, &candidate_layout);
2895 EXPECT_TRUE(result);
2896
2897 ASSERT_EQ(2, layouts.size());
2898
2899 {
2900 const CompositionWindowLayout &layout = layouts.at(0);
2901 EXPECT_COMPOSITION_WINDOW_LAYOUT(1581, 599, 2031, 648, 0, 0, 450, 49,
2902 0, 0, 0, 0, 0, 0, logfont, layout);
2903 }
2904
2905 {
2906 const CompositionWindowLayout &layout = layouts.at(1);
2907 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 648, 1238, 697, 0, 0, 45, 49,
2908 0, 0, 0, 0, 1, 49, logfont, layout);
2909 }
2910 }
2911 }
2912
TEST_F(Win32RendererUtilTest,CheckCaretPosInVerticalComposition)2913 TEST_F(Win32RendererUtilTest, CheckCaretPosInVerticalComposition) {
2914 // Check the caret points the first character.
2915 {
2916 const int kCursorOffsetY = -10;
2917 HWND hwnd = nullptr;
2918 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2919 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2920 std::vector<CompositionWindowLayout> layouts;
2921
2922 RendererCommand command;
2923 CandidateWindowLayout candidate_layout;
2924 CLogFont logfont;
2925 bool result = false;
2926 SetRenderereCommandForCaretTest(
2927 false, true, 4, 0, kCursorOffsetY, hwnd, &command);
2928 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2929 command.application_info().composition_font(), &logfont));
2930 logfont.lfOrientation = 2700;
2931
2932 layouts.clear();
2933 candidate_layout.Clear();
2934 result = layout_mgr.LayoutCompositionWindow(
2935 command, &layouts, &candidate_layout);
2936 EXPECT_TRUE(result);
2937
2938 ASSERT_EQ(1, layouts.size());
2939
2940 {
2941 const CompositionWindowLayout &layout = layouts.at(0);
2942 EXPECT_COMPOSITION_WINDOW_LAYOUT(1983, 917, 2034, 1097, 0, 0, 51, 180,
2943 51, 0, 0, 0, 51, 1, logfont, layout);
2944 }
2945 }
2946
2947 // Check the caret points the middle character.
2948 {
2949 const int kCursorOffsetY = -10;
2950 HWND hwnd = nullptr;
2951 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2952 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2953 std::vector<CompositionWindowLayout> layouts;
2954
2955 RendererCommand command;
2956 CandidateWindowLayout candidate_layout;
2957 CLogFont logfont;
2958 bool result = false;
2959 SetRenderereCommandForCaretTest(
2960 false, true, 4, 2, kCursorOffsetY, hwnd, &command);
2961 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2962 command.application_info().composition_font(), &logfont));
2963 logfont.lfOrientation = 2700;
2964
2965 layouts.clear();
2966 candidate_layout.Clear();
2967 result = layout_mgr.LayoutCompositionWindow(
2968 command, &layouts, &candidate_layout);
2969 EXPECT_TRUE(result);
2970
2971 ASSERT_EQ(1, layouts.size());
2972
2973 {
2974 const CompositionWindowLayout &layout = layouts.at(0);
2975 EXPECT_COMPOSITION_WINDOW_LAYOUT(1983, 917, 2034, 1097, 0, 0, 51, 180,
2976 51, 0, 0, 90, 51, 91, logfont, layout);
2977 }
2978 }
2979
2980 // Check the caret points the next to the last character.
2981 // In this case, composition window should have an extra space to draw the
2982 // caret except that there is no room to extend.
2983 {
2984 const int kCursorOffsetY = -10;
2985 HWND hwnd = nullptr;
2986 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
2987 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
2988 std::vector<CompositionWindowLayout> layouts;
2989
2990 RendererCommand command;
2991 CandidateWindowLayout candidate_layout;
2992 CLogFont logfont;
2993 bool result = false;
2994 SetRenderereCommandForCaretTest(
2995 false, true, 4, 4, kCursorOffsetY, hwnd, &command);
2996 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
2997 command.application_info().composition_font(), &logfont));
2998 logfont.lfOrientation = 2700;
2999
3000 layouts.clear();
3001 candidate_layout.Clear();
3002 result = layout_mgr.LayoutCompositionWindow(
3003 command, &layouts, &candidate_layout);
3004 EXPECT_TRUE(result);
3005
3006 ASSERT_EQ(1, layouts.size());
3007
3008 {
3009 const CompositionWindowLayout &layout = layouts.at(0);
3010 EXPECT_COMPOSITION_WINDOW_LAYOUT(1983, 917, 2034, 1098, 0, 0, 51, 180,
3011 51, 0, 0, 180, 51, 181, logfont, layout);
3012 }
3013 }
3014
3015 // To emulate built-in edit control, we will adjust caret position to be
3016 // inside of the line if it exceeds the end of line.
3017 {
3018 const int kCursorOffsetY = -2;
3019 HWND hwnd = nullptr;
3020 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
3021 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
3022 std::vector<CompositionWindowLayout> layouts;
3023
3024 RendererCommand command;
3025 CandidateWindowLayout candidate_layout;
3026 CLogFont logfont;
3027 bool result = false;
3028 SetRenderereCommandForCaretTest(
3029 false, true, 4, 4, kCursorOffsetY, hwnd, &command);
3030 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3031 command.application_info().composition_font(), &logfont));
3032 logfont.lfOrientation = 2700;
3033
3034 layouts.clear();
3035 candidate_layout.Clear();
3036 result = layout_mgr.LayoutCompositionWindow(
3037 command, &layouts, &candidate_layout);
3038 EXPECT_TRUE(result);
3039
3040 ASSERT_EQ(1, layouts.size());
3041
3042 {
3043 const CompositionWindowLayout &layout = layouts.at(0);
3044 EXPECT_COMPOSITION_WINDOW_LAYOUT(1983, 925, 2034, 1105, 0, 0, 51, 180,
3045 51, 0, 0, 179, 51, 180, logfont, layout);
3046 }
3047 }
3048
3049 // If there exists other characters in the next line, caret position should
3050 // not be adjusted.
3051 {
3052 const int kCursorOffsetY = -2;
3053 HWND hwnd = nullptr;
3054 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
3055 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
3056 std::vector<CompositionWindowLayout> layouts;
3057
3058 RendererCommand command;
3059 CandidateWindowLayout candidate_layout;
3060 CLogFont logfont;
3061 bool result = false;
3062 SetRenderereCommandForCaretTest(
3063 false, true, 5, 4, kCursorOffsetY, hwnd, &command);
3064 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3065 command.application_info().composition_font(), &logfont));
3066 logfont.lfOrientation = 2700;
3067
3068 layouts.clear();
3069 candidate_layout.Clear();
3070 result = layout_mgr.LayoutCompositionWindow(
3071 command, &layouts, &candidate_layout);
3072 EXPECT_TRUE(result);
3073
3074 ASSERT_EQ(2, layouts.size());
3075
3076 {
3077 const CompositionWindowLayout &layout = layouts.at(0);
3078 EXPECT_COMPOSITION_WINDOW_LAYOUT(1983, 925, 2034, 1105, 0, 0, 51, 180,
3079 51, 0, 0, 0, 0, 0, logfont, layout);
3080 }
3081
3082 {
3083 const CompositionWindowLayout &layout = layouts.at(1);
3084 EXPECT_COMPOSITION_WINDOW_LAYOUT(1932, 712, 1983, 757, 0, 0, 51, 45,
3085 51, 0, 0, 0, 51, 1, logfont, layout);
3086 }
3087 }
3088 }
3089
3090 // Check if suggest window does not hide preedit.
3091 // See b/4317753 for details.
TEST_F(Win32RendererUtilTest,SuggestWindowNeverHidesHorizontalPreedit)3092 TEST_F(Win32RendererUtilTest, SuggestWindowNeverHidesHorizontalPreedit) {
3093 const int kCursorOffsetX = 0;
3094
3095 RendererCommand command;
3096
3097 HWND hwnd = nullptr;
3098 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
3099 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
3100 std::vector<CompositionWindowLayout> layouts;
3101 CandidateWindowLayout candidate_layout;
3102 CLogFont logfont;
3103
3104 bool result = false;
3105
3106 // w/ candidates, proportional, horizontal
3107 SetRenderereCommandForSuggestTest(true, false, kCursorOffsetX,
3108 hwnd, &command);
3109 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3110 command.application_info().composition_font(), &logfont));
3111 layouts.clear();
3112 candidate_layout.Clear();
3113 result = layout_mgr.LayoutCompositionWindow(
3114 command, &layouts, &candidate_layout);
3115 EXPECT_TRUE(result);
3116
3117 // Suggest window should be aligned to the last composition window.
3118 EXPECT_EQ(layouts.rbegin()->window_position_in_screen_coordinate.left,
3119 candidate_layout.position().x);
3120 EXPECT_EQ(layouts.rbegin()->window_position_in_screen_coordinate.bottom,
3121 candidate_layout.position().y);
3122 EXPECT_EQ(CRect(1193, 599, 2003, 707), candidate_layout.exclude_region());
3123 }
3124
3125 // Check if suggest window does not hide preedit.
3126 // See b/4317753 for details.
TEST_F(Win32RendererUtilTest,SuggestWindowNeverHidesVerticalPreedit)3127 TEST_F(Win32RendererUtilTest, SuggestWindowNeverHidesVerticalPreedit) {
3128 const int kCursorOffsetY = 0;
3129
3130 RendererCommand command;
3131
3132 HWND hwnd = nullptr;
3133 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
3134 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
3135 std::vector<CompositionWindowLayout> layouts;
3136 CandidateWindowLayout candidate_layout;
3137 CLogFont logfont;
3138
3139 bool result = false;
3140
3141 // w/ candidates, proportional, horizontal
3142 SetRenderereCommandForSuggestTest(true, true, kCursorOffsetY,
3143 hwnd, &command);
3144 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3145 command.application_info().composition_font(), &logfont));
3146 layouts.clear();
3147 candidate_layout.Clear();
3148 result = layout_mgr.LayoutCompositionWindow(
3149 command, &layouts, &candidate_layout);
3150 EXPECT_TRUE(result);
3151
3152 // Suggest window should be aligned to the first composition window.
3153 // TODO(yukawa): Use the last composition window when vertical candidate
3154 // window is implemented.
3155 EXPECT_EQ(layouts.begin()->window_position_in_screen_coordinate.left,
3156 candidate_layout.position().x);
3157 EXPECT_EQ(layouts.begin()->window_position_in_screen_coordinate.top,
3158 candidate_layout.position().y);
3159 EXPECT_EQ(CRect(1978, 927, 2034, 1062), candidate_layout.exclude_region());
3160 }
3161
TEST_F(Win32RendererUtilTest,RemoveUnderlineFromFont_Issue2935480)3162 TEST_F(Win32RendererUtilTest, RemoveUnderlineFromFont_Issue2935480) {
3163 const int kCursorOffsetY = 0;
3164 HWND hwnd = nullptr;
3165 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
3166 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
3167 std::vector<CompositionWindowLayout> layouts;
3168
3169 RendererCommand command;
3170 CandidateWindowLayout candidate_layout;
3171 CLogFont logfont;
3172 bool result = false;
3173 SetRenderereCommandForCaretTest(
3174 false, true, 4, 0, kCursorOffsetY, hwnd, &command);
3175 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3176 command.application_info().composition_font(), &logfont));
3177 logfont.lfOrientation = 0;
3178 // Assume underline is enabled in the application.
3179 logfont.lfUnderline = 1;
3180
3181 layouts.clear();
3182 candidate_layout.Clear();
3183 result = layout_mgr.LayoutCompositionWindow(
3184 command, &layouts, &candidate_layout);
3185 EXPECT_TRUE(result);
3186
3187 // Underline should be stripped.
3188 ASSERT_EQ(2, layouts.size());
3189 EXPECT_EQ(0, layouts[0].log_font.lfUnderline);
3190 EXPECT_EQ(0, layouts[1].log_font.lfUnderline);
3191 }
3192
3193 // Some applications such as MIEFS use CompositionForm::RECT as a bit flag.
3194 // We should consider the case where two or more style bits are specified
3195 // at the same time.
TEST_F(Win32RendererUtilTest,CompositionFormRECTAsBitFlag_Issue3200425)3196 TEST_F(Win32RendererUtilTest, CompositionFormRECTAsBitFlag_Issue3200425) {
3197 const uint32 kStyleBit = CompositionForm::RECT | CompositionForm::POINT;
3198
3199 const int kCursorOffsetX = 0;
3200
3201 RendererCommand command;
3202
3203 HWND hwnd = nullptr;
3204 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
3205 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
3206 std::vector<CompositionWindowLayout> layouts;
3207 CandidateWindowLayout candidate_layout;
3208
3209 CLogFont logfont;
3210
3211 bool result = false;
3212
3213 // w/ candidates, monospaced, horizontal
3214 SetRenderereCommandForTest(
3215 false, true, false, kCursorOffsetX, hwnd, &command);
3216 command.mutable_application_info()->mutable_composition_form()
3217 ->set_style_bits(kStyleBit);
3218
3219 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3220 command.application_info().composition_font(), &logfont));
3221 layouts.clear();
3222 candidate_layout.Clear();
3223 result = layout_mgr.LayoutCompositionWindow(
3224 command, &layouts, &candidate_layout);
3225 EXPECT_TRUE(result);
3226
3227 ASSERT_EQ(2, layouts.size());
3228
3229 // The first line
3230 {
3231 const CompositionWindowLayout &layout = layouts.at(0);
3232 EXPECT_COMPOSITION_WINDOW_LAYOUT(1868, 599, 2003, 648, 0, 0, 135, 49,
3233 0, 0, 0, 0, 0, 0, logfont, layout);
3234 {
3235 const char kMsg[] = "これは";
3236 std::wstring msg;
3237 mozc::Util::UTF8ToWide(kMsg, &msg);
3238 EXPECT_EQ(msg, layout.text);
3239 }
3240 ASSERT_EQ(1, layout.marker_layouts.size());
3241
3242 EXPECT_EQ(CPoint(0, 48), layout.marker_layouts[0].from);
3243 EXPECT_EQ(CPoint(126, 48), layout.marker_layouts[0].to);
3244 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3245 }
3246
3247 // The second line
3248 {
3249 const CompositionWindowLayout &layout = layouts.at(1);
3250 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 648, 1840, 697, 0, 0, 646, 49,
3251 0, 0, 646, 0, 647, 49, logfont, layout);
3252 {
3253 const char kMsg[] = "、Google日本語入力のTestです";
3254 std::wstring msg;
3255 mozc::Util::UTF8ToWide(kMsg, &msg);
3256 EXPECT_EQ(msg, layout.text);
3257 }
3258 ASSERT_EQ(4, layout.marker_layouts.size());
3259
3260 EXPECT_EQ(CPoint(0, 48), layout.marker_layouts[0].from);
3261 EXPECT_EQ(CPoint(36, 48), layout.marker_layouts[0].to);
3262 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3263 EXPECT_EQ(CPoint(45, 48), layout.marker_layouts[1].from);
3264 EXPECT_EQ(CPoint(190, 48), layout.marker_layouts[1].to);
3265 EXPECT_TRUE(layout.marker_layouts[1].highlighted);
3266 EXPECT_EQ(CPoint(196, 48), layout.marker_layouts[2].from);
3267 EXPECT_EQ(CPoint(457, 48), layout.marker_layouts[2].to);
3268 EXPECT_FALSE(layout.marker_layouts[2].highlighted);
3269 EXPECT_EQ(CPoint(466, 48), layout.marker_layouts[3].from);
3270 EXPECT_EQ(CPoint(646, 48), layout.marker_layouts[3].to);
3271 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
3272 }
3273 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3274 1238, 697, 1238, 648, 1839, 697, candidate_layout);
3275
3276 // Check other candidate positions.
3277 command.mutable_output()->mutable_candidates()->set_position(0);
3278 layouts.clear();
3279 candidate_layout.Clear();
3280 result = layout_mgr.LayoutCompositionWindow(
3281 command, &layouts, &candidate_layout);
3282 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3283 1868, 648, 1868, 599, 2003, 648, candidate_layout);
3284
3285 command.mutable_output()->mutable_candidates()->set_position(3);
3286 layouts.clear();
3287 candidate_layout.Clear();
3288 result = layout_mgr.LayoutCompositionWindow(
3289 command, &layouts, &candidate_layout);
3290 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3291 1193, 697, 1193, 648, 1839, 697, candidate_layout);
3292
3293 command.mutable_output()->mutable_candidates()->set_position(10);
3294 layouts.clear();
3295 candidate_layout.Clear();
3296 result = layout_mgr.LayoutCompositionWindow(
3297 command, &layouts, &candidate_layout);
3298 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3299 1389, 697, 1389, 648, 1839, 697, candidate_layout);
3300
3301 command.mutable_output()->mutable_candidates()->set_position(16);
3302 layouts.clear();
3303 candidate_layout.Clear();
3304 result = layout_mgr.LayoutCompositionWindow(
3305 command, &layouts, &candidate_layout);
3306 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3307 1659, 697, 1659, 648, 1839, 697, candidate_layout);
3308
3309 // w/o candidates, monospaced, horizontal
3310 SetRenderereCommandForTest(false, false, false, 0, hwnd, &command);
3311 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3312 command.application_info().composition_font(), &logfont));
3313 layouts.clear();
3314 candidate_layout.Clear();
3315 result = layout_mgr.LayoutCompositionWindow(
3316 command, &layouts, &candidate_layout);
3317 EXPECT_TRUE(result);
3318 EXPECT_FALSE(candidate_layout.initialized());
3319 }
3320
3321 // Evernote Windows Client 4.0.0.2880 (107102) / Editor component
TEST_F(Win32RendererUtilTest,EvernoteEditorComposition)3322 TEST_F(Win32RendererUtilTest, EvernoteEditorComposition) {
3323 const wchar_t kClassName[] = L"WebViewHost";
3324 const UINT kClassStyle = CS_DBLCLKS;
3325 const DWORD kWindowStyle =
3326 WS_CHILDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
3327 static_assert(kWindowStyle == 0x56000000, "Check actual value");
3328 const DWORD kWindowExStyle =
3329 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
3330 static_assert(kWindowExStyle == 0, "Check actual value");
3331
3332 const CRect kWindowRect(1548, 879, 1786, 1416);
3333 const CPoint kClientOffset(0, 0);
3334 const CSize kClientSize(238, 537);
3335 const double kScaleFactor = 1.0;
3336
3337 HWND hwnd = nullptr;
3338 LayoutManager layout_mgr(
3339 CreateDefaultGUIFontEmulator(),
3340 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
3341 kScaleFactor, &hwnd));
3342
3343 RendererCommand command;
3344 SetRenderereCommandForTest(
3345 false, true, false, 0, hwnd, &command);
3346
3347 // Clear the default ApplicationInfo and update it for Evernote.
3348 command.clear_application_info();
3349 AppInfoUtil::SetBasicApplicationInfo(
3350 command.mutable_application_info(), hwnd,
3351 (ApplicationInfo::ShowCandidateWindow |
3352 ApplicationInfo::ShowSuggestWindow |
3353 ApplicationInfo::ShowCompositionWindow));
3354
3355 AppInfoUtil::SetCaretInfo(
3356 command.mutable_application_info(), false, 0, 0, 0, 0, hwnd);
3357
3358 CandidateWindowLayout candidate_layout;
3359 std::vector<CompositionWindowLayout> layouts;
3360 bool result = false;
3361
3362 layouts.clear();
3363 candidate_layout.Clear();
3364 result = layout_mgr.LayoutCompositionWindow(
3365 command, &layouts, &candidate_layout);
3366 EXPECT_TRUE(result);
3367
3368 // Default GUI font should be selected.
3369 CLogFont default_font = GetFont(true, false);
3370 default_font.lfHeight = 18;
3371 default_font.lfWidth = 0;
3372
3373 ASSERT_EQ(2, layouts.size());
3374
3375 // The first line
3376 {
3377 const CompositionWindowLayout &layout = layouts.at(0);
3378 EXPECT_COMPOSITION_WINDOW_LAYOUT(1548, 1416, 1777, 1434, 0, 0, 229, 18,
3379 0, 0, 0, 0, 0, 0, default_font, layout);
3380 {
3381 const char kMsg[] = "これは、Google日本語入力のTest";
3382 std::wstring msg;
3383 mozc::Util::UTF8ToWide(kMsg, &msg);
3384 EXPECT_EQ(msg, layout.text);
3385 }
3386 ASSERT_EQ(5, layout.marker_layouts.size());
3387
3388 EXPECT_EQ(CPoint(0, 17), layout.marker_layouts[0].from);
3389 EXPECT_EQ(CPoint(42, 17), layout.marker_layouts[0].to);
3390 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3391 EXPECT_EQ(CPoint(45, 17), layout.marker_layouts[1].from);
3392 EXPECT_EQ(CPoint(57, 17), layout.marker_layouts[1].to);
3393 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
3394 EXPECT_EQ(CPoint(60, 17), layout.marker_layouts[2].from);
3395 EXPECT_EQ(CPoint(108, 17), layout.marker_layouts[2].to);
3396 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
3397 EXPECT_EQ(CPoint(110, 17), layout.marker_layouts[3].from);
3398 EXPECT_EQ(CPoint(197, 17), layout.marker_layouts[3].to);
3399 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
3400 EXPECT_EQ(CPoint(200, 17), layout.marker_layouts[4].from);
3401 EXPECT_EQ(CPoint(229, 17), layout.marker_layouts[4].to);
3402 EXPECT_FALSE(layout.marker_layouts[4].highlighted);
3403 }
3404
3405 // The second line
3406 {
3407 const CompositionWindowLayout &layout = layouts.at(1);
3408 EXPECT_COMPOSITION_WINDOW_LAYOUT(1548, 1434, 1579, 1452, 0, 0, 30, 18,
3409 0, 0, 30, 0, 31, 18, default_font, layout);
3410 {
3411 const char kMsg[] = "です";
3412 std::wstring msg;
3413 mozc::Util::UTF8ToWide(kMsg, &msg);
3414 EXPECT_EQ(msg, layout.text);
3415 }
3416 ASSERT_EQ(1, layout.marker_layouts.size());
3417
3418 EXPECT_EQ(CPoint(0, 17), layout.marker_layouts[0].from);
3419 EXPECT_EQ(CPoint(30, 17), layout.marker_layouts[0].to);
3420 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3421 }
3422
3423 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3424 1608, 1434, 1608, 1416, 1777, 1434, candidate_layout);
3425 }
3426
3427 // Crescent Eve 0.82a / Apr 24 2010.
3428 // Crescent Eve sets larger composition form area than its client area.
3429 // DPI virtualization API may fail in this case. See b/3239031.
TEST_F(Win32RendererUtilTest,CrescentEveComposition_Issue3239031)3430 TEST_F(Win32RendererUtilTest, CrescentEveComposition_Issue3239031) {
3431 const wchar_t kClassName[] = L"CrescentEditer";
3432 const UINT kClassStyle = CS_DBLCLKS | CS_BYTEALIGNCLIENT;
3433 static_assert(kClassStyle == 0x00001008, "Check actual value");
3434 const DWORD kWindowStyle = WS_CHILDWINDOW | WS_VISIBLE | WS_VSCROLL;
3435 static_assert(kWindowStyle == 0x50200000, "Check actual value");
3436 const DWORD kWindowExStyle =
3437 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR |
3438 WS_EX_ACCEPTFILES | WS_EX_CLIENTEDGE;
3439 static_assert(kWindowExStyle == 0x00000210, "Check actual value");
3440
3441 const CRect kWindowRect(184, 192, 1312, 1426);
3442 const CPoint kClientOffset(2, 2);
3443 const CSize kClientSize(1107, 1230);
3444 const double kScaleFactor = 1.0;
3445
3446 HWND hwnd = nullptr;
3447 LayoutManager layout_mgr(
3448 CreateDefaultGUIFontEmulator(),
3449 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
3450 kScaleFactor, &hwnd));
3451
3452 RendererCommand command;
3453 SetRenderereCommandForTest(
3454 false, true, false, 0, hwnd, &command);
3455
3456 // Replace the default values with those of Crescent Eve.
3457 command.clear_application_info();
3458 AppInfoUtil::SetBasicApplicationInfo(
3459 command.mutable_application_info(), hwnd,
3460 (ApplicationInfo::ShowCandidateWindow |
3461 ApplicationInfo::ShowSuggestWindow |
3462 ApplicationInfo::ShowCompositionWindow));
3463
3464 AppInfoUtil::SetCompositionForm(
3465 command.mutable_application_info(),
3466 CompositionForm::POINT | CompositionForm::RECT,
3467 35, 0, 35, 0, 1106, 1624);
3468
3469 AppInfoUtil::SetCaretInfo(
3470 command.mutable_application_info(),
3471 false, 34, 0, 36, 14, hwnd);
3472
3473 CandidateWindowLayout candidate_layout;
3474 std::vector<CompositionWindowLayout> layouts;
3475 bool result = false;
3476
3477 layouts.clear();
3478 candidate_layout.Clear();
3479 result = layout_mgr.LayoutCompositionWindow(
3480 command, &layouts, &candidate_layout);
3481 EXPECT_TRUE(result);
3482
3483 // Default GUI font should be selected.
3484 CLogFont default_font = GetFont(true, false);
3485 default_font.lfHeight = 18;
3486 default_font.lfWidth = 0;
3487
3488 ASSERT_EQ(1, layouts.size());
3489
3490 // The first line
3491 {
3492 const CompositionWindowLayout &layout = layouts.at(0);
3493 EXPECT_COMPOSITION_WINDOW_LAYOUT(221, 194, 481, 212, 0, 0, 259, 18, 0, 0,
3494 259, 0, 260, 18, default_font, layout);
3495 {
3496 const char kMsg[] = "これは、Google日本語入力のTestです";
3497 std::wstring msg;
3498 mozc::Util::UTF8ToWide(kMsg, &msg);
3499 EXPECT_EQ(msg, layout.text);
3500 }
3501 ASSERT_EQ(5, layout.marker_layouts.size());
3502
3503 EXPECT_EQ(CPoint(0, 17), layout.marker_layouts[0].from);
3504 EXPECT_EQ(CPoint(42, 17), layout.marker_layouts[0].to);
3505 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3506 EXPECT_EQ(CPoint(45, 17), layout.marker_layouts[1].from);
3507 EXPECT_EQ(CPoint(57, 17), layout.marker_layouts[1].to);
3508 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
3509 EXPECT_EQ(CPoint(60, 17), layout.marker_layouts[2].from);
3510 EXPECT_EQ(CPoint(108, 17), layout.marker_layouts[2].to);
3511 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
3512 EXPECT_EQ(CPoint(110, 17), layout.marker_layouts[3].from);
3513 EXPECT_EQ(CPoint(197, 17), layout.marker_layouts[3].to);
3514 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
3515 EXPECT_EQ(CPoint(200, 17), layout.marker_layouts[4].from);
3516 EXPECT_EQ(CPoint(259, 17), layout.marker_layouts[4].to);
3517 EXPECT_FALSE(layout.marker_layouts[4].highlighted);
3518 }
3519
3520 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3521 281, 212, 281, 194, 480, 212, candidate_layout);
3522 }
3523
3524 // MSInfo32.exe 6.1.7600 on Windows 7. (b/3433099)
3525 // The composition window and candidate window must be shown even when the
3526 // client sets Composition/CandidateForm outside of the top-level window.
3527 // Note that LogicalToPhysicalPoint API may return FALSE in this situation.
TEST_F(Win32RendererUtilTest,MSInfo32Composition_Issue3433099)3528 TEST_F(Win32RendererUtilTest, MSInfo32Composition_Issue3433099) {
3529 const double kScaleFactor = 1.0;
3530
3531 WindowPositionEmulator *window_emulator = nullptr;
3532 HWND root_window = nullptr;
3533 HWND child_window = nullptr;
3534
3535 {
3536 const wchar_t kRootClassName[] = L"#32770 (Dialog)";
3537 const UINT kRootClassStyle = CS_DBLCLKS | CS_SAVEBITS;
3538 const DWORD kRootWindowStyle = 0x96CF0044;
3539 const DWORD kRootWindowExStyle = 0x00010100;
3540 const CRect kRootWindowRect(838, 651, 1062, 1157);
3541 const CPoint kRootClientOffset(8, 71);
3542 const CSize kRootClientSize(208, 427);
3543 window_emulator = CreateWindowEmulator(
3544 kRootClassName, kRootWindowRect, kRootClientOffset, kRootClientSize,
3545 kScaleFactor, &root_window);
3546 }
3547 {
3548 const wchar_t kChildClassName[] = L"Edit";
3549 const UINT kChildClassStyle = CS_DBLCLKS | CS_PARENTDC | CS_GLOBALCLASS;
3550 const DWORD kChildWindowStyle = 0x50010080;
3551 const DWORD kChildWindowExStyle = 0x00000204;
3552 const CRect kChildWindowRect(951, 1071, 1072, 1098);
3553 const CPoint kChildClientOffset(2, 2);
3554 const CSize kChildClientSize(117, 23);
3555 child_window = window_emulator->RegisterWindow(
3556 kChildClassName, kChildWindowRect, kChildClientOffset,
3557 kChildClientSize, kScaleFactor);
3558
3559 window_emulator->SetRoot(child_window, root_window);
3560 }
3561
3562 LayoutManager layout_mgr(
3563 CreateDefaultGUIFontEmulator(),
3564 window_emulator);
3565
3566 ApplicationInfo app_info;
3567
3568 RendererCommand command;
3569 SetRenderereCommandForTest(
3570 false, true, false, 0, child_window, &command);
3571
3572 // Replace the default values with those of MSInfo32.
3573 command.clear_application_info();
3574 AppInfoUtil::SetBasicApplicationInfo(
3575 command.mutable_application_info(), child_window,
3576 (ApplicationInfo::ShowCandidateWindow |
3577 ApplicationInfo::ShowSuggestWindow |
3578 ApplicationInfo::ShowCompositionWindow));
3579
3580 AppInfoUtil::SetCompositionForm(
3581 command.mutable_application_info(),
3582 CompositionForm::POINT, 2, 1, 0, 0, 0, 0);
3583
3584 AppInfoUtil::SetCaretInfo(
3585 command.mutable_application_info(),
3586 true, 2, 1, 3, 19, child_window);
3587
3588 CandidateWindowLayout candidate_layout;
3589 std::vector<CompositionWindowLayout> layouts;
3590 bool result = false;
3591
3592 layouts.clear();
3593 candidate_layout.Clear();
3594 result = layout_mgr.LayoutCompositionWindow(
3595 command, &layouts, &candidate_layout);
3596 EXPECT_TRUE(result);
3597
3598 // Default GUI font should be selected.
3599 CLogFont default_font = GetFont(true, false);
3600 default_font.lfHeight = 18;
3601 default_font.lfWidth = 0;
3602
3603 ASSERT_EQ(3, layouts.size());
3604
3605 // The first line
3606 {
3607 const CompositionWindowLayout &layout = layouts.at(0);
3608 EXPECT_COMPOSITION_WINDOW_LAYOUT(955, 1074, 1065, 1092, 0, 0, 110, 18, 0, 0,
3609 0, 0, 0, 0, default_font, layout);
3610 {
3611 const char kMsg[] = "これは、Google";
3612 std::wstring msg;
3613 mozc::Util::UTF8ToWide(kMsg, &msg);
3614 EXPECT_EQ(msg, layout.text);
3615 }
3616 ASSERT_EQ(3, layout.marker_layouts.size());
3617
3618 EXPECT_EQ(CPoint(0, 17), layout.marker_layouts[0].from);
3619 EXPECT_EQ(CPoint(42, 17), layout.marker_layouts[0].to);
3620 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3621 EXPECT_EQ(CPoint(45, 17), layout.marker_layouts[1].from);
3622 EXPECT_EQ(CPoint(57, 17), layout.marker_layouts[1].to);
3623 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
3624 EXPECT_EQ(CPoint(60, 17), layout.marker_layouts[2].from);
3625 EXPECT_EQ(CPoint(108, 17), layout.marker_layouts[2].to);
3626 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
3627 }
3628
3629 // The second line
3630 {
3631 const CompositionWindowLayout &layout = layouts.at(1);
3632 EXPECT_COMPOSITION_WINDOW_LAYOUT(953, 1092, 1067, 1110, 0, 0, 114, 18, 0, 0,
3633 0, 0, 0, 0, default_font, layout);
3634 {
3635 const char kMsg[] = "日本語入力のTes";
3636 std::wstring msg;
3637 mozc::Util::UTF8ToWide(kMsg, &msg);
3638 EXPECT_EQ(msg, layout.text);
3639 }
3640 ASSERT_EQ(2, layout.marker_layouts.size());
3641
3642 EXPECT_EQ(CPoint(0, 17), layout.marker_layouts[0].from);
3643 EXPECT_EQ(CPoint(87, 17), layout.marker_layouts[0].to);
3644 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3645 EXPECT_EQ(CPoint(90, 17), layout.marker_layouts[1].from);
3646 EXPECT_EQ(CPoint(114, 17), layout.marker_layouts[1].to);
3647 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
3648 }
3649
3650 // The third line
3651 {
3652 const CompositionWindowLayout &layout = layouts.at(2);
3653 EXPECT_COMPOSITION_WINDOW_LAYOUT(953, 1110, 989, 1128, 0, 0, 35, 18, 0, 0,
3654 35, 0, 36, 18, default_font, layout);
3655 {
3656 const char kMsg[] = "tです";
3657 std::wstring msg;
3658 mozc::Util::UTF8ToWide(kMsg, &msg);
3659 EXPECT_EQ(msg, layout.text);
3660 }
3661 ASSERT_EQ(1, layout.marker_layouts.size());
3662
3663 EXPECT_EQ(CPoint(0, 17), layout.marker_layouts[0].from);
3664 EXPECT_EQ(CPoint(35, 17), layout.marker_layouts[0].to);
3665 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3666 }
3667
3668 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3669 1015, 1092, 1015, 1074, 1065, 1092, candidate_layout);
3670 }
3671
3672 // Check if LayoutManager can handle preedits which contains surrogate pair.
3673 // See b/4159275 for details.
TEST_F(Win32RendererUtilTest,CheckSurrogatePairInHorizontalComposition_Issue4159275)3674 TEST_F(Win32RendererUtilTest,
3675 CheckSurrogatePairInHorizontalComposition_Issue4159275) {
3676 const int kCursorOffsetX = 150;
3677
3678 HWND hwnd = nullptr;
3679 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
3680 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
3681
3682 RendererCommand command;
3683 SetRenderereCommandForSurrogatePair(
3684 false, false, kCursorOffsetX, hwnd, &command);
3685
3686 CLogFont logfont;
3687 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3688 command.application_info().composition_font(), &logfont));
3689
3690 std::vector<CompositionWindowLayout> layouts;
3691 CandidateWindowLayout candidate_layout;
3692 EXPECT_TRUE(layout_mgr.LayoutCompositionWindow(
3693 command, &layouts, &candidate_layout));
3694
3695 ASSERT_EQ(1, layouts.size());
3696
3697 // The first line
3698 {
3699 const CompositionWindowLayout &layout = layouts.at(0);
3700 EXPECT_COMPOSITION_WINDOW_LAYOUT(1193, 648, 1554, 697, 0, 0, 360, 49,
3701 0, 0, 360, 0, 361, 49, logfont,
3702 layout);
3703 {
3704 const char kMsg[] = "咤咤咤咤";
3705 std::wstring msg;
3706 mozc::Util::UTF8ToWide(kMsg, &msg);
3707 EXPECT_EQ(msg, layout.text);
3708 }
3709 ASSERT_EQ(4, layout.marker_layouts.size());
3710
3711 EXPECT_EQ(CPoint(0, 48), layout.marker_layouts[0].from);
3712 EXPECT_EQ(CPoint(81, 48), layout.marker_layouts[0].to);
3713 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3714 EXPECT_EQ(CPoint(90, 48), layout.marker_layouts[1].from);
3715 EXPECT_EQ(CPoint(171, 48), layout.marker_layouts[1].to);
3716 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
3717 EXPECT_EQ(CPoint(180, 48), layout.marker_layouts[2].from);
3718 EXPECT_EQ(CPoint(261, 48), layout.marker_layouts[2].to);
3719 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
3720 EXPECT_EQ(CPoint(270, 48), layout.marker_layouts[3].from);
3721 EXPECT_EQ(CPoint(360, 48), layout.marker_layouts[3].to);
3722 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
3723 }
3724
3725 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3726 1373, 697, 1373, 648, 1553, 697, candidate_layout);
3727 }
3728
3729 // Check if LayoutManager can handle preedits which contains surrogate pair.
3730 // See b/4159275 for details.
TEST_F(Win32RendererUtilTest,CheckSurrogatePairInVerticalComposition_Issue4159275)3731 TEST_F(Win32RendererUtilTest,
3732 CheckSurrogatePairInVerticalComposition_Issue4159275) {
3733 const int kCursorOffsetY = 175;
3734
3735 HWND hwnd = nullptr;
3736 LayoutManager layout_mgr(CreateDefaultGUIFontEmulator(),
3737 CreateWindowEmulatorWithDPIScaling(1.0, &hwnd));
3738
3739 RendererCommand command;
3740 SetRenderereCommandForSurrogatePair(
3741 false, true, kCursorOffsetY, hwnd, &command);
3742
3743 CLogFont logfont;
3744 EXPECT_TRUE(mozc::win32::FontUtil::ToLOGFONT(
3745 command.application_info().composition_font(), &logfont));
3746 logfont.lfOrientation = 2700;
3747
3748 std::vector<CompositionWindowLayout> layouts;
3749 CandidateWindowLayout candidate_layout;
3750 EXPECT_TRUE(layout_mgr.LayoutCompositionWindow(
3751 command, &layouts, &candidate_layout));
3752
3753 ASSERT_EQ(1, layouts.size());
3754
3755 // The first line
3756 {
3757 const CompositionWindowLayout &layout = layouts.at(0);
3758 EXPECT_COMPOSITION_WINDOW_LAYOUT(
3759 1932, 712, 1983, 1073, 0, 0, 51, 360, 51, 0,
3760 0, 360, 51, 361, logfont, layout);
3761 {
3762 const char kMsg[] = "咤咤咤咤";
3763 std::wstring msg;
3764 mozc::Util::UTF8ToWide(kMsg, &msg);
3765 EXPECT_EQ(msg, layout.text);
3766 }
3767 ASSERT_EQ(4, layout.marker_layouts.size());
3768
3769 EXPECT_EQ(CPoint(50, 0), layout.marker_layouts[0].from);
3770 EXPECT_EQ(CPoint(50, 81), layout.marker_layouts[0].to);
3771 EXPECT_FALSE(layout.marker_layouts[0].highlighted);
3772 EXPECT_EQ(CPoint(50, 90), layout.marker_layouts[1].from);
3773 EXPECT_EQ(CPoint(50, 171), layout.marker_layouts[1].to);
3774 EXPECT_FALSE(layout.marker_layouts[1].highlighted);
3775 EXPECT_EQ(CPoint(50, 180), layout.marker_layouts[2].from);
3776 EXPECT_EQ(CPoint(50, 261), layout.marker_layouts[2].to);
3777 EXPECT_TRUE(layout.marker_layouts[2].highlighted);
3778 EXPECT_EQ(CPoint(50, 270), layout.marker_layouts[3].from);
3779 EXPECT_EQ(CPoint(50, 360), layout.marker_layouts[3].to);
3780 EXPECT_FALSE(layout.marker_layouts[3].highlighted);
3781 }
3782
3783 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3784 1932, 892, 1932, 892, 1983, 1072, candidate_layout);
3785 }
3786
TEST_F(Win32RendererUtilTest,GetWritingDirectionTest)3787 TEST_F(Win32RendererUtilTest, GetWritingDirectionTest) {
3788 RendererCommand command;
3789
3790 // Horizontal
3791 SetRenderereCommandForTest(
3792 false, true, false, 0, nullptr, &command);
3793 EXPECT_EQ(LayoutManager::HORIZONTAL_WRITING,
3794 LayoutManager::GetWritingDirection(command.application_info()));
3795
3796 // Vertical
3797 SetRenderereCommandForTest(
3798 false, true, true, 0, nullptr, &command);
3799 EXPECT_EQ(LayoutManager::VERTICAL_WRITING,
3800 LayoutManager::GetWritingDirection(command.application_info()));
3801
3802 // Unspecified
3803 command.mutable_application_info()->
3804 mutable_composition_font()->clear_escapement();
3805 EXPECT_EQ(LayoutManager::WRITING_DIRECTION_UNSPECIFIED,
3806 LayoutManager::GetWritingDirection(command.application_info()));
3807
3808 // Unspecified
3809 command.mutable_application_info()->clear_composition_font();
3810 EXPECT_EQ(LayoutManager::WRITING_DIRECTION_UNSPECIFIED,
3811 LayoutManager::GetWritingDirection(command.application_info()));
3812 }
3813
3814 // Hidemaru 8.01a True-Inline
TEST_F(Win32RendererUtilTest,Hidemaru_Horizontal_Suggest)3815 TEST_F(Win32RendererUtilTest, Hidemaru_Horizontal_Suggest) {
3816 const wchar_t kClassName[] = L"HM32CLIENT";
3817 const CRect kWindowRect(0, 20, 2016, 1050);
3818 const CPoint kClientOffset(8, 42);
3819 const CSize kClientSize(2000, 1000);
3820 const double kScaleFactor = 1.0;
3821
3822 HWND hwnd = nullptr;
3823 LayoutManager layout_mgr(
3824 CreateDefaultGUIFontEmulator(),
3825 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
3826 kScaleFactor, &hwnd));
3827
3828 ApplicationInfo app_info;
3829 AppInfoUtil::SetBasicApplicationInfo(
3830 &app_info, hwnd, ApplicationInfo::ShowSuggestWindow);
3831
3832 AppInfoUtil::SetCompositionFont(
3833 &app_info, -15, 0, 0, 0, FW_NORMAL, SHIFTJIS_CHARSET,
3834 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
3835 DEFAULT_QUALITY, FF_MODERN | FIXED_PITCH,
3836 "MS ゴシック");
3837
3838 AppInfoUtil::SetCompositionForm(
3839 &app_info, CompositionForm::RECT, 112, 25, 48, 0, 1408, 552);
3840
3841 AppInfoUtil::SetCandidateForm(
3842 &app_info, CandidateForm::EXCLUDE, 112, 42, 112, 25, 752, 42);
3843
3844 AppInfoUtil::SetCaretInfo(&app_info, true, 160, 25, 162, 40, hwnd);
3845
3846 CandidateWindowLayout layout;
3847 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
3848 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3849 168, 102, 168, 87, 170, 102, layout);
3850 }
3851
3852 // Hidemaru 8.01a True-Inline
TEST_F(Win32RendererUtilTest,Hidemaru_Horizontal_Convert)3853 TEST_F(Win32RendererUtilTest, Hidemaru_Horizontal_Convert) {
3854 const wchar_t kClassName[] = L"HM32CLIENT";
3855 const CRect kWindowRect(0, 20, 2016, 1050);
3856 const CPoint kClientOffset(8, 42);
3857 const CSize kClientSize(2000, 1000);
3858 const double kScaleFactor = 1.0;
3859
3860 HWND hwnd = nullptr;
3861 LayoutManager layout_mgr(
3862 CreateDefaultGUIFontEmulator(),
3863 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
3864 kScaleFactor, &hwnd));
3865
3866 ApplicationInfo app_info;
3867
3868 AppInfoUtil::SetBasicApplicationInfo(
3869 &app_info, hwnd, ApplicationInfo::ShowCandidateWindow);
3870
3871 AppInfoUtil::SetCompositionFont(
3872 &app_info, -15, 0, 0, 0, FW_NORMAL, SHIFTJIS_CHARSET,
3873 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
3874 DEFAULT_QUALITY, FF_MODERN | FIXED_PITCH,
3875 "MS ゴシック");
3876
3877 AppInfoUtil::SetCompositionForm(
3878 &app_info, CompositionForm::RECT, 112, 25, 48, 0, 1408, 552);
3879
3880 AppInfoUtil::SetCandidateForm(
3881 &app_info, CandidateForm::EXCLUDE, 128, 25, 128, 25, 144, 42);
3882
3883 AppInfoUtil::SetCaretInfo(&app_info, true, 160, 25, 162, 40, hwnd);
3884
3885 CandidateWindowLayout layout;
3886 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
3887 app_info, &layout));
3888 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3889 136, 87, 136, 87, 152, 104, layout);
3890 }
3891
3892 // Hidemaru 8.01a True-Inline
TEST_F(Win32RendererUtilTest,Hidemaru_Vertical_Suggest)3893 TEST_F(Win32RendererUtilTest, Hidemaru_Vertical_Suggest) {
3894 const wchar_t kClassName[] = L"HM32CLIENT";
3895 const CRect kWindowRect(0, 20, 2016, 1050);
3896 const CPoint kClientOffset(8, 42);
3897 const CSize kClientSize(2000, 1000);
3898 const double kScaleFactor = 1.0;
3899
3900 HWND hwnd = nullptr;
3901 LayoutManager layout_mgr(
3902 CreateDefaultGUIFontEmulator(),
3903 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
3904 kScaleFactor, &hwnd));
3905
3906 ApplicationInfo app_info;
3907
3908 AppInfoUtil::SetBasicApplicationInfo(
3909 &app_info, hwnd, ApplicationInfo::ShowSuggestWindow);
3910
3911 AppInfoUtil::SetCompositionFont(
3912 &app_info, -15, 0, 2700, 0, FW_NORMAL, SHIFTJIS_CHARSET,
3913 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
3914 DEFAULT_QUALITY, FF_MODERN | FIXED_PITCH,
3915 "@MS ゴシック");
3916
3917 AppInfoUtil::SetCompositionForm(
3918 &app_info, CompositionForm::RECT, 660, 48, 0, 48, 688, 397);
3919
3920 AppInfoUtil::SetCandidateForm(
3921 &app_info, CandidateForm::EXCLUDE, 660, 67, 641, 48, 660, 400);
3922
3923 AppInfoUtil::SetCaretInfo(&app_info, true, 644, 96, 661, 98, hwnd);
3924
3925 CandidateWindowLayout layout;
3926 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
3927 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3928 652, 158, 652, 158, 669, 160, layout);
3929 }
3930
3931 // Hidemaru 8.01a True-Inline
TEST_F(Win32RendererUtilTest,Hidemaru_Vertical_Convert)3932 TEST_F(Win32RendererUtilTest, Hidemaru_Vertical_Convert) {
3933 const wchar_t kClassName[] = L"HM32CLIENT";
3934 const CRect kWindowRect(0, 20, 2016, 1050);
3935 const CPoint kClientOffset(8, 42);
3936 const CSize kClientSize(2000, 1000);
3937 const double kScaleFactor = 1.0;
3938
3939 HWND hwnd = nullptr;
3940 LayoutManager layout_mgr(
3941 CreateDefaultGUIFontEmulator(),
3942 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
3943 kScaleFactor, &hwnd));
3944
3945 ApplicationInfo app_info;
3946
3947 AppInfoUtil::SetBasicApplicationInfo(
3948 &app_info, hwnd,
3949 ApplicationInfo::ShowCandidateWindow |
3950 ApplicationInfo::ShowSuggestWindow);
3951
3952 AppInfoUtil::SetCompositionFont(
3953 &app_info, -15, 0, 2700, 0, FW_NORMAL, SHIFTJIS_CHARSET,
3954 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
3955 DEFAULT_QUALITY, FF_MODERN | FIXED_PITCH,
3956 "@MS ゴシック");
3957
3958 AppInfoUtil::SetCompositionForm(
3959 &app_info, CompositionForm::RECT, 660, 48, 0, 48, 668, 397);
3960
3961 AppInfoUtil::SetCandidateForm(
3962 &app_info, CandidateForm::EXCLUDE, 644, 63, 644, 63, 661, 80);
3963
3964 AppInfoUtil::SetCaretInfo(&app_info, true, 644, 96, 661, 98, hwnd);
3965
3966 CandidateWindowLayout layout;
3967 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
3968 app_info, &layout));
3969 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
3970 652, 125, 652, 125, 669, 142, layout);
3971 }
3972
3973 // Open Office Writer 3.01
TEST_F(Win32RendererUtilTest,OOo_Suggest)3974 TEST_F(Win32RendererUtilTest, OOo_Suggest) {
3975 const wchar_t kClassName[] = L"SALFRAME";
3976 const CRect kWindowRect(0, 20, 2016, 1050);
3977 const CPoint kClientOffset(8, 42);
3978 const CSize kClientSize(2000, 1000);
3979 const double kScaleFactor = 1.0;
3980
3981 HWND hwnd = nullptr;
3982 LayoutManager layout_mgr(
3983 CreateDefaultGUIFontEmulator(),
3984 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
3985 kScaleFactor, &hwnd));
3986
3987 ApplicationInfo app_info;
3988
3989 AppInfoUtil::SetBasicApplicationInfo(
3990 &app_info, hwnd,
3991 ApplicationInfo::ShowSuggestWindow);
3992
3993 AppInfoUtil::SetCompositionFont(
3994 &app_info, -16, 0, 0, 0, FW_DONTCARE, ANSI_CHARSET,
3995 OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
3996 DEFAULT_QUALITY, 23,
3997 "Times New Roman");
3998
3999 AppInfoUtil::SetCompositionForm(
4000 &app_info, CompositionForm::POINT, 292, 253, 0, 0, 0, 0);
4001
4002 AppInfoUtil::SetCaretInfo(&app_info, true, 292, 253, 294, 273, hwnd);
4003
4004 CandidateWindowLayout layout;
4005 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4006 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4007 300, 335, 300, 315, 302, 335, layout);
4008 }
4009
4010 // Open Office Writer 3.01
TEST_F(Win32RendererUtilTest,OOo_Convert)4011 TEST_F(Win32RendererUtilTest, OOo_Convert) {
4012 const wchar_t kClassName[] = L"SALFRAME";
4013 const CRect kWindowRect(0, 20, 2016, 1050);
4014 const CPoint kClientOffset(8, 42);
4015 const CSize kClientSize(2000, 1000);
4016 const double kScaleFactor = 1.0;
4017
4018 HWND hwnd = nullptr;
4019 LayoutManager layout_mgr(
4020 CreateDefaultGUIFontEmulator(),
4021 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4022 kScaleFactor, &hwnd));
4023
4024 ApplicationInfo app_info;
4025
4026 AppInfoUtil::SetBasicApplicationInfo(
4027 &app_info, hwnd,
4028 ApplicationInfo::ShowCandidateWindow |
4029 ApplicationInfo::ShowSuggestWindow);
4030
4031 AppInfoUtil::SetCompositionFont(
4032 &app_info, -16, 0, 0, 0, FW_DONTCARE, ANSI_CHARSET,
4033 OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
4034 DEFAULT_QUALITY, 23,
4035 "Times New Roman");
4036
4037 AppInfoUtil::SetCompositionForm(
4038 &app_info, CompositionForm::POINT, 264, 253, 0, 0, 0, 0);
4039
4040 AppInfoUtil::SetCandidateForm(
4041 &app_info, CandidateForm::EXCLUDE, 250, 258, 250, 257, 253, 275);
4042
4043 AppInfoUtil::SetCaretInfo(&app_info, true, 264, 253, 266, 273, hwnd);
4044
4045 CandidateWindowLayout layout;
4046 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4047 app_info, &layout));
4048 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4049 258, 320, 258, 319, 261, 337, layout);
4050 }
4051
4052 // Pidgin 2.6.1
TEST_F(Win32RendererUtilTest,Pidgin_Indicator)4053 TEST_F(Win32RendererUtilTest, Pidgin_Indicator) {
4054 const wchar_t kClassName[] = L"gdkWindowToplevel";
4055 const CRect kWindowRect(0, 20, 2016, 1050);
4056 const CPoint kClientOffset(8, 42);
4057 const CSize kClientSize(2000, 1000);
4058 const double kScaleFactor = 1.0;
4059
4060 HWND hwnd = nullptr;
4061 LayoutManager layout_mgr(
4062 CreateDefaultGUIFontEmulator(),
4063 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4064 kScaleFactor, &hwnd));
4065
4066 ApplicationInfo app_info;
4067
4068 AppInfoUtil::SetBasicApplicationInfo(
4069 &app_info, hwnd,
4070 ApplicationInfo::ShowCandidateWindow |
4071 ApplicationInfo::ShowSuggestWindow);
4072
4073 AppInfoUtil::SetCompositionFont(
4074 &app_info, -16, 0, 0, 0, FW_NORMAL, SHIFTJIS_CHARSET,
4075 OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS,
4076 DRAFT_QUALITY, 50,
4077 "メイリオ");
4078
4079 AppInfoUtil::SetCompositionForm(
4080 &app_info, CompositionForm::POINT, 48, 589,
4081 96504880, 2617504, 97141432, 2617480);
4082
4083 AppInfoUtil::SetCandidateForm(
4084 &app_info, CandidateForm::CANDIDATEPOS, 32, 636,
4085 40706080, 96552944, 2615824, 1815374140);
4086
4087 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, nullptr);
4088
4089 IndicatorWindowLayout layout;
4090 EXPECT_TRUE(layout_mgr.LayoutIndicatorWindow(app_info, &layout));
4091 EXPECT_EQ(CRect(56, 651, 57, 667), layout.window_rect);
4092 EXPECT_FALSE(layout.is_vertical);
4093 }
4094
4095 // Pidgin 2.6.1
TEST_F(Win32RendererUtilTest,Pidgin_Suggest)4096 TEST_F(Win32RendererUtilTest, Pidgin_Suggest) {
4097 const wchar_t kClassName[] = L"gdkWindowToplevel";
4098 const CRect kWindowRect(0, 20, 2016, 1050);
4099 const CPoint kClientOffset(8, 42);
4100 const CSize kClientSize(2000, 1000);
4101 const double kScaleFactor = 1.0;
4102
4103 HWND hwnd = nullptr;
4104 LayoutManager layout_mgr(
4105 CreateDefaultGUIFontEmulator(),
4106 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4107 kScaleFactor, &hwnd));
4108
4109 ApplicationInfo app_info;
4110
4111 AppInfoUtil::SetBasicApplicationInfo(
4112 &app_info, hwnd,
4113 ApplicationInfo::ShowSuggestWindow);
4114
4115 AppInfoUtil::SetCompositionFont(
4116 &app_info, -16, 0, 0, 0, FW_NORMAL, SHIFTJIS_CHARSET,
4117 OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS,
4118 DRAFT_QUALITY, 50,
4119 "メイリオ");
4120
4121 AppInfoUtil::SetCompositionForm(
4122 &app_info, CompositionForm::POINT, 48, 589,
4123 96504880, 2617504, 97141432, 2617480);
4124
4125 AppInfoUtil::SetCandidateForm(
4126 &app_info, CandidateForm::CANDIDATEPOS, 48, 636,
4127 40706080, 96552944, 2615824, 1815374140);
4128
4129 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, nullptr);
4130
4131 CandidateWindowLayout layout;
4132 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4133 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4134 56, 667, 56, 651, 57, 667, layout);
4135 }
4136
4137 // Pidgin 2.6.1
TEST_F(Win32RendererUtilTest,Pidgin_Convert)4138 TEST_F(Win32RendererUtilTest, Pidgin_Convert) {
4139 const wchar_t kClassName[] = L"gdkWindowToplevel";
4140 const CRect kWindowRect(0, 20, 2016, 1050);
4141 const CPoint kClientOffset(8, 42);
4142 const CSize kClientSize(2000, 1000);
4143 const double kScaleFactor = 1.0;
4144
4145 HWND hwnd = nullptr;
4146 LayoutManager layout_mgr(
4147 CreateDefaultGUIFontEmulator(),
4148 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4149 kScaleFactor, &hwnd));
4150
4151 ApplicationInfo app_info;
4152
4153 AppInfoUtil::SetBasicApplicationInfo(
4154 &app_info, hwnd,
4155 ApplicationInfo::ShowCandidateWindow |
4156 ApplicationInfo::ShowSuggestWindow);
4157
4158 AppInfoUtil::SetCompositionFont(
4159 &app_info, -16, 0, 0, 0, FW_NORMAL, SHIFTJIS_CHARSET,
4160 OUT_STROKE_PRECIS, CLIP_STROKE_PRECIS,
4161 DRAFT_QUALITY, 50,
4162 "メイリオ");
4163
4164 AppInfoUtil::SetCompositionForm(
4165 &app_info, CompositionForm::POINT, 48, 589,
4166 96504880, 2617504, 97141432, 2617480);
4167
4168 AppInfoUtil::SetCandidateForm(
4169 &app_info, CandidateForm::CANDIDATEPOS, 32, 636,
4170 40706080, 96552944, 2615824, 1815374140);
4171
4172 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, nullptr);
4173
4174 CandidateWindowLayout layout;
4175 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4176 app_info, &layout));
4177 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4178 32, 656, 32, 640, 33, 656, layout);
4179 }
4180
4181 // V2C 2.1.6 on JRE 1.6.0.21 (32-bit)
TEST_F(Win32RendererUtilTest,V2C_Indicator)4182 TEST_F(Win32RendererUtilTest, V2C_Indicator) {
4183 const wchar_t kClassName[] = L"SunAwtFrame";
4184 const CRect kWindowRect(977, 446, 2042, 1052);
4185 const CPoint kClientOffset(8, 8);
4186 const CSize kClientSize(1049, 569);
4187 const double kScaleFactor = 1.0;
4188
4189 HWND hwnd = nullptr;
4190 LayoutManager layout_mgr(
4191 CreateDefaultGUIFontEmulator(),
4192 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4193 kScaleFactor, &hwnd));
4194
4195 ApplicationInfo app_info;
4196
4197 AppInfoUtil::SetBasicApplicationInfo(
4198 &app_info, hwnd,
4199 ApplicationInfo::ShowSuggestWindow);
4200
4201 // V2C occasionally creates zero-initialized CANDIDATEFORM and maintains
4202 // it regardless of the actual position of the composition.
4203 AppInfoUtil::SetCompositionForm(
4204 &app_info, CompositionForm::DEFAULT, 0, 0, 0, 0, 0, 0);
4205
4206 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, nullptr);
4207
4208 IndicatorWindowLayout layout;
4209 EXPECT_FALSE(layout_mgr.LayoutIndicatorWindow(app_info, &layout));
4210 }
4211
4212 // V2C 2.1.6 on JRE 1.6.0.21 (32-bit)
TEST_F(Win32RendererUtilTest,V2C_Suggest)4213 TEST_F(Win32RendererUtilTest, V2C_Suggest) {
4214 const wchar_t kClassName[] = L"SunAwtFrame";
4215 const CRect kWindowRect(977, 446, 2042, 1052);
4216 const CPoint kClientOffset(8, 8);
4217 const CSize kClientSize(1049, 569);
4218 const double kScaleFactor = 1.0;
4219
4220 HWND hwnd = nullptr;
4221 LayoutManager layout_mgr(
4222 CreateDefaultGUIFontEmulator(),
4223 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4224 kScaleFactor, &hwnd));
4225
4226 ApplicationInfo app_info;
4227
4228 AppInfoUtil::SetBasicApplicationInfo(
4229 &app_info, hwnd,
4230 ApplicationInfo::ShowSuggestWindow);
4231
4232 // V2C occasionally creates zero-initialized CANDIDATEFORM and maintains
4233 // it regardless of the actual position of the composition.
4234 AppInfoUtil::SetCompositionForm(
4235 &app_info, CompositionForm::DEFAULT, 0, 0, 0, 0, 0, 0);
4236
4237 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, nullptr);
4238
4239 CandidateWindowLayout layout;
4240 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4241 EXPECT_NON_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(985, 1023, layout);
4242 }
4243
4244 // V2C 2.1.6 on JRE 1.6.0.21 (32-bit)
TEST_F(Win32RendererUtilTest,V2C_Convert)4245 TEST_F(Win32RendererUtilTest, V2C_Convert) {
4246 const wchar_t kClassName[] = L"SunAwtFrame";
4247 const CRect kWindowRect(977, 446, 2042, 1052);
4248 const CPoint kClientOffset(8, 8);
4249 const CSize kClientSize(1049, 569);
4250 const double kScaleFactor = 1.0;
4251
4252 HWND hwnd = nullptr;
4253 LayoutManager layout_mgr(
4254 CreateDefaultGUIFontEmulator(),
4255 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4256 kScaleFactor, &hwnd));
4257
4258 ApplicationInfo app_info;
4259
4260 AppInfoUtil::SetBasicApplicationInfo(
4261 &app_info, hwnd,
4262 ApplicationInfo::ShowCandidateWindow |
4263 ApplicationInfo::ShowSuggestWindow);
4264
4265 // V2C occasionally creates zero-initialized CANDIDATEFORM and maintains
4266 // it regardless of the actual position of the composition.
4267 AppInfoUtil::SetCompositionForm(
4268 &app_info, CompositionForm::DEFAULT, 0, 0, 0, 0, 0, 0);
4269
4270 AppInfoUtil::SetCandidateForm(
4271 &app_info, CandidateForm::CANDIDATEPOS, 234, 523,
4272 1272967816, 1974044135, -348494668, -2);
4273
4274 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, nullptr);
4275
4276 CandidateWindowLayout layout;
4277 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4278 app_info, &layout));
4279 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4280 1211, 969, 1211, 951, 1212, 969, layout);
4281 }
4282
4283
4284 // Qt 4.6.3
TEST_F(Win32RendererUtilTest,Qt_Suggest)4285 TEST_F(Win32RendererUtilTest, Qt_Suggest) {
4286 const wchar_t kClassName[] = L"QWidget";
4287 const CRect kWindowRect(0, 20, 2016, 1050);
4288 const CPoint kClientOffset(8, 42);
4289 const CSize kClientSize(2000, 1000);
4290 const double kScaleFactor = 1.0;
4291
4292 HWND hwnd = nullptr;
4293 LayoutManager layout_mgr(
4294 CreateDefaultGUIFontEmulator(),
4295 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4296 kScaleFactor, &hwnd));
4297
4298 ApplicationInfo app_info;
4299
4300 AppInfoUtil::SetBasicApplicationInfo(
4301 &app_info,
4302 hwnd,
4303 ApplicationInfo::ShowSuggestWindow);
4304
4305 AppInfoUtil::SetCompositionFont(
4306 &app_info, -12, 0, 0, 0, FW_DONTCARE, DEFAULT_CHARSET,
4307 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
4308 DEFAULT_QUALITY, 0,
4309 "メイリオ");
4310
4311 AppInfoUtil::SetCompositionForm(
4312 &app_info, CompositionForm::FORCE_POSITION, 211, 68,
4313 18901544, 103737984, 4247412, 19851904);
4314
4315 AppInfoUtil::SetCandidateForm(
4316 &app_info, CandidateForm::EXCLUDE, 211, 87,
4317 211, 68, 221, 87);
4318
4319 AppInfoUtil::SetCaretInfo(&app_info, false, 211, 68, 212, 69, hwnd);
4320
4321 CandidateWindowLayout layout;
4322 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4323 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4324 219, 149, 219, 130, 229, 149, layout);
4325 }
4326
4327 // Qt 4.6.3
TEST_F(Win32RendererUtilTest,Qt_Convert)4328 TEST_F(Win32RendererUtilTest, Qt_Convert) {
4329 const wchar_t kClassName[] = L"QWidget";
4330 const CRect kWindowRect(0, 20, 2016, 1050);
4331 const CPoint kClientOffset(8, 42);
4332 const CSize kClientSize(2000, 1000);
4333 const double kScaleFactor = 1.0;
4334
4335 HWND hwnd = nullptr;
4336 LayoutManager layout_mgr(
4337 CreateDefaultGUIFontEmulator(),
4338 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4339 kScaleFactor, &hwnd));
4340
4341 ApplicationInfo app_info;
4342
4343 AppInfoUtil::SetBasicApplicationInfo(
4344 &app_info,
4345 hwnd,
4346 ApplicationInfo::ShowCandidateWindow |
4347 ApplicationInfo::ShowSuggestWindow);
4348
4349 AppInfoUtil::SetCompositionFont(
4350 &app_info, -12, 0, 0, 0, FW_DONTCARE, DEFAULT_CHARSET,
4351 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
4352 DEFAULT_QUALITY, 0,
4353 "メイリオ");
4354
4355 AppInfoUtil::SetCompositionForm(
4356 &app_info, CompositionForm::FORCE_POSITION, 187, 68,
4357 18901544, 103737984, 4247412, 19851904);
4358
4359 AppInfoUtil::SetCandidateForm(
4360 &app_info, CandidateForm::EXCLUDE, 187, 87,
4361 187, 68, 197, 87);
4362
4363 AppInfoUtil::SetCaretInfo(&app_info, false, 187, 68, 188, 69, hwnd);
4364
4365 CandidateWindowLayout layout;
4366 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4367 app_info, &layout));
4368 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4369 195, 149, 195, 130, 205, 149, layout);
4370 }
4371
4372 // Wordpad x86 on Vista SP1
TEST_F(Win32RendererUtilTest,Wordpad_Vista_Indicator)4373 TEST_F(Win32RendererUtilTest, Wordpad_Vista_Indicator) {
4374 const wchar_t kClassName[] = L"RICHEDIT50W";
4375 const CRect kWindowRect(617, 573, 1319, 881);
4376 const CPoint kClientOffset(2, 22);
4377 const CSize kClientSize(698, 304);
4378 const double kScaleFactor = 1.0;
4379
4380 HWND hwnd = nullptr;
4381 LayoutManager layout_mgr(
4382 CreateDefaultGUIFontEmulator(),
4383 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4384 kScaleFactor, &hwnd));
4385
4386 ApplicationInfo app_info;
4387
4388 AppInfoUtil::SetBasicApplicationInfo(
4389 &app_info, hwnd,
4390 ApplicationInfo::ShowCandidateWindow |
4391 ApplicationInfo::ShowSuggestWindow);
4392
4393 AppInfoUtil::SetCompositionFont(
4394 &app_info, 10, 0, 0, 0, FW_DONTCARE, SHIFTJIS_CHARSET,
4395 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
4396 DEFAULT_QUALITY, 17,
4397 "MS Pゴシック");
4398
4399 AppInfoUtil::SetCandidateForm(
4400 &app_info, CandidateForm::EXCLUDE, 62, 42, 62, 21, 64, 42);
4401
4402 AppInfoUtil::SetCompositionTarget(
4403 &app_info, 1, 693, 596, 17, 625, 579, 1317, 879);
4404
4405 AppInfoUtil::SetCaretInfo(&app_info, false, 74, 21, 75, 38, hwnd);
4406
4407 IndicatorWindowLayout layout;
4408 EXPECT_TRUE(layout_mgr.LayoutIndicatorWindow(app_info, &layout));
4409 EXPECT_EQ(CRect(693, 596, 694, 613), layout.window_rect);
4410 EXPECT_FALSE(layout.is_vertical);
4411 }
4412
4413 // Wordpad x86 on Vista SP1
TEST_F(Win32RendererUtilTest,Wordpad_Vista_Suggest)4414 TEST_F(Win32RendererUtilTest, Wordpad_Vista_Suggest) {
4415 const wchar_t kClassName[] = L"RICHEDIT50W";
4416 const CRect kWindowRect(617, 573, 1319, 881);
4417 const CPoint kClientOffset(2, 22);
4418 const CSize kClientSize(698, 304);
4419 const double kScaleFactor = 1.0;
4420
4421 HWND hwnd = nullptr;
4422 LayoutManager layout_mgr(
4423 CreateDefaultGUIFontEmulator(),
4424 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4425 kScaleFactor, &hwnd));
4426
4427 ApplicationInfo app_info;
4428
4429 AppInfoUtil::SetBasicApplicationInfo(
4430 &app_info, hwnd,
4431 ApplicationInfo::ShowSuggestWindow);
4432
4433 AppInfoUtil::SetCompositionFont(
4434 &app_info, 10, 0, 0, 0, FW_DONTCARE, SHIFTJIS_CHARSET,
4435 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
4436 DEFAULT_QUALITY, 17,
4437 "MS Pゴシック");
4438
4439 AppInfoUtil::SetCompositionTarget(
4440 &app_info, 0, 681, 596, 17, 625, 579, 1317, 879);
4441
4442 AppInfoUtil::SetCaretInfo(&app_info, false, 98, 21, 99, 38, hwnd);
4443
4444 CandidateWindowLayout layout;
4445 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4446 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4447 681, 613, 681, 596, 682, 613, layout);
4448 }
4449
4450 // Wordpad x86 on Vista SP1
TEST_F(Win32RendererUtilTest,Wordpad_Vista_Convert)4451 TEST_F(Win32RendererUtilTest, Wordpad_Vista_Convert) {
4452 const wchar_t kClassName[] = L"RICHEDIT50W";
4453 const CRect kWindowRect(617, 573, 1319, 881);
4454 const CPoint kClientOffset(2, 22);
4455 const CSize kClientSize(698, 304);
4456 const double kScaleFactor = 1.0;
4457
4458 HWND hwnd = nullptr;
4459 LayoutManager layout_mgr(
4460 CreateDefaultGUIFontEmulator(),
4461 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4462 kScaleFactor, &hwnd));
4463
4464 ApplicationInfo app_info;
4465
4466 AppInfoUtil::SetBasicApplicationInfo(
4467 &app_info, hwnd,
4468 ApplicationInfo::ShowCandidateWindow |
4469 ApplicationInfo::ShowSuggestWindow);
4470
4471 AppInfoUtil::SetCompositionFont(
4472 &app_info, 10, 0, 0, 0, FW_DONTCARE, SHIFTJIS_CHARSET,
4473 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
4474 DEFAULT_QUALITY, 17,
4475 "MS Pゴシック");
4476
4477 AppInfoUtil::SetCandidateForm(
4478 &app_info, CandidateForm::EXCLUDE, 62, 42, 62, 21, 64, 42);
4479
4480 AppInfoUtil::SetCompositionTarget(
4481 &app_info, 1, 693, 596, 17, 625, 579, 1317, 879);
4482
4483 AppInfoUtil::SetCaretInfo(&app_info, false, 74, 21, 75, 38, hwnd);
4484
4485 CandidateWindowLayout layout;
4486 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4487 app_info, &layout));
4488 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4489 693, 613, 681, 616, 683, 637, layout);
4490 }
4491
4492 // MS Word 2010 x64, True Inline, Horizontal
TEST_F(Win32RendererUtilTest,MSWord2010_Horizontal_Suggest)4493 TEST_F(Win32RendererUtilTest, MSWord2010_Horizontal_Suggest) {
4494 const wchar_t kClassName[] = L"_WwG";
4495 const CRect kWindowRect(434, 288, 1275, 841);
4496 const CPoint kClientOffset(0, 0);
4497 const CSize kClientSize(841, 553);
4498 const double kScaleFactor = 1.0;
4499
4500 HWND hwnd = nullptr;
4501 LayoutManager layout_mgr(
4502 CreateDefaultGUIFontEmulator(),
4503 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4504 kScaleFactor, &hwnd));
4505
4506 ApplicationInfo app_info;
4507
4508 AppInfoUtil::SetBasicApplicationInfo(
4509 &app_info, hwnd,
4510 ApplicationInfo::ShowSuggestWindow);
4511
4512 AppInfoUtil::SetCompositionFont(
4513 &app_info, -14, 0, 0, 0, FW_NORMAL, SHIFTJIS_CHARSET,
4514 OUT_SCREEN_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,
4515 DEFAULT_QUALITY, 17,
4516 "MS 明朝");
4517
4518 AppInfoUtil::SetCandidateForm(
4519 &app_info, CandidateForm::EXCLUDE, 234, 176,
4520 136, 176, 703, 193);
4521
4522 AppInfoUtil::SetCompositionTarget(
4523 &app_info, 0, 626, 464, 17, 570, 288, 1137, 841);
4524
4525 AppInfoUtil::SetCaretInfo(&app_info, false, 220, 176, 221, 194, hwnd);
4526
4527 CandidateWindowLayout layout;
4528 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4529 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4530 626, 481, 626, 464, 627, 481, layout);
4531 }
4532
4533 // MS Word 2010 x64, True Inline, Horizontal
TEST_F(Win32RendererUtilTest,MSWord2010_Horizontal_Convert)4534 TEST_F(Win32RendererUtilTest, MSWord2010_Horizontal_Convert) {
4535 const wchar_t kClassName[] = L"_WwG";
4536 const CRect kWindowRect(434, 288, 1275, 841);
4537 const CPoint kClientOffset(0, 0);
4538 const CSize kClientSize(841, 553);
4539 const double kScaleFactor = 1.0;
4540
4541 HWND hwnd = nullptr;
4542 LayoutManager layout_mgr(
4543 CreateDefaultGUIFontEmulator(),
4544 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4545 kScaleFactor, &hwnd));
4546
4547 ApplicationInfo app_info;
4548
4549 AppInfoUtil::SetBasicApplicationInfo(
4550 &app_info, hwnd,
4551 ApplicationInfo::ShowCandidateWindow |
4552 ApplicationInfo::ShowSuggestWindow);
4553
4554 AppInfoUtil::SetCompositionFont(
4555 &app_info, -14, 0, 0, 0, FW_NORMAL, SHIFTJIS_CHARSET,
4556 OUT_SCREEN_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,
4557 DEFAULT_QUALITY, 17,
4558 "MS 明朝");
4559
4560 AppInfoUtil::SetCandidateForm(
4561 &app_info, CandidateForm::EXCLUDE, 206, 178,
4562 136, 178, 703, 194);
4563
4564 AppInfoUtil::SetCompositionTarget(
4565 &app_info, 1, 640, 466, 16, 570, 288, 1137, 841);
4566
4567 AppInfoUtil::SetCaretInfo(&app_info, false, 192, 179, 193, 197, hwnd);
4568
4569 CandidateWindowLayout layout;
4570 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4571 app_info, &layout));
4572 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4573 640, 482, 570, 466, 1137, 482, layout);
4574 }
4575
4576 // MS Word 2010 x64, True Inline, Vertical
TEST_F(Win32RendererUtilTest,MSWord2010_Vertical_Suggest)4577 TEST_F(Win32RendererUtilTest, MSWord2010_Vertical_Suggest) {
4578 const wchar_t kClassName[] = L"_WwG";
4579 const CRect kWindowRect(434, 288, 1275, 824);
4580 const CPoint kClientOffset(0, 0);
4581 const CSize kClientSize(841, 536);
4582 const double kScaleFactor = 1.0;
4583
4584 HWND hwnd = nullptr;
4585 LayoutManager layout_mgr(
4586 CreateDefaultGUIFontEmulator(),
4587 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4588 kScaleFactor, &hwnd));
4589
4590 ApplicationInfo app_info;
4591
4592 AppInfoUtil::SetBasicApplicationInfo(
4593 &app_info, hwnd,
4594 ApplicationInfo::ShowSuggestWindow);
4595
4596 AppInfoUtil::SetCompositionFont(
4597 &app_info, -14, 0, 2700, 2700, FW_NORMAL, SHIFTJIS_CHARSET,
4598 OUT_SCREEN_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,
4599 DEFAULT_QUALITY, 17,
4600 "@MS 明朝");
4601
4602 AppInfoUtil::SetCandidateForm(
4603 &app_info, CandidateForm::EXCLUDE, 662, 228,
4604 644, 130, 662, 697);
4605
4606 AppInfoUtil::SetCompositionTarget(
4607 &app_info, 0, 1096, 474, 18, 434, 418, 1275, 985);
4608
4609 AppInfoUtil::SetCaretInfo(&app_info, false, 644, 214, 645, 235, hwnd);
4610
4611 CandidateWindowLayout layout;
4612 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4613 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4614 1078, 474, 1078, 474, 1096, 475, layout);
4615 }
4616
4617 // MS Word 2010 x64, True Inline, Vertical
TEST_F(Win32RendererUtilTest,MSWord2010_Vertical_Convert)4618 TEST_F(Win32RendererUtilTest, MSWord2010_Vertical_Convert) {
4619 const wchar_t kClassName[] = L"_WwG";
4620 const CRect kWindowRect(434, 288, 1275, 824);
4621 const CPoint kClientOffset(0, 0);
4622 const CSize kClientSize(841, 536);
4623 const double kScaleFactor = 1.0;
4624
4625 HWND hwnd = nullptr;
4626 LayoutManager layout_mgr(
4627 CreateDefaultGUIFontEmulator(),
4628 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4629 kScaleFactor, &hwnd));
4630
4631 ApplicationInfo app_info;
4632
4633 AppInfoUtil::SetBasicApplicationInfo(
4634 &app_info, hwnd,
4635 ApplicationInfo::ShowCandidateWindow |
4636 ApplicationInfo::ShowSuggestWindow);
4637
4638 AppInfoUtil::SetCompositionFont(
4639 &app_info, -14, 0, 2700, 2700, FW_NORMAL, SHIFTJIS_CHARSET,
4640 OUT_SCREEN_OUTLINE_PRECIS, CLIP_DEFAULT_PRECIS,
4641 DEFAULT_QUALITY, 17,
4642 "@MS 明朝");
4643
4644 AppInfoUtil::SetCandidateForm(
4645 &app_info, CandidateForm::EXCLUDE, 661, 200,
4646 643, 130, 661, 697);
4647
4648 AppInfoUtil::SetCompositionTarget(
4649 &app_info, 1, 1095, 488, 18, 434, 418, 1275, 985);
4650
4651 AppInfoUtil::SetCaretInfo(&app_info, false, 643, 200, 644, 221, hwnd);
4652
4653 CandidateWindowLayout layout;
4654 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4655 app_info, &layout));
4656 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4657 1077, 488, 1077, 418, 1095, 985, layout);
4658 }
4659
4660 // Firefox 3.6.10 on Vista SP1 / textarea
TEST_F(Win32RendererUtilTest,Firefox_textarea_Suggest)4661 TEST_F(Win32RendererUtilTest, Firefox_textarea_Suggest) {
4662 const wchar_t kClassName[] = L"MozillaWindowClass";
4663 const CRect kWindowRect(198, 329, 1043, 1133);
4664 const CPoint kClientOffset(0, 0);
4665 const CSize kClientSize(845, 804);
4666 const double kScaleFactor = 1.0;
4667
4668 HWND hwnd = nullptr;
4669 LayoutManager layout_mgr(
4670 CreateDefaultGUIFontEmulator(),
4671 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4672 kScaleFactor, &hwnd));
4673
4674 ApplicationInfo app_info;
4675
4676 AppInfoUtil::SetBasicApplicationInfo(
4677 &app_info, hwnd,
4678 ApplicationInfo::ShowSuggestWindow);
4679
4680 AppInfoUtil::SetCandidateForm(
4681 &app_info, CandidateForm::EXCLUDE, 44, 378, 44, 378, 44, 398);
4682
4683 AppInfoUtil::SetCompositionTarget(
4684 &app_info, 0, 242, 707, 20, 198, 329, 1043, 1133);
4685
4686 AppInfoUtil::SetCaretInfo(&app_info, false, 89, 378, 90, 398, hwnd);
4687
4688 CandidateWindowLayout layout;
4689 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4690 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4691 242, 727, 242, 707, 242, 727, layout);
4692 }
4693
4694 // Firefox 3.6.10 on Vista SP1 / textarea
TEST_F(Win32RendererUtilTest,Firefox_textarea_Convert)4695 TEST_F(Win32RendererUtilTest, Firefox_textarea_Convert) {
4696 const wchar_t kClassName[] = L"MozillaWindowClass";
4697 const CRect kWindowRect(198, 329, 1043, 1133);
4698 const CPoint kClientOffset(0, 0);
4699 const CSize kClientSize(845, 804);
4700 const double kScaleFactor = 1.0;
4701
4702 HWND hwnd = nullptr;
4703 LayoutManager layout_mgr(
4704 CreateDefaultGUIFontEmulator(),
4705 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4706 kScaleFactor, &hwnd));
4707
4708 ApplicationInfo app_info;
4709
4710 AppInfoUtil::SetBasicApplicationInfo(
4711 &app_info, hwnd,
4712 ApplicationInfo::ShowCandidateWindow |
4713 ApplicationInfo::ShowSuggestWindow);
4714
4715 AppInfoUtil::SetCandidateForm(
4716 &app_info, CandidateForm::EXCLUDE, 59, 378, 59, 378, 59, 398);
4717
4718 AppInfoUtil::SetCompositionTarget(
4719 &app_info, 1, 257, 707, 20, 198, 329, 1043, 1133);
4720
4721 AppInfoUtil::SetCaretInfo(&app_info, false, 60, 378, 61, 398, hwnd);
4722
4723 CandidateWindowLayout layout;
4724 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4725 app_info, &layout));
4726 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4727 257, 727, 257, 707, 257, 727, layout);
4728 }
4729
4730 // Chrome 6.0.472.63 on Vista SP1 / textarea
TEST_F(Win32RendererUtilTest,Chrome_textarea_Suggest)4731 TEST_F(Win32RendererUtilTest, Chrome_textarea_Suggest) {
4732 const wchar_t kClassName[] = L"Chrome_RenderWidgetHostHWND";
4733 const CRect kWindowRect(153, 190, 891, 906);
4734 const CPoint kClientOffset(0, 0);
4735 const CSize kClientSize(738, 716);
4736 const double kScaleFactor = 1.0;
4737
4738 HWND hwnd = nullptr;
4739 LayoutManager layout_mgr(
4740 CreateDefaultGUIFontEmulator(),
4741 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4742 kScaleFactor, &hwnd));
4743
4744 ApplicationInfo app_info;
4745
4746 AppInfoUtil::SetBasicApplicationInfo(
4747 &app_info, hwnd,
4748 ApplicationInfo::ShowSuggestWindow);
4749
4750 AppInfoUtil::SetCompositionFont(
4751 &app_info, 11, 0, 0, 0, FW_DONTCARE, SHIFTJIS_CHARSET,
4752 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
4753 DEFAULT_QUALITY, 0,
4754 "メイリオ");
4755
4756 AppInfoUtil::SetCandidateForm(
4757 &app_info, CandidateForm::EXCLUDE, 84, 424, 84, 424, 85, 444);
4758
4759 AppInfoUtil::SetCaretInfo(&app_info, false, 84, 444, 85, 445, hwnd);
4760
4761 CandidateWindowLayout layout;
4762 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4763 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4764 237, 614, 237, 614, 238, 634, layout);
4765 }
4766
4767 // Chrome 6.0.472.63 on Vista SP1 / textarea
TEST_F(Win32RendererUtilTest,Chrome_textarea_Convert)4768 TEST_F(Win32RendererUtilTest, Chrome_textarea_Convert) {
4769 const wchar_t kClassName[] = L"Chrome_RenderWidgetHostHWND";
4770 const CRect kWindowRect(153, 190, 891, 906);
4771 const CPoint kClientOffset(0, 0);
4772 const CSize kClientSize(738, 716);
4773 const double kScaleFactor = 1.0;
4774
4775 HWND hwnd = nullptr;
4776 LayoutManager layout_mgr(
4777 CreateDefaultGUIFontEmulator(),
4778 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4779 kScaleFactor, &hwnd));
4780
4781 ApplicationInfo app_info;
4782
4783 AppInfoUtil::SetBasicApplicationInfo(
4784 &app_info, hwnd,
4785 ApplicationInfo::ShowCandidateWindow |
4786 ApplicationInfo::ShowSuggestWindow);
4787
4788 AppInfoUtil::SetCompositionFont(
4789 &app_info, 11, 0, 0, 0, FW_DONTCARE, SHIFTJIS_CHARSET,
4790 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
4791 DEFAULT_QUALITY, 0,
4792 "メイリオ");
4793
4794 AppInfoUtil::SetCandidateForm(
4795 &app_info, CandidateForm::EXCLUDE, 58, 424, 58, 424, 59, 444);
4796
4797 AppInfoUtil::SetCaretInfo(&app_info, false, 58, 444, 59, 445, hwnd);
4798
4799 CandidateWindowLayout layout;
4800 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4801 app_info, &layout));
4802 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4803 211, 614, 211, 614, 212, 634, layout);
4804 }
4805
4806 // Internet Explorer 8.0.6001.18943 on Vista SP1 / textarea
TEST_F(Win32RendererUtilTest,IE8_textarea_Suggest)4807 TEST_F(Win32RendererUtilTest, IE8_textarea_Suggest) {
4808 const wchar_t kClassName[] = L"Internet Explorer_Server";
4809 const CRect kWindowRect(304, 349, 1360, 1067);
4810 const CPoint kClientOffset(0, 0);
4811 const CSize kClientSize(1056, 718);
4812 const double kScaleFactor = 1.0;
4813
4814 HWND hwnd = nullptr;
4815 LayoutManager layout_mgr(
4816 CreateDefaultGUIFontEmulator(),
4817 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4818 kScaleFactor, &hwnd));
4819
4820 ApplicationInfo app_info;
4821
4822 AppInfoUtil::SetBasicApplicationInfo(
4823 &app_info, hwnd,
4824 ApplicationInfo::ShowSuggestWindow);
4825
4826 AppInfoUtil::SetCandidateForm(
4827 &app_info, CandidateForm::EXCLUDE, 105, 376, 105, 356, 107, 376);
4828
4829 AppInfoUtil::SetCaretInfo(&app_info, false, 105, 368, 106, 384, hwnd);
4830
4831 CandidateWindowLayout layout;
4832 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4833 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4834 409, 735, 409, 717, 410, 735, layout);
4835 }
4836
4837 // Internet Explorer 8.0.6001.18943 on Vista SP1 / textarea
TEST_F(Win32RendererUtilTest,IE8_textarea_Convert)4838 TEST_F(Win32RendererUtilTest, IE8_textarea_Convert) {
4839 const wchar_t kClassName[] = L"Internet Explorer_Server";
4840 const CRect kWindowRect(304, 349, 1360, 1067);
4841 const CPoint kClientOffset(0, 0);
4842 const CSize kClientSize(1056, 718);
4843 const double kScaleFactor = 1.0;
4844
4845 HWND hwnd = nullptr;
4846 LayoutManager layout_mgr(
4847 CreateDefaultGUIFontEmulator(),
4848 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4849 kScaleFactor, &hwnd));
4850
4851 ApplicationInfo app_info;
4852
4853 AppInfoUtil::SetBasicApplicationInfo(
4854 &app_info, hwnd,
4855 ApplicationInfo::ShowCandidateWindow |
4856 ApplicationInfo::ShowSuggestWindow);
4857
4858 AppInfoUtil::SetCandidateForm(
4859 &app_info, CandidateForm::EXCLUDE, 91, 387, 91, 367, 93, 387);
4860
4861 AppInfoUtil::SetCaretInfo(&app_info, false, 91, 379, 92, 380, hwnd);
4862
4863 CandidateWindowLayout layout;
4864 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4865 app_info, &layout));
4866 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4867 395, 736, 395, 716, 397, 736, layout);
4868 }
4869
4870 // Fudemame 21. See b/3067011.
4871 // It provides no positional information for suggestion. See b/3067011.
TEST_F(Win32RendererUtilTest,Fudemame21_Suggest)4872 TEST_F(Win32RendererUtilTest, Fudemame21_Suggest) {
4873 const wchar_t kClassName[] = L"MrnDirectEdit4";
4874 const CRect kWindowRect(507, 588, 1024, 698);
4875 const CPoint kClientOffset(0, 0);
4876 const CSize kClientSize(517, 110);
4877 const double kScaleFactor = 1.0;
4878
4879 HWND hwnd = nullptr;
4880 LayoutManager layout_mgr(
4881 CreateDefaultGUIFontEmulator(),
4882 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4883 kScaleFactor, &hwnd));
4884
4885 ApplicationInfo app_info;
4886
4887 AppInfoUtil::SetBasicApplicationInfo(
4888 &app_info, hwnd,
4889 ApplicationInfo::ShowSuggestWindow);
4890
4891 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, nullptr);
4892
4893 CandidateWindowLayout layout;
4894 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4895 EXPECT_NON_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(507, 698, layout);
4896 }
4897
4898 // Fudemame 21. See b/3067011.
TEST_F(Win32RendererUtilTest,Fudemame19_Convert)4899 TEST_F(Win32RendererUtilTest, Fudemame19_Convert) {
4900 const wchar_t kClassName[] = L"MrnDirectEdit4";
4901 const CRect kWindowRect(507, 588, 1024, 698);
4902 const CPoint kClientOffset(0, 0);
4903 const CSize kClientSize(517, 110);
4904 const double kScaleFactor = 1.0;
4905
4906 HWND hwnd = nullptr;
4907 LayoutManager layout_mgr(
4908 CreateDefaultGUIFontEmulator(),
4909 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4910 kScaleFactor, &hwnd));
4911
4912 ApplicationInfo app_info;
4913
4914 AppInfoUtil::SetBasicApplicationInfo(
4915 &app_info, hwnd,
4916 ApplicationInfo::ShowCandidateWindow |
4917 ApplicationInfo::ShowSuggestWindow);
4918
4919 AppInfoUtil::SetCandidateForm(
4920 &app_info, CandidateForm::CANDIDATEPOS, 87, 87, 0, 0, 0, 0);
4921
4922 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, nullptr);
4923
4924 CandidateWindowLayout layout;
4925 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
4926 app_info, &layout));
4927 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4928 594, 675, 594, 657, 595, 675, layout);
4929 }
4930
4931 // Opera 10.63 (build 3516) / Textarea
TEST_F(Win32RendererUtilTest,Opera10_Suggest)4932 TEST_F(Win32RendererUtilTest, Opera10_Suggest) {
4933 const wchar_t kClassName[] = L"OperaWindowClass";
4934 const UINT kClassStyle = CS_DBLCLKS;
4935 const DWORD kWindowStyle =
4936 WS_CAPTION | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
4937 WS_SYSMENU | WS_THICKFRAME | WS_OVERLAPPED | WS_MINIMIZEBOX |
4938 WS_MAXIMIZEBOX;
4939 static_assert(kWindowStyle == 0x16cf0000, "Check actual value");
4940 const DWORD kWindowExStyle =
4941 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR |
4942 WS_EX_ACCEPTFILES | WS_EX_WINDOWEDGE;
4943 static_assert(kWindowExStyle == 0x00000110, "Check actual value");
4944
4945 const CRect kWindowRect(538, 229, 2114, 1271);
4946 const CPoint kClientOffset(8, 0);
4947 const CSize kClientSize(1560, 1034);
4948 const double kScaleFactor = 1.0;
4949
4950 HWND hwnd = nullptr;
4951 LayoutManager layout_mgr(
4952 CreateDefaultGUIFontEmulator(),
4953 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4954 kScaleFactor, &hwnd));
4955
4956 ApplicationInfo app_info;
4957
4958 AppInfoUtil::SetBasicApplicationInfo(
4959 &app_info, hwnd,
4960 ApplicationInfo::ShowSuggestWindow);
4961
4962 AppInfoUtil::SetCandidateForm(
4963 &app_info, CandidateForm::EXCLUDE, 44, 444, 44, 444, 44, 459);
4964
4965 AppInfoUtil::SetCaretInfo(&app_info, false, 44, 444, 667, 750, hwnd);
4966
4967 CandidateWindowLayout layout;
4968 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(app_info, &layout));
4969 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
4970 590, 673, 590, 673, 590, 688, layout);
4971 }
4972
4973 // Opera 10.63 (build 3516) / Textarea
TEST_F(Win32RendererUtilTest,Opera10_Convert)4974 TEST_F(Win32RendererUtilTest, Opera10_Convert) {
4975 const wchar_t kClassName[] = L"OperaWindowClass";
4976 const UINT kClassStyle = CS_DBLCLKS;
4977 const DWORD kWindowStyle =
4978 WS_CAPTION | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
4979 WS_SYSMENU | WS_THICKFRAME | WS_OVERLAPPED | WS_MINIMIZEBOX |
4980 WS_MAXIMIZEBOX;
4981 static_assert(kWindowStyle == 0x16cf0000, "Check actual value");
4982 const DWORD kWindowExStyle =
4983 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR |
4984 WS_EX_ACCEPTFILES | WS_EX_WINDOWEDGE;
4985 static_assert(kWindowExStyle == 0x00000110, "Check actual value");
4986
4987 const CRect kWindowRect(538, 229, 2114, 1271);
4988 const CPoint kClientOffset(8, 0);
4989 const CSize kClientSize(1560, 1034);
4990 const double kScaleFactor = 1.0;
4991
4992 HWND hwnd = nullptr;
4993 LayoutManager layout_mgr(
4994 CreateDefaultGUIFontEmulator(),
4995 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
4996 kScaleFactor, &hwnd));
4997
4998 ApplicationInfo app_info;
4999
5000 AppInfoUtil::SetBasicApplicationInfo(
5001 &app_info, hwnd,
5002 ApplicationInfo::ShowCandidateWindow |
5003 ApplicationInfo::ShowSuggestWindow);
5004
5005 AppInfoUtil::SetCandidateForm(
5006 &app_info, CandidateForm::EXCLUDE, 22, 444, 22, 444, 22, 459);
5007
5008 AppInfoUtil::SetCaretInfo(&app_info, false, 22, 444, 645, 750, hwnd);
5009
5010 CandidateWindowLayout layout;
5011 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
5012 app_info, &layout));
5013 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
5014 568, 673, 568, 673, 568, 688, layout);
5015 }
5016
5017 // NTEmacs22 / GNU Emacs 22.2.1
5018 // Issue 5824433
TEST_F(Win32RendererUtilTest,Emacs22)5019 TEST_F(Win32RendererUtilTest, Emacs22) {
5020 const wchar_t kClassName[] = L"Emacs";
5021 const UINT kClassStyle = CS_VREDRAW | CS_HREDRAW;
5022 const DWORD kWindowStyle =
5023 WS_CAPTION | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
5024 WS_SYSMENU | WS_THICKFRAME | WS_OVERLAPPED | WS_MINIMIZEBOX |
5025 WS_MAXIMIZEBOX;
5026 static_assert(kWindowStyle == 0x16cf0000, "Check actual value");
5027 const DWORD kWindowExStyle =
5028 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR |
5029 WS_EX_ACCEPTFILES | WS_EX_OVERLAPPEDWINDOW;
5030 static_assert(kWindowExStyle == 0x00000310, "Check actual value");
5031
5032 const CRect kWindowRect(175, 175, 797, 924);
5033 const CPoint kClientOffset(10, 53);
5034 const CSize kClientSize(602, 686);
5035 const double kScaleFactor = 1.0;
5036
5037 HWND hwnd = nullptr;
5038 LayoutManager layout_mgr(
5039 CreateDefaultGUIFontEmulator(),
5040 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
5041 kScaleFactor, &hwnd));
5042
5043 ApplicationInfo app_info;
5044
5045 AppInfoUtil::SetBasicApplicationInfo(
5046 &app_info, hwnd,
5047 ApplicationInfo::ShowCompositionWindow |
5048 ApplicationInfo::ShowCandidateWindow |
5049 ApplicationInfo::ShowSuggestWindow);
5050
5051 AppInfoUtil::SetCompositionFont(
5052 &app_info, -14, 0, 0, 0, FW_NORMAL, ANSI_CHARSET,
5053 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
5054 DEFAULT_QUALITY, FIXED_PITCH,
5055 "Courier New");
5056
5057 AppInfoUtil::SetCompositionForm(
5058 &app_info, CompositionForm::RECT, 66, 58,
5059 10, 42, 570, 658);
5060
5061 AppInfoUtil::SetCaretInfo(&app_info, false, 66, 58, 67, 74, hwnd);
5062
5063 CandidateWindowLayout layout;
5064 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
5065 app_info, &layout));
5066 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
5067 251, 302, 251, 286, 252, 302, layout);
5068
5069 // This application automatically and frequently generates
5070 // WM_IME_CONTROL/IMC_SETCOMPOSITIONWINDOW even when a user is not
5071 // typing. So we need to show InfoList without delay. b/5824433.
5072 const int mode = layout_mgr.GetCompatibilityMode(app_info);
5073 EXPECT_EQ(SHOW_INFOLIST_IMMEDIATELY, mode & SHOW_INFOLIST_IMMEDIATELY);
5074 }
5075
5076 // Meadow 3.0 / GNU Emacs 22.3.1
5077 // Issue 5824433
TEST_F(Win32RendererUtilTest,Meadow3)5078 TEST_F(Win32RendererUtilTest, Meadow3) {
5079 const wchar_t kClassName[] = L"MEADOW";
5080 const UINT kClassStyle = CS_VREDRAW | CS_HREDRAW;
5081 const DWORD kWindowStyle =
5082 WS_CAPTION | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
5083 WS_SYSMENU | WS_THICKFRAME | WS_OVERLAPPED | WS_MINIMIZEBOX |
5084 WS_MAXIMIZEBOX;
5085 static_assert(kWindowStyle == 0x16cf0000, "Check actual value");
5086 const DWORD kWindowExStyle =
5087 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR |
5088 WS_EX_ACCEPTFILES | WS_EX_OVERLAPPEDWINDOW;
5089 static_assert(kWindowExStyle == 0x00000310, "Check actual value");
5090
5091 const CRect kWindowRect(175, 175, 797, 928);
5092 const CPoint kClientOffset(10, 53);
5093 const CSize kClientSize(602, 690);
5094 const double kScaleFactor = 1.0;
5095
5096 HWND hwnd = nullptr;
5097 LayoutManager layout_mgr(
5098 CreateDefaultGUIFontEmulator(),
5099 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
5100 kScaleFactor, &hwnd));
5101
5102 ApplicationInfo app_info;
5103
5104 AppInfoUtil::SetBasicApplicationInfo(
5105 &app_info, hwnd,
5106 ApplicationInfo::ShowCompositionWindow |
5107 ApplicationInfo::ShowCandidateWindow |
5108 ApplicationInfo::ShowSuggestWindow);
5109
5110 AppInfoUtil::SetCompositionForm(
5111 &app_info, CompositionForm::RECT, 73, 65,
5112 9, 49, 577, 657);
5113
5114 AppInfoUtil::SetCaretInfo(&app_info, false, 0, 0, 0, 0, hwnd);
5115
5116 CandidateWindowLayout layout;
5117 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
5118 app_info, &layout));
5119 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
5120 258, 311, 258, 293, 259, 311, layout);
5121
5122 // This application automatically and frequently generates
5123 // WM_IME_CONTROL/IMC_SETCOMPOSITIONWINDOW even when a user is not
5124 // typing. So we need to show InfoList without delay. b/5824433.
5125 const int mode = layout_mgr.GetCompatibilityMode(app_info);
5126 EXPECT_EQ(SHOW_INFOLIST_IMMEDIATELY, mode & SHOW_INFOLIST_IMMEDIATELY);
5127 }
5128
5129 // Firefox 47.0a1 (2016-02-28)
TEST_F(Win32RendererUtilTest,Firefox_ExcludeRect_Suggest)5130 TEST_F(Win32RendererUtilTest, Firefox_ExcludeRect_Suggest) {
5131 const wchar_t kClassName[] = L"MozillaWindowClass";
5132 const UINT kClassStyle = CS_DBLCLKS;
5133 const DWORD kWindowStyle =
5134 WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
5135 static_assert(kWindowStyle == 0x96000000, "Check actual value");
5136 const DWORD kWindowExStyle =
5137 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
5138 static_assert(kWindowExStyle == 0x00000000, "Check actual value");
5139
5140 const CRect kWindowRect(58, 22, 1210, 622);
5141 const CPoint kClientOffset(6, 0);
5142 const CSize kClientSize(1140, 594);
5143 const double kScaleFactor = 1.0;
5144
5145 HWND hwnd = nullptr;
5146 LayoutManager layout_mgr(
5147 CreateDefaultGUIFontEmulator(),
5148 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
5149 kScaleFactor, &hwnd));
5150
5151 ApplicationInfo app_info;
5152
5153 AppInfoUtil::SetBasicApplicationInfo(
5154 &app_info, hwnd,
5155 ApplicationInfo::ShowSuggestWindow);
5156
5157 AppInfoUtil::SetCandidateForm(
5158 &app_info, CandidateForm::EXCLUDE, 22, 100, 22, 100, 37, 160);
5159
5160 AppInfoUtil::SetCompositionTarget(
5161 &app_info, 0, 86, 122, 20, 83, 119, 109, 525);
5162
5163 AppInfoUtil::SetCaretInfo(&app_info, false, 35, 140, 36, 160, hwnd);
5164
5165 CandidateWindowLayout layout;
5166 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForSuggestion(
5167 app_info, &layout));
5168 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
5169 86, 142, 86, 122, 101, 182, layout);
5170 }
5171
5172 // Firefox 47.0a1 (2016-02-28)
TEST_F(Win32RendererUtilTest,Firefox_ExcludeRect_Convert)5173 TEST_F(Win32RendererUtilTest, Firefox_ExcludeRect_Convert) {
5174 const wchar_t kClassName[] = L"MozillaWindowClass";
5175 const UINT kClassStyle = CS_DBLCLKS;
5176 const DWORD kWindowStyle =
5177 WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
5178 static_assert(kWindowStyle == 0x96000000, "Check actual value");
5179 const DWORD kWindowExStyle =
5180 WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR;
5181 static_assert(kWindowExStyle == 0x00000000, "Check actual value");
5182
5183 const CRect kWindowRect(58, 22, 1210, 622);
5184 const CPoint kClientOffset(6, 0);
5185 const CSize kClientSize(1140, 594);
5186 const double kScaleFactor = 1.0;
5187
5188 HWND hwnd = nullptr;
5189 LayoutManager layout_mgr(
5190 CreateDefaultGUIFontEmulator(),
5191 CreateWindowEmulator(kClassName, kWindowRect, kClientOffset, kClientSize,
5192 kScaleFactor, &hwnd));
5193
5194 ApplicationInfo app_info;
5195
5196 AppInfoUtil::SetBasicApplicationInfo(
5197 &app_info, hwnd,
5198 ApplicationInfo::ShowCandidateWindow |
5199 ApplicationInfo::ShowSuggestWindow);
5200
5201 AppInfoUtil::SetCandidateForm(
5202 &app_info, CandidateForm::EXCLUDE, 22, 100, 22, 100, 37, 160);
5203
5204 AppInfoUtil::SetCompositionTarget(
5205 &app_info, 0, 86, 122, 20, 83, 119, 109, 525);
5206
5207 AppInfoUtil::SetCaretInfo(&app_info, false, 35, 140, 36, 160, hwnd);
5208
5209 CandidateWindowLayout layout;
5210 EXPECT_TRUE(layout_mgr.LayoutCandidateWindowForConversion(
5211 app_info, &layout));
5212 EXPECT_EXCLUDE_CANDIDATE_WINDOW_LAYOUT(
5213 86, 142, 86, 122, 101, 182, layout);
5214 }
5215
5216 } // namespace win32
5217 } // namespace renderer
5218 } // namespace mozc
5219