/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef SkDWrite_DEFINED
#define SkDWrite_DEFINED

#include "SkFontStyle.h"
#include "SkTemplates.h"

#include <dwrite.h>
#include <winsdkver.h>

class SkString;

////////////////////////////////////////////////////////////////////////////////
// Factory

IDWriteFactory* sk_get_dwrite_factory();

////////////////////////////////////////////////////////////////////////////////
// String conversion

/** Prefer to use this type to prevent template proliferation. */
typedef SkAutoSTMalloc<16, WCHAR> SkSMallocWCHAR;

/** Converts a utf8 string to a WCHAR string. */
HRESULT sk_cstring_to_wchar(const char* skname, SkSMallocWCHAR* name);

/** Converts a WCHAR string to a utf8 string.
 *  @param nameLen the number of WCHARs in the name.
 */
HRESULT sk_wchar_to_skstring(WCHAR* name, int nameLen, SkString* skname);

////////////////////////////////////////////////////////////////////////////////
// Locale

HRESULT sk_get_locale_string(IDWriteLocalizedStrings* names, const WCHAR* preferedLocale,
                             SkString* skname);

typedef int (WINAPI *SkGetUserDefaultLocaleNameProc)(LPWSTR, int);
HRESULT SkGetGetUserDefaultLocaleNameProc(SkGetUserDefaultLocaleNameProc* proc);

////////////////////////////////////////////////////////////////////////////////
// Table handling

class AutoDWriteTable {
public:
    AutoDWriteTable(IDWriteFontFace* fontFace, UINT32 beTag) : fExists(FALSE), fFontFace(fontFace) {
        // Any errors are ignored, user must check fExists anyway.
        fontFace->TryGetFontTable(beTag,
            reinterpret_cast<const void **>(&fData), &fSize, &fLock, &fExists);
    }
    ~AutoDWriteTable() {
        if (fExists) {
            fFontFace->ReleaseFontTable(fLock);
        }
    }

    const uint8_t* fData;
    UINT32 fSize;
    BOOL fExists;
private:
    // Borrowed reference, the user must ensure the fontFace stays alive.
    IDWriteFontFace* fFontFace;
    void* fLock;
};
template<typename T> class AutoTDWriteTable : public AutoDWriteTable {
public:
    static const UINT32 tag = DWRITE_MAKE_OPENTYPE_TAG(T::TAG0, T::TAG1, T::TAG2, T::TAG3);
    AutoTDWriteTable(IDWriteFontFace* fontFace) : AutoDWriteTable(fontFace, tag) { }

    const T* get() const { return reinterpret_cast<const T*>(fData); }
    const T* operator->() const { return reinterpret_cast<const T*>(fData); }
};

////////////////////////////////////////////////////////////////////////////////
// Style conversion

struct DWriteStyle {
    explicit DWriteStyle(const SkFontStyle& pattern) {
        fWeight = (DWRITE_FONT_WEIGHT)pattern.weight();
        fWidth = (DWRITE_FONT_STRETCH)pattern.width();
        switch (pattern.slant()) {
            case SkFontStyle::kUpright_Slant: fSlant = DWRITE_FONT_STYLE_NORMAL ; break;
            case SkFontStyle::kItalic_Slant:  fSlant = DWRITE_FONT_STYLE_ITALIC ; break;
            case SkFontStyle::kOblique_Slant: fSlant = DWRITE_FONT_STYLE_OBLIQUE; break;
            default: SkASSERT(false); break;
        }
    }
    DWRITE_FONT_WEIGHT fWeight;
    DWRITE_FONT_STRETCH fWidth;
    DWRITE_FONT_STYLE fSlant;
};

#endif
