Home | History | Annotate | Download | only in ime
      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 
     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 
    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