1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/tests/gtest/gfxFontSelectionTest.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,314 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "gtest/gtest.h" 1.10 + 1.11 +#include "nsCOMPtr.h" 1.12 +#include "nsTArray.h" 1.13 +#include "nsString.h" 1.14 +#include "nsDependentString.h" 1.15 + 1.16 +#include "mozilla/Preferences.h" 1.17 + 1.18 +#include "gfxContext.h" 1.19 +#include "gfxFont.h" 1.20 +#include "gfxPlatform.h" 1.21 + 1.22 +#include "gfxFontTest.h" 1.23 + 1.24 +using namespace mozilla; 1.25 + 1.26 +enum { 1.27 + S_UTF8 = 0, 1.28 + S_ASCII = 1 1.29 +}; 1.30 + 1.31 +class FrameTextRunCache; 1.32 + 1.33 +struct LiteralArray { 1.34 + LiteralArray (unsigned long l1) { 1.35 + data.AppendElement(l1); 1.36 + } 1.37 + LiteralArray (unsigned long l1, unsigned long l2) { 1.38 + data.AppendElement(l1); 1.39 + data.AppendElement(l2); 1.40 + } 1.41 + LiteralArray (unsigned long l1, unsigned long l2, unsigned long l3) { 1.42 + data.AppendElement(l1); 1.43 + data.AppendElement(l2); 1.44 + data.AppendElement(l3); 1.45 + } 1.46 + LiteralArray (unsigned long l1, unsigned long l2, unsigned long l3, unsigned long l4) { 1.47 + data.AppendElement(l1); 1.48 + data.AppendElement(l2); 1.49 + data.AppendElement(l3); 1.50 + data.AppendElement(l4); 1.51 + } 1.52 + LiteralArray (unsigned long l1, unsigned long l2, unsigned long l3, unsigned long l4, unsigned long l5) { 1.53 + data.AppendElement(l1); 1.54 + data.AppendElement(l2); 1.55 + data.AppendElement(l3); 1.56 + data.AppendElement(l4); 1.57 + data.AppendElement(l5); 1.58 + } 1.59 + 1.60 + LiteralArray (const LiteralArray& other) { 1.61 + data = other.data; 1.62 + } 1.63 + 1.64 + nsTArray<unsigned long> data; 1.65 +}; 1.66 + 1.67 +#define GLYPHS LiteralArray 1.68 + 1.69 +struct TestEntry { 1.70 + TestEntry (const char *aUTF8FamilyString, 1.71 + const gfxFontStyle& aFontStyle, 1.72 + const char *aString) 1.73 + : utf8FamilyString(aUTF8FamilyString), 1.74 + fontStyle(aFontStyle), 1.75 + stringType(S_ASCII), 1.76 + string(aString), 1.77 + isRTL(false) 1.78 + { 1.79 + } 1.80 + 1.81 + TestEntry (const char *aUTF8FamilyString, 1.82 + const gfxFontStyle& aFontStyle, 1.83 + int stringType, 1.84 + const char *aString) 1.85 + : utf8FamilyString(aUTF8FamilyString), 1.86 + fontStyle(aFontStyle), 1.87 + stringType(stringType), 1.88 + string(aString), 1.89 + isRTL(false) 1.90 + { 1.91 + } 1.92 + 1.93 + struct ExpectItem { 1.94 + ExpectItem(const nsCString& aFontName, 1.95 + const LiteralArray& aGlyphs) 1.96 + : fontName(aFontName), glyphs(aGlyphs) 1.97 + { } 1.98 + 1.99 + bool Compare(const nsCString& aFontName, 1.100 + cairo_glyph_t *aGlyphs, 1.101 + int num_glyphs) 1.102 + { 1.103 + // bit that allowed for empty fontname to match all is commented 1.104 + // out 1.105 + if (/*!fontName.IsEmpty() &&*/ !fontName.Equals(aFontName)) 1.106 + return false; 1.107 + 1.108 + if (num_glyphs != int(glyphs.data.Length())) 1.109 + return false; 1.110 + 1.111 + for (int j = 0; j < num_glyphs; j++) { 1.112 + if (glyphs.data[j] != aGlyphs[j].index) 1.113 + return false; 1.114 + } 1.115 + 1.116 + return true; 1.117 + } 1.118 + 1.119 + nsCString fontName; 1.120 + LiteralArray glyphs; 1.121 + }; 1.122 + 1.123 + void SetRTL() 1.124 + { 1.125 + isRTL = true; 1.126 + } 1.127 + 1.128 + // Empty/nullptr fontName means ignore font name 1.129 + void Expect (const char *platform, 1.130 + const char *fontName, 1.131 + const LiteralArray& glyphs) 1.132 + { 1.133 + if (fontName) 1.134 + Expect (platform, nsDependentCString(fontName), glyphs); 1.135 + else 1.136 + Expect (platform, nsCString(), glyphs); 1.137 + } 1.138 + 1.139 + void Expect (const char *platform, 1.140 + const nsCString& fontName, 1.141 + const LiteralArray& glyphs) 1.142 + { 1.143 +#if defined(XP_WIN) 1.144 + if (strcmp(platform, "win32")) 1.145 + return; 1.146 +#elif defined(XP_MACOSX) 1.147 + if (strcmp(platform, "macosx")) 1.148 + return; 1.149 +#elif defined(XP_UNIX) 1.150 + if (strcmp(platform, "gtk2-pango")) 1.151 + return; 1.152 +#else 1.153 + return; 1.154 +#endif 1.155 + 1.156 + expectItems.AppendElement(ExpectItem(fontName, glyphs)); 1.157 + } 1.158 + 1.159 + bool Check (gfxFontTestStore *store) { 1.160 + if (expectItems.Length() == 0 || 1.161 + store->items.Length() != expectItems.Length()) 1.162 + { 1.163 + return false; 1.164 + } 1.165 + 1.166 + for (uint32_t i = 0; i < expectItems.Length(); i++) { 1.167 + if (!expectItems[i].Compare(store->items[i].platformFont, 1.168 + store->items[i].glyphs, 1.169 + store->items[i].num_glyphs)) 1.170 + return false; 1.171 + } 1.172 + 1.173 + return true; 1.174 + } 1.175 + 1.176 + const char *utf8FamilyString; 1.177 + gfxFontStyle fontStyle; 1.178 + 1.179 + int stringType; 1.180 + const char *string; 1.181 + bool isRTL; 1.182 + 1.183 + nsTArray<ExpectItem> expectItems; 1.184 +}; 1.185 + 1.186 +static already_AddRefed<gfxContext> 1.187 +MakeContext () 1.188 +{ 1.189 + const int size = 200; 1.190 + 1.191 + nsRefPtr<gfxASurface> surface; 1.192 + 1.193 + surface = gfxPlatform::GetPlatform()-> 1.194 + CreateOffscreenSurface(IntSize(size, size), 1.195 + gfxASurface::ContentFromFormat(gfxImageFormat::RGB24)); 1.196 + nsRefPtr<gfxContext> ctx = new gfxContext(surface); 1.197 + return ctx.forget(); 1.198 +} 1.199 + 1.200 +TestEntry* 1.201 +AddTest (nsTArray<TestEntry>& testList, 1.202 + const char *utf8FamilyString, 1.203 + const gfxFontStyle& fontStyle, 1.204 + int stringType, 1.205 + const char *string) 1.206 +{ 1.207 + TestEntry te (utf8FamilyString, 1.208 + fontStyle, 1.209 + stringType, 1.210 + string); 1.211 + 1.212 + testList.AppendElement(te); 1.213 + 1.214 + return &(testList[testList.Length()-1]); 1.215 +} 1.216 + 1.217 +void 1.218 +DumpStore (gfxFontTestStore *store) { 1.219 + if (store->items.Length() == 0) { 1.220 + printf ("(empty)\n"); 1.221 + } 1.222 + 1.223 + for (uint32_t i = 0; 1.224 + i < store->items.Length(); 1.225 + i++) 1.226 + { 1.227 + printf ("Run[% 2d]: '%s' ", i, store->items[i].platformFont.BeginReading()); 1.228 + 1.229 + for (int j = 0; j < store->items[i].num_glyphs; j++) 1.230 + printf ("%d ", int(store->items[i].glyphs[j].index)); 1.231 + 1.232 + printf ("\n"); 1.233 + } 1.234 +} 1.235 + 1.236 +void 1.237 +DumpTestExpect (TestEntry *test) { 1.238 + for (uint32_t i = 0; i < test->expectItems.Length(); i++) { 1.239 + printf ("Run[% 2d]: '%s' ", i, test->expectItems[i].fontName.BeginReading()); 1.240 + for (uint32_t j = 0; j < test->expectItems[i].glyphs.data.Length(); j++) 1.241 + printf ("%d ", int(test->expectItems[i].glyphs.data[j])); 1.242 + 1.243 + printf ("\n"); 1.244 + } 1.245 +} 1.246 + 1.247 +void SetupTests(nsTArray<TestEntry>& testList); 1.248 + 1.249 +static bool 1.250 +RunTest (TestEntry *test, gfxContext *ctx) { 1.251 + nsRefPtr<gfxFontGroup> fontGroup; 1.252 + 1.253 + fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->utf8FamilyString), &test->fontStyle, nullptr); 1.254 + 1.255 + nsAutoPtr<gfxTextRun> textRun; 1.256 + gfxTextRunFactory::Parameters params = { 1.257 + ctx, nullptr, nullptr, nullptr, 0, 60 1.258 + }; 1.259 + uint32_t flags = gfxTextRunFactory::TEXT_IS_PERSISTENT; 1.260 + if (test->isRTL) { 1.261 + flags |= gfxTextRunFactory::TEXT_IS_RTL; 1.262 + } 1.263 + uint32_t length; 1.264 + if (test->stringType == S_ASCII) { 1.265 + flags |= gfxTextRunFactory::TEXT_IS_ASCII | gfxTextRunFactory::TEXT_IS_8BIT; 1.266 + length = strlen(test->string); 1.267 + textRun = fontGroup->MakeTextRun(reinterpret_cast<const uint8_t*>(test->string), length, ¶ms, flags); 1.268 + } else { 1.269 + NS_ConvertUTF8toUTF16 str(nsDependentCString(test->string)); 1.270 + length = str.Length(); 1.271 + textRun = fontGroup->MakeTextRun(str.get(), length, ¶ms, flags); 1.272 + } 1.273 + 1.274 + gfxFontTestStore::NewStore(); 1.275 + textRun->Draw(ctx, gfxPoint(0,0), DrawMode::GLYPH_FILL, 0, length, nullptr, nullptr, nullptr); 1.276 + gfxFontTestStore *s = gfxFontTestStore::CurrentStore(); 1.277 + 1.278 + if (!test->Check(s)) { 1.279 + DumpStore(s); 1.280 + printf (" expected:\n"); 1.281 + DumpTestExpect(test); 1.282 + gfxFontTestStore::DeleteStore(); 1.283 + return false; 1.284 + } 1.285 + 1.286 + gfxFontTestStore::DeleteStore(); 1.287 + 1.288 + return true; 1.289 +} 1.290 + 1.291 +TEST(Gfx, FontSelection) { 1.292 + int passed = 0; 1.293 + int failed = 0; 1.294 + 1.295 + // set up the tests 1.296 + nsTArray<TestEntry> testList; 1.297 + SetupTests(testList); 1.298 + 1.299 + nsRefPtr<gfxContext> context = MakeContext(); 1.300 + 1.301 + for (uint32_t test = 0; 1.302 + test < testList.Length(); 1.303 + test++) 1.304 + { 1.305 + bool result = RunTest (&testList[test], context); 1.306 + if (result) { 1.307 + passed++; 1.308 + } else { 1.309 + printf ("Test %d failed\n", test); 1.310 + failed++; 1.311 + } 1.312 + } 1.313 +} 1.314 + 1.315 +// The tests themselves 1.316 + 1.317 +#include "gfxFontSelectionTests.h"