DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Header

Mercurial (c291143e2401)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "gfxFT2FontBase.h"
#include "gfxFT2Utils.h"
#include "mozilla/Likely.h"

#ifdef HAVE_FONTCONFIG_FCFREETYPE_H
#include <fontconfig/fcfreetype.h>
#endif

#include "ft2build.h"
#include FT_MULTIPLE_MASTERS_H

#include "prlink.h"

uint32_t
gfxFT2LockedFace::GetGlyph(uint32_t aCharCode)
{
    if (MOZ_UNLIKELY(!mFace))
        return 0;

#ifdef HAVE_FONTCONFIG_FCFREETYPE_H
    // FcFreeTypeCharIndex will search starting from the most recently
    // selected charmap.  This can cause non-determistic behavior when more
    // than one charmap supports a character but with different glyphs, as
    // with older versions of MS Gothic, for example.  Always prefer a Unicode
    // charmap, if there is one.  (FcFreeTypeCharIndex usually does the
    // appropriate Unicode conversion, but some fonts have non-Roman glyphs
    // for FT_ENCODING_APPLE_ROMAN characters.)
    if (!mFace->charmap || mFace->charmap->encoding != FT_ENCODING_UNICODE) {
        FT_Select_Charmap(mFace, FT_ENCODING_UNICODE);
    }

    return FcFreeTypeCharIndex(mFace, aCharCode);
#else
    return FT_Get_Char_Index(mFace, aCharCode);
#endif
}

typedef FT_UInt (*GetCharVariantFunction)(FT_Face  face,
                                          FT_ULong charcode,
                                          FT_ULong variantSelector);

uint32_t
gfxFT2LockedFace::GetUVSGlyph(uint32_t aCharCode, uint32_t aVariantSelector)
{
    MOZ_ASSERT(aVariantSelector, "aVariantSelector should not be NULL");

    if (MOZ_UNLIKELY(!mFace))
        return 0;

    // This function is available from FreeType 2.3.6 (June 2008).
    static CharVariantFunction sGetCharVariantPtr = FindCharVariantFunction();
    if (!sGetCharVariantPtr)
        return 0;

#ifdef HAVE_FONTCONFIG_FCFREETYPE_H
    // FcFreeTypeCharIndex may have changed the selected charmap.
    // FT_Face_GetCharVariantIndex needs a unicode charmap.
    if (!mFace->charmap || mFace->charmap->encoding != FT_ENCODING_UNICODE) {
        FT_Select_Charmap(mFace, FT_ENCODING_UNICODE);
    }
#endif

    return (*sGetCharVariantPtr)(mFace, aCharCode, aVariantSelector);
}

gfxFT2LockedFace::CharVariantFunction
gfxFT2LockedFace::FindCharVariantFunction()
{
    // This function is available from FreeType 2.3.6 (June 2008).
    PRLibrary *lib = nullptr;
    CharVariantFunction function =
        reinterpret_cast<CharVariantFunction>
        (PR_FindFunctionSymbolAndLibrary("FT_Face_GetCharVariantIndex", &lib));
    if (!lib) {
        return nullptr;
    }

    FT_Int major;
    FT_Int minor;
    FT_Int patch;
    FT_Library_Version(mFace->glyph->library, &major, &minor, &patch);

    // Versions 2.4.0 to 2.4.3 crash if configured with
    // FT_CONFIG_OPTION_OLD_INTERNALS.  Presence of the symbol FT_Alloc
    // indicates FT_CONFIG_OPTION_OLD_INTERNALS.
    if (major == 2 && minor == 4 && patch < 4 &&
        PR_FindFunctionSymbol(lib, "FT_Alloc")) {
        function = nullptr;
    }

    // Decrement the reference count incremented in
    // PR_FindFunctionSymbolAndLibrary.
    PR_UnloadLibrary(lib);

    return function;
}

/*static*/
void
gfxFT2Utils::GetVariationAxes(const FT_MM_Var* aMMVar,
                              nsTArray<gfxFontVariationAxis>& aAxes)
{
    MOZ_ASSERT(aAxes.IsEmpty());
    if (!aMMVar) {
        return;
    }
    aAxes.SetCapacity(aMMVar->num_axis);
    for (unsigned i = 0; i < aMMVar->num_axis; i++) {
        const auto& a = aMMVar->axis[i];
        gfxFontVariationAxis axis;
        axis.mMinValue = a.minimum / 65536.0;
        axis.mMaxValue = a.maximum / 65536.0;
        axis.mDefaultValue = a.def / 65536.0;
        axis.mTag = a.tag;
        axis.mName = a.name;
        aAxes.AppendElement(axis);
    }
}

/*static*/
void
gfxFT2Utils::GetVariationInstances(
    gfxFontEntry* aFontEntry,
    const FT_MM_Var* aMMVar,
    nsTArray<gfxFontVariationInstance>& aInstances)
{
    MOZ_ASSERT(aInstances.IsEmpty());
    if (!aMMVar) {
        return;
    }
    hb_blob_t* nameTable =
        aFontEntry->GetFontTable(TRUETYPE_TAG('n','a','m','e'));
    if (!nameTable) {
        return;
    }
    aInstances.SetCapacity(aMMVar->num_namedstyles);
    for (unsigned i = 0; i < aMMVar->num_namedstyles; i++) {
        const auto& ns = aMMVar->namedstyle[i];
        gfxFontVariationInstance inst;
        nsresult rv =
            gfxFontUtils::ReadCanonicalName(nameTable, ns.strid, inst.mName);
        if (NS_FAILED(rv)) {
            continue;
        }
        inst.mValues.SetCapacity(aMMVar->num_axis);
        for (unsigned j = 0; j < aMMVar->num_axis; j++) {
            gfxFontVariationValue value;
            value.mAxis = aMMVar->axis[j].tag;
            value.mValue = ns.coords[j] / 65536.0;
            inst.mValues.AppendElement(value);
        }
        aInstances.AppendElement(inst);
    }
    hb_blob_destroy(nameTable);
}