| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "ui/base/ime/composition_text_util_pango.h" |
| |
| #include <pango/pango-attributes.h> |
| |
| #include <string> |
| #include <utility> |
| |
| #include "base/basictypes.h" |
| #include "base/logging.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/ime/composition_text.h" |
| |
| namespace { |
| |
| struct AttributeInfo { |
| int type; |
| int value; |
| int start_offset; |
| int end_offset; |
| }; |
| |
| struct Underline { |
| unsigned start_offset; |
| unsigned end_offset; |
| uint32 color; |
| bool thick; |
| uint32 background_color; |
| }; |
| |
| struct TestData { |
| const char* text; |
| const AttributeInfo attrs[10]; |
| const Underline underlines[10]; |
| }; |
| |
| const TestData kTestData[] = { |
| // Normal case |
| {"One Two Three", |
| {{PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3}, |
| {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_DOUBLE, 4, 7}, |
| {PANGO_ATTR_BACKGROUND, 0, 4, 7}, |
| {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 13}, |
| {0, 0, 0, 0}}, |
| {{0, 3, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {4, 7, SK_ColorBLACK, true, SK_ColorTRANSPARENT}, |
| {8, 13, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {0, 0, 0, false, SK_ColorTRANSPARENT}}}, |
| |
| // Offset overflow. |
| {"One Two Three", |
| {{PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3}, |
| {PANGO_ATTR_BACKGROUND, 0, 4, 7}, |
| {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 20}, |
| {0, 0, 0, 0}}, |
| {{0, 3, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {4, 7, SK_ColorBLACK, true, SK_ColorTRANSPARENT}, |
| {8, 13, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {0, 0, 0, false, SK_ColorTRANSPARENT}}}, |
| |
| // Error underline. |
| {"One Two Three", |
| {{PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3}, |
| {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_ERROR, 4, 7}, |
| {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 8, 13}, |
| {0, 0, 0, 0}}, |
| {{0, 3, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {4, 7, SK_ColorRED, false, SK_ColorTRANSPARENT}, |
| {8, 13, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {0, 0, 0, false, SK_ColorTRANSPARENT}}}, |
| |
| // Default underline. |
| {"One Two Three", |
| {{0, 0, 0, 0}}, |
| {{0, 13, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {0, 0, 0, false, SK_ColorTRANSPARENT}}}, |
| |
| // Unicode, including non-BMP characters: "123你好𠀀𠀁一丁 456" |
| {"123\xE4\xBD\xA0\xE5\xA5\xBD\xF0\xA0\x80\x80\xF0\xA0\x80\x81\xE4\xB8\x80" |
| "\xE4\xB8\x81 456", |
| {{PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 0, 3}, |
| {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 3, 5}, |
| {PANGO_ATTR_BACKGROUND, 0, 5, 7}, |
| {PANGO_ATTR_UNDERLINE, PANGO_UNDERLINE_SINGLE, 7, 13}, |
| {0, 0, 0, 0}}, |
| {{0, 3, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {3, 5, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {5, 9, SK_ColorBLACK, true, SK_ColorTRANSPARENT}, |
| {9, 15, SK_ColorBLACK, false, SK_ColorTRANSPARENT}, |
| {0, 0, 0, false, SK_ColorTRANSPARENT}}}, |
| }; |
| |
| void CompareUnderline(const Underline& a, |
| const ui::CompositionUnderline& b) { |
| EXPECT_EQ(a.start_offset, b.start_offset); |
| EXPECT_EQ(a.end_offset, b.end_offset); |
| EXPECT_EQ(a.color, b.color); |
| EXPECT_EQ(a.thick, b.thick); |
| EXPECT_EQ(a.background_color, b.background_color); |
| } |
| |
| TEST(CompositionTextUtilPangoTest, ExtractCompositionText) { |
| for (size_t i = 0; i < arraysize(kTestData); ++i) { |
| const char* text = kTestData[i].text; |
| const AttributeInfo* attrs = kTestData[i].attrs; |
| SCOPED_TRACE(testing::Message() << "Testing:" << i |
| << " text:" << text); |
| |
| PangoAttrList* pango_attrs = pango_attr_list_new(); |
| for (size_t a = 0; attrs[a].type; ++a) { |
| PangoAttribute* pango_attr = NULL; |
| switch (attrs[a].type) { |
| case PANGO_ATTR_UNDERLINE: |
| pango_attr = pango_attr_underline_new( |
| static_cast<PangoUnderline>(attrs[a].value)); |
| break; |
| case PANGO_ATTR_BACKGROUND: |
| pango_attr = pango_attr_background_new(0, 0, 0); |
| break; |
| default: |
| NOTREACHED(); |
| } |
| pango_attr->start_index = |
| g_utf8_offset_to_pointer(text, attrs[a].start_offset) - text; |
| pango_attr->end_index = |
| g_utf8_offset_to_pointer(text, attrs[a].end_offset) - text; |
| pango_attr_list_insert(pango_attrs, pango_attr); |
| } |
| |
| ui::CompositionText result; |
| ui::ExtractCompositionTextFromGtkPreedit(text, pango_attrs, 0, &result); |
| |
| const Underline* underlines = kTestData[i].underlines; |
| for (size_t u = 0; underlines[u].color && |
| u < result.underlines.size(); ++u) { |
| SCOPED_TRACE(testing::Message() << "Underline:" << u); |
| CompareUnderline(underlines[u], result.underlines[u]); |
| } |
| |
| pango_attr_list_unref(pango_attrs); |
| } |
| } |
| |
| } // namespace |