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 17namespace { 18 19struct AttributeInfo { 20 int type; 21 int value; 22 int start_offset; 23 int end_offset; 24}; 25 26struct Underline { 27 unsigned start_offset; 28 unsigned end_offset; 29 uint32 color; 30 bool thick; 31 uint32 background_color; 32}; 33 34struct TestData { 35 const char* text; 36 const AttributeInfo attrs[10]; 37 const Underline underlines[10]; 38}; 39 40const 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 96void 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 105TEST(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