1/*
2 * Copyright 2011 Google Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// type.h needs to be included first because of building issues on Windows
18// Type aliases we delcare are defined in other headers and make the build
19// fail otherwise.
20#include "sfntly/port/type.h"
21#include <assert.h>
22#include <stdio.h>
23#include <unicode/ucnv.h>
24
25#include <iostream>
26#include <string>
27
28#include "gtest/gtest.h"
29#include "sfntly/data/memory_byte_array.h"
30#include "sfntly/font.h"
31#include "sfntly/font_factory.h"
32#include "sfntly/table/core/cmap_table.h"
33#include "sfntly/table/core/font_header_table.h"
34#include "sfntly/tag.h"
35#include "test/autogenerated/cmap_test_data.h"
36#include "test/test_font_utils.h"
37#include "test/test_utils.h"
38#include "test/test_xml_utils.h"
39
40namespace sfntly {
41
42#if GTEST_HAS_PARAM_TEST
43
44using ::testing::TestWithParam;
45using ::testing::Values;
46
47class CMapBasicTests : public :: testing::TestWithParam<const char*> {
48 public:
49  CMapBasicTests() {}
50  virtual void SetUp();
51  virtual void TearDown() {}
52
53  Ptr<CMapTable> cmap_table_;
54  TiXmlDocument document_;
55};
56
57void CMapBasicTests::SetUp() {
58  // Loading the font
59  Ptr<FontFactory> font_factory;
60  font_factory.Attach(FontFactory::GetInstance());
61  FontArray font_array;
62  std::string font_name = "../../";
63#if defined (WIN32)
64  font_name += "../";
65#endif
66  font_name += std::string(GetParam());
67  LoadFont(font_name.c_str(), font_factory, &font_array);
68  ASSERT_FALSE(font_array.empty());
69  Ptr<Font> font = font_array.at(0);
70  ASSERT_NE(font, reinterpret_cast<Font*>(NULL));
71  cmap_table_ = down_cast<CMapTable*>(font->GetTable(Tag::cmap));
72  if (!cmap_table_)
73    fprintf(stderr, "No CMap: %s\n", font_name.c_str());
74  ASSERT_NE(cmap_table_, reinterpret_cast<CMapTable*>(NULL));
75
76  // Loading the XML file
77  document_ = TiXmlDocument((font_name + ".xml").c_str());
78  ASSERT_TRUE(document_.LoadFile());
79}
80
81TEST_P(CMapBasicTests, BasicTest) {
82  TiXmlNodeVector* cmap_table = GetNodesWithName(&document_, "cmap_table");
83  // A font can only have one CMap table
84  ASSERT_EQ(cmap_table->size(), (size_t)1);
85  TiXmlNodeVector* cmaps = GetNodesWithName(cmap_table->at(0), "cmap");
86  const TiXmlAttribute* num_cmaps_attr = GetAttribute(cmap_table->at(0),
87                                                      "num_cmaps");
88  ASSERT_NE(num_cmaps_attr, reinterpret_cast<TiXmlAttribute*>(NULL));
89  // But there may be more than one CMap in this table
90  ASSERT_LE(cmaps->size(), (size_t)num_cmaps_attr->IntValue());
91  for (TiXmlNodeVector::iterator it = cmaps->begin();
92       it != cmaps->end(); ++it) {
93    int32_t platform_id = GetAttribute(*it, "platform_id")->IntValue();
94    int32_t encoding_id = GetAttribute(*it, "encoding_id")->IntValue();
95    Ptr<CMapTable::CMap> cmap;
96    cmap.Attach(cmap_table_->GetCMap(platform_id, encoding_id));
97    if (!cmap) {
98      fprintf(stderr, "Cannot test unsupported CMapFormat%d\n",
99              GetAttribute(*it, "format")->IntValue());
100      continue;
101    }
102    ASSERT_EQ(cmap->platform_id(), platform_id);
103    ASSERT_EQ(cmap->encoding_id(), encoding_id);
104    TiXmlNodeVector* maps = GetNodesWithName(*it, "map");
105    for (TiXmlNodeVector::iterator jt = maps->begin();
106         jt != maps->end(); ++jt) {
107      int32_t character;
108#if defined (WIN32)
109      sscanf_s(GetAttribute(*jt, "char")->Value(), "%x", &character);
110#else
111      sscanf(GetAttribute(*jt, "char")->Value(), "%x", &character);
112#endif
113      int32_t glyph_id = GetAttribute(*jt, "gid")->IntValue();
114      ASSERT_EQ(cmap->GlyphId(character), glyph_id);
115    }
116    delete maps;
117  }
118  delete cmaps;
119  delete cmap_table;
120}
121
122INSTANTIATE_TEST_CASE_P(CMapBasicTests,
123                        CMapBasicTests,
124                        ::testing::ValuesIn(cmap_test_data::kAllTests));
125
126#else
127
128TEST(DummyTest, ValueParameterizedTestsAreNotSupportedOnThisPlatform) {}
129
130#endif  // GTEST_HAS_PARAM
131}
132