1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "include/core/SkBitmap.h"
9#include "include/core/SkCanvas.h"
10#include "include/core/SkFont.h"
11#include "include/core/SkFontMgr.h"
12#include "include/core/SkTypeface.h"
13#include "include/ports/SkFontMgr_fontconfig.h"
14#include "tests/Test.h"
15#include "tools/Resources.h"
16
17#include <fontconfig/fontconfig.h>
18
19static bool bitmap_compare(const SkBitmap& ref, const SkBitmap& test) {
20    for (int y = 0; y < test.height(); ++y) {
21        for (int x = 0; x < test.width(); ++x) {
22            SkColor testColor = test.getColor(x, y);
23            SkColor refColor = ref.getColor(x, y);
24            if (refColor != testColor) {
25                return false;
26            }
27        }
28    }
29    return true;
30}
31
32DEF_TEST(FontMgrFontConfig, reporter) {
33    FcConfig* config = FcConfigCreate();
34
35    // FontConfig may modify the passed path (make absolute or other).
36    FcConfigSetSysRoot(config, reinterpret_cast<const FcChar8*>(GetResourcePath("").c_str()));
37    // FontConfig will lexically compare paths against its version of the sysroot.
38    SkString distortablePath(reinterpret_cast<const char*>(FcConfigGetSysRoot(config)));
39    distortablePath += "/fonts/Distortable.ttf";
40    FcConfigAppFontAddFile(config, reinterpret_cast<const FcChar8*>(distortablePath.c_str()));
41
42    FcConfigBuildFonts(config);
43
44    sk_sp<SkFontMgr> fontMgr(SkFontMgr_New_FontConfig(config));
45    sk_sp<SkTypeface> typeface(fontMgr->legacyMakeTypeface("Distortable", SkFontStyle()));
46    if (!typeface) {
47        ERRORF(reporter, "Could not find typeface. FcVersion: %d", FcGetVersion());
48        return;
49    }
50
51    SkBitmap bitmapStream;
52    bitmapStream.allocN32Pixels(64, 64);
53    SkCanvas canvasStream(bitmapStream);
54    canvasStream.drawColor(SK_ColorWHITE);
55
56    SkBitmap bitmapClone;
57    bitmapClone.allocN32Pixels(64, 64);
58    SkCanvas canvasClone(bitmapClone);
59    canvasStream.drawColor(SK_ColorWHITE);
60
61    SkPaint paint;
62    paint.setColor(SK_ColorGRAY);
63
64    constexpr float kTextSize = 20;
65
66    std::unique_ptr<SkStreamAsset> distortableStream(
67        GetResourceAsStream("fonts/Distortable.ttf"));
68    if (!distortableStream) {
69        return;
70    }
71
72    SkPoint point = SkPoint::Make(20.0f, 20.0f);
73    SkFourByteTag tag = SkSetFourByteTag('w', 'g', 'h', 't');
74
75    for (int i = 0; i < 10; ++i) {
76        SkScalar styleValue =
77            SkDoubleToScalar(0.5 + i * ((2.0 - 0.5) / 10));
78        SkFontArguments::VariationPosition::Coordinate
79            coordinates[] = {{tag, styleValue}};
80        SkFontArguments::VariationPosition
81            position = {coordinates, SK_ARRAY_COUNT(coordinates)};
82
83        SkFont fontStream(
84            fontMgr->makeFromStream(distortableStream->duplicate(),
85                                    SkFontArguments().setVariationDesignPosition(position)),
86            kTextSize);
87        fontStream.setEdging(SkFont::Edging::kSubpixelAntiAlias);
88
89        SkFont fontClone(
90            typeface->makeClone(SkFontArguments().setVariationDesignPosition(position)), kTextSize);
91        fontClone.setEdging(SkFont::Edging::kSubpixelAntiAlias);
92
93        constexpr char text[] = "abc";
94
95        canvasStream.drawColor(SK_ColorWHITE);
96        canvasStream.drawString(text, point.fX, point.fY, fontStream, paint);
97
98        canvasClone.drawColor(SK_ColorWHITE);
99        canvasClone.drawString(text, point.fX, point.fY, fontClone, paint);
100
101        bool success = bitmap_compare(bitmapStream, bitmapClone);
102        REPORTER_ASSERT(reporter, success);
103    }
104}
105