зеркало из https://github.com/mozilla/gecko-dev.git
186 строки
5.3 KiB
C++
186 строки
5.3 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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 "UnscaledFontFreeType.h"
|
|
#include "NativeFontResourceFreeType.h"
|
|
#include "ScaledFontFreeType.h"
|
|
#include "Logging.h"
|
|
#include "StackArray.h"
|
|
|
|
#include FT_MULTIPLE_MASTERS_H
|
|
#include FT_TRUETYPE_TABLES_H
|
|
|
|
#include <dlfcn.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
|
|
namespace mozilla {
|
|
namespace gfx {
|
|
|
|
bool
|
|
UnscaledFontFreeType::GetFontFileData(FontFileDataOutput aDataCallback, void* aBaton)
|
|
{
|
|
if (!mFile.empty()) {
|
|
int fd = open(mFile.c_str(), O_RDONLY);
|
|
if (fd < 0) {
|
|
return false;
|
|
}
|
|
struct stat buf;
|
|
if (fstat(fd, &buf) < 0 ||
|
|
// Don't erroneously read directories as files.
|
|
!S_ISREG(buf.st_mode) ||
|
|
// Verify the file size fits in a uint32_t.
|
|
buf.st_size <= 0 ||
|
|
off_t(uint32_t(buf.st_size)) != buf.st_size) {
|
|
close(fd);
|
|
return false;
|
|
}
|
|
uint32_t length = buf.st_size;
|
|
uint8_t* fontData =
|
|
reinterpret_cast<uint8_t*>(
|
|
mmap(nullptr, length, PROT_READ, MAP_PRIVATE, fd, 0));
|
|
close(fd);
|
|
if (fontData == MAP_FAILED) {
|
|
return false;
|
|
}
|
|
aDataCallback(fontData, length, mIndex, aBaton);
|
|
munmap(fontData, length);
|
|
return true;
|
|
}
|
|
|
|
bool success = false;
|
|
FT_ULong length = 0;
|
|
// Request the SFNT file. This may not always succeed for all font types.
|
|
if (FT_Load_Sfnt_Table(mFace, 0, 0, nullptr, &length) == FT_Err_Ok) {
|
|
uint8_t* fontData = new uint8_t[length];
|
|
if (FT_Load_Sfnt_Table(mFace, 0, 0, fontData, &length) == FT_Err_Ok) {
|
|
aDataCallback(fontData, length, 0, aBaton);
|
|
success = true;
|
|
}
|
|
delete[] fontData;
|
|
}
|
|
return success;
|
|
}
|
|
|
|
bool
|
|
UnscaledFontFreeType::GetFontDescriptor(FontDescriptorOutput aCb, void* aBaton)
|
|
{
|
|
if (mFile.empty()) {
|
|
return false;
|
|
}
|
|
|
|
aCb(reinterpret_cast<const uint8_t*>(mFile.data()), mFile.size(), mIndex, aBaton);
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
UnscaledFontFreeType::GetWRFontDescriptor(WRFontDescriptorOutput aCb, void* aBaton)
|
|
{
|
|
if (mFile.empty()) {
|
|
return false;
|
|
}
|
|
|
|
aCb(reinterpret_cast<const uint8_t*>(mFile.data()), mFile.size(), mIndex, aBaton);
|
|
return true;
|
|
}
|
|
|
|
void
|
|
UnscaledFontFreeType::GetVariationSettingsFromFace(std::vector<FontVariation>* aVariations,
|
|
FT_Face aFace)
|
|
{
|
|
if (!aFace || !(aFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
|
|
return;
|
|
}
|
|
|
|
typedef FT_Error (*GetVarFunc)(FT_Face, FT_MM_Var**);
|
|
typedef FT_Error (*DoneVarFunc)(FT_Library, FT_MM_Var*);
|
|
typedef FT_Error (*GetVarDesignCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
|
#if MOZ_TREE_FREETYPE
|
|
GetVarFunc getVar = &FT_Get_MM_Var;
|
|
DoneVarFunc doneVar = &FT_Done_MM_Var;
|
|
GetVarDesignCoordsFunc getCoords = &FT_Get_Var_Design_Coordinates;
|
|
#else
|
|
static GetVarFunc getVar;
|
|
static DoneVarFunc doneVar;
|
|
static GetVarDesignCoordsFunc getCoords;
|
|
static bool firstTime = true;
|
|
if (firstTime) {
|
|
firstTime = false;
|
|
getVar = (GetVarFunc)dlsym(RTLD_DEFAULT, "FT_Get_MM_Var");
|
|
doneVar = (DoneVarFunc)dlsym(RTLD_DEFAULT, "FT_Done_MM_Var");
|
|
getCoords = (GetVarDesignCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Get_Var_Design_Coordinates");
|
|
}
|
|
if (!getVar || !getCoords) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
FT_MM_Var* mmVar = nullptr;
|
|
if ((*getVar)(aFace, &mmVar) == FT_Err_Ok) {
|
|
aVariations->reserve(mmVar->num_axis);
|
|
StackArray<FT_Fixed, 32> coords(mmVar->num_axis);
|
|
if ((*getCoords)(aFace, mmVar->num_axis, coords.data()) == FT_Err_Ok) {
|
|
bool changed = false;
|
|
for (uint32_t i = 0; i < mmVar->num_axis; i++) {
|
|
if (coords[i] != mmVar->axis[i].def) {
|
|
changed = true;
|
|
}
|
|
aVariations->push_back(FontVariation{uint32_t(mmVar->axis[i].tag),
|
|
float(coords[i] / 65536.0)});
|
|
}
|
|
if (!changed) {
|
|
aVariations->clear();
|
|
}
|
|
}
|
|
if (doneVar) {
|
|
(*doneVar)(aFace->glyph->library, mmVar);
|
|
} else {
|
|
free(mmVar);
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
UnscaledFontFreeType::ApplyVariationsToFace(const FontVariation* aVariations,
|
|
uint32_t aNumVariations,
|
|
FT_Face aFace)
|
|
{
|
|
if (!aFace || !(aFace->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS)) {
|
|
return;
|
|
}
|
|
|
|
typedef FT_Error (*SetVarDesignCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
|
#ifdef MOZ_TREE_FREETYPE
|
|
SetVarDesignCoordsFunc setCoords = &FT_Set_Var_Design_Coordinates;
|
|
#else
|
|
typedef FT_Error (*SetVarDesignCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
|
|
static SetVarDesignCoordsFunc setCoords;
|
|
static bool firstTime = true;
|
|
if (firstTime) {
|
|
firstTime = false;
|
|
setCoords = (SetVarDesignCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Set_Var_Design_Coordinates");
|
|
}
|
|
if (!setCoords) {
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
StackArray<FT_Fixed, 32> coords(aNumVariations);
|
|
for (uint32_t i = 0; i < aNumVariations; i++) {
|
|
coords[i] = std::round(aVariations[i].mValue * 65536.0f);
|
|
}
|
|
if ((*setCoords)(aFace, aNumVariations, coords.data()) != FT_Err_Ok) {
|
|
// ignore the problem?
|
|
}
|
|
}
|
|
|
|
} // namespace gfx
|
|
} // namespace mozilla
|
|
|