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#ifndef SkTypeface_win_dw_DEFINED
9#define SkTypeface_win_dw_DEFINED
10
11#include "SkAdvancedTypefaceMetrics.h"
12#include "SkDWrite.h"
13#include "SkHRESULT.h"
14#include "SkLeanWindows.h"
15#include "SkTScopedComPtr.h"
16#include "SkTypeface.h"
17#include "SkTypefaceCache.h"
18
19#include <dwrite.h>
20#include <dwrite_1.h>
21#include <dwrite_2.h>
22
23class SkFontDescriptor;
24struct SkScalerContextRec;
25
26static SkFontStyle get_style(IDWriteFont* font) {
27    int weight = font->GetWeight();
28    int width = font->GetStretch();
29    SkFontStyle::Slant slant = SkFontStyle::kUpright_Slant;
30    switch (font->GetStyle()) {
31        case DWRITE_FONT_STYLE_NORMAL: slant = SkFontStyle::kUpright_Slant; break;
32        case DWRITE_FONT_STYLE_OBLIQUE: slant = SkFontStyle::kOblique_Slant; break;
33        case DWRITE_FONT_STYLE_ITALIC: slant = SkFontStyle::kItalic_Slant; break;
34        default: SkASSERT(false); break;
35    }
36    return SkFontStyle(weight, width, slant);
37}
38
39class DWriteFontTypeface : public SkTypeface {
40private:
41    DWriteFontTypeface(const SkFontStyle& style,
42                       IDWriteFactory* factory,
43                       IDWriteFontFace* fontFace,
44                       IDWriteFont* font,
45                       IDWriteFontFamily* fontFamily,
46                       IDWriteFontFileLoader* fontFileLoader = nullptr,
47                       IDWriteFontCollectionLoader* fontCollectionLoader = nullptr)
48        : SkTypeface(style, false)
49        , fFactory(SkRefComPtr(factory))
50        , fDWriteFontCollectionLoader(SkSafeRefComPtr(fontCollectionLoader))
51        , fDWriteFontFileLoader(SkSafeRefComPtr(fontFileLoader))
52        , fDWriteFontFamily(SkRefComPtr(fontFamily))
53        , fDWriteFont(SkRefComPtr(font))
54        , fDWriteFontFace(SkRefComPtr(fontFace))
55    {
56        if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace1))) {
57            // IUnknown::QueryInterface states that if it fails, punk will be set to nullptr.
58            // http://blogs.msdn.com/b/oldnewthing/archive/2004/03/26/96777.aspx
59            SkASSERT_RELEASE(nullptr == fDWriteFontFace1.get());
60        }
61        if (!SUCCEEDED(fDWriteFontFace->QueryInterface(&fDWriteFontFace2))) {
62            SkASSERT_RELEASE(nullptr == fDWriteFontFace2.get());
63        }
64        if (!SUCCEEDED(fFactory->QueryInterface(&fFactory2))) {
65            SkASSERT_RELEASE(nullptr == fFactory2.get());
66        }
67    }
68
69public:
70    SkTScopedComPtr<IDWriteFactory> fFactory;
71    SkTScopedComPtr<IDWriteFactory2> fFactory2;
72    SkTScopedComPtr<IDWriteFontCollectionLoader> fDWriteFontCollectionLoader;
73    SkTScopedComPtr<IDWriteFontFileLoader> fDWriteFontFileLoader;
74    SkTScopedComPtr<IDWriteFontFamily> fDWriteFontFamily;
75    SkTScopedComPtr<IDWriteFont> fDWriteFont;
76    SkTScopedComPtr<IDWriteFontFace> fDWriteFontFace;
77    SkTScopedComPtr<IDWriteFontFace1> fDWriteFontFace1;
78    SkTScopedComPtr<IDWriteFontFace2> fDWriteFontFace2;
79
80    static DWriteFontTypeface* Create(IDWriteFactory* factory,
81                                      IDWriteFontFace* fontFace,
82                                      IDWriteFont* font,
83                                      IDWriteFontFamily* fontFamily,
84                                      IDWriteFontFileLoader* fontFileLoader = nullptr,
85                                      IDWriteFontCollectionLoader* fontCollectionLoader = nullptr) {
86        return new DWriteFontTypeface(get_style(font), factory, fontFace, font, fontFamily,
87                                      fontFileLoader, fontCollectionLoader);
88    }
89
90protected:
91    void weak_dispose() const override {
92        if (fDWriteFontCollectionLoader.get()) {
93            HRV(fFactory->UnregisterFontCollectionLoader(fDWriteFontCollectionLoader.get()));
94        }
95        if (fDWriteFontFileLoader.get()) {
96            HRV(fFactory->UnregisterFontFileLoader(fDWriteFontFileLoader.get()));
97        }
98
99        //SkTypefaceCache::Remove(this);
100        INHERITED::weak_dispose();
101    }
102
103    SkStreamAsset* onOpenStream(int* ttcIndex) const override;
104    SkScalerContext* onCreateScalerContext(const SkScalerContextEffects&,
105                                           const SkDescriptor*) const override;
106    void onFilterRec(SkScalerContextRec*) const override;
107    std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;
108    void onGetFontDescriptor(SkFontDescriptor*, bool*) const override;
109    int onCharsToGlyphs(const void* chars, Encoding encoding,
110                        uint16_t glyphs[], int glyphCount) const override;
111    int onCountGlyphs() const override;
112    int onGetUPEM() const override;
113    void onGetFamilyName(SkString* familyName) const override;
114    SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;
115    int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate coordinates[],
116                                     int coordinateCount) const override
117    {
118        return -1;
119    }
120    int onGetTableTags(SkFontTableTag tags[]) const override;
121    size_t onGetTableData(SkFontTableTag, size_t offset, size_t length, void* data) const override;
122
123private:
124    typedef SkTypeface INHERITED;
125};
126
127#endif
128