• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ui/base/ime/composition_text_util_pango.h"
6 
7 #include <pango/pango-attributes.h>
8 
9 #include <string>
10 #include <utility>
11 
12 #include "base/basictypes.h"
13 #include "base/logging.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/base/ime/composition_text.h"
16 
17 namespace {
18 
19 struct AttributeInfo {
20   int type;
21   int value;
22   int start_offset;
23   int end_offset;
24 };
25 
26 struct Underline {
27   unsigned start_offset;
28   unsigned end_offset;
29   uint32 color;
30   bool thick;
31   uint32 background_color;
32 };
33 
34 struct TestData {
35   const char* text;
36   const AttributeInfo attrs[10];
37   const Underline underlines[10];
38 };
39 
40 const TestData kTestData[] = {
41     // Normal case
42     {"One Two Three",
43      {{PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3},
44       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_DOUBLE, 4, 7},
45       {PANGO_ATTR_BACKGROUND, 0, 4, 7},
46       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 13},
47       {0, 0, 0, 0}},
48      {{0, 3, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
49       {4, 7, SK_ColorBLACK, true, SK_ColorTRANSPARENT},
50       {8, 13, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
51       {0, 0, 0, false, SK_ColorTRANSPARENT}}},
52 
53     // Offset overflow.
54     {"One Two Three",
55      {{PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3},
56       {PANGO_ATTR_BACKGROUND, 0, 4, 7},
57       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 20},
58       {0, 0, 0, 0}},
59      {{0, 3, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
60       {4, 7, SK_ColorBLACK, true, SK_ColorTRANSPARENT},
61       {8, 13, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
62       {0, 0, 0, false, SK_ColorTRANSPARENT}}},
63 
64     // Error underline.
65     {"One Two Three",
66      {{PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3},
67       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_ERROR, 4, 7},
68       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 13},
69       {0, 0, 0, 0}},
70      {{0, 3, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
71       {4, 7, SK_ColorRED, false, SK_ColorTRANSPARENT},
72       {8, 13, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
73       {0, 0, 0, false, SK_ColorTRANSPARENT}}},
74 
75     // Default underline.
76     {"One Two Three",
77      {{0, 0, 0, 0}},
78      {{0, 13, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
79       {0, 0, 0, false, SK_ColorTRANSPARENT}}},
80 
81     // Unicode, including non-BMP characters: "123你好����一丁 456"
82     {"123\xE4\xBD\xA0\xE5\xA5\xBD\xF0\xA0\x80\x80\xF0\xA0\x80\x81\xE4\xB8\x80"
83      "\xE4\xB8\x81 456",
84      {{PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3},
85       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 3, 5},
86       {PANGO_ATTR_BACKGROUND, 0, 5, 7},
87       {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 7, 13},
88       {0, 0, 0, 0}},
89      {{0, 3, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
90       {3, 5, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
91       {5, 9, SK_ColorBLACK, true, SK_ColorTRANSPARENT},
92       {9, 15, SK_ColorBLACK, false, SK_ColorTRANSPARENT},
93       {0, 0, 0, false, SK_ColorTRANSPARENT}}},
94 };
95 
CompareUnderline(const Underline & a,const ui::CompositionUnderline & b)96 void CompareUnderline(const Underline& a,
97                       const ui::CompositionUnderline& b) {
98   EXPECT_EQ(a.start_offset, b.start_offset);
99   EXPECT_EQ(a.end_offset, b.end_offset);
100   EXPECT_EQ(a.color, b.color);
101   EXPECT_EQ(a.thick, b.thick);
102   EXPECT_EQ(a.background_color, b.background_color);
103 }
104 
TEST(CompositionTextUtilPangoTest,ExtractCompositionText)105 TEST(CompositionTextUtilPangoTest, ExtractCompositionText) {
106   for (size_t i = 0; i < arraysize(kTestData); ++i) {
107     const char* text = kTestData[i].text;
108     const AttributeInfo* attrs = kTestData[i].attrs;
109     SCOPED_TRACE(testing::Message() << "Testing:" << i
110                  << " text:" << text);
111 
112     PangoAttrList* pango_attrs = pango_attr_list_new();
113     for (size_t a = 0; attrs[a].type; ++a) {
114       PangoAttribute* pango_attr = NULL;
115       switch (attrs[a].type) {
116         case PANGO_ATTR_UNDERLINE:
117           pango_attr = pango_attr_underline_new(
118               static_cast<PangoUnderline>(attrs[a].value));
119           break;
120         case PANGO_ATTR_BACKGROUND:
121           pango_attr = pango_attr_background_new(0, 0, 0);
122           break;
123         default:
124           NOTREACHED();
125       }
126       pango_attr->start_index =
127           g_utf8_offset_to_pointer(text, attrs[a].start_offset) - text;
128       pango_attr->end_index =
129           g_utf8_offset_to_pointer(text, attrs[a].end_offset) - text;
130       pango_attr_list_insert(pango_attrs, pango_attr);
131     }
132 
133     ui::CompositionText result;
134     ui::ExtractCompositionTextFromGtkPreedit(text, pango_attrs, 0, &result);
135 
136     const Underline* underlines = kTestData[i].underlines;
137     for (size_t u = 0; underlines[u].color &&
138          u < result.underlines.size(); ++u) {
139       SCOPED_TRACE(testing::Message() << "Underline:" << u);
140       CompareUnderline(underlines[u], result.underlines[u]);
141     }
142 
143     pango_attr_list_unref(pango_attrs);
144   }
145 }
146 
147 }  // namespace
148