1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "UnscaledFontFreeType.h"
8 #include "NativeFontResourceFreeType.h"
9 #include "ScaledFontFreeType.h"
11 #include "StackArray.h"
13 #include FT_MULTIPLE_MASTERS_H
14 #include FT_TRUETYPE_TABLES_H
19 #include <sys/types.h>
23 namespace mozilla::gfx
{
25 bool UnscaledFontFreeType::GetFontFileData(FontFileDataOutput aDataCallback
,
28 int fd
= open(mFile
.c_str(), O_RDONLY
);
33 if (fstat(fd
, &buf
) < 0 ||
34 // Don't erroneously read directories as files.
35 !S_ISREG(buf
.st_mode
) ||
36 // Verify the file size fits in a uint32_t.
37 buf
.st_size
<= 0 || off_t(uint32_t(buf
.st_size
)) != buf
.st_size
) {
41 uint32_t length
= buf
.st_size
;
42 uint8_t* fontData
= reinterpret_cast<uint8_t*>(
43 mmap(nullptr, length
, PROT_READ
, MAP_PRIVATE
, fd
, 0));
45 if (fontData
== MAP_FAILED
) {
48 aDataCallback(fontData
, length
, mIndex
, aBaton
);
49 munmap(fontData
, length
);
55 // Request the SFNT file. This may not always succeed for all font types.
56 if (FT_Load_Sfnt_Table(mFace
->GetFace(), 0, 0, nullptr, &length
) ==
58 uint8_t* fontData
= new uint8_t[length
];
59 if (FT_Load_Sfnt_Table(mFace
->GetFace(), 0, 0, fontData
, &length
) ==
61 aDataCallback(fontData
, length
, 0, aBaton
);
69 bool UnscaledFontFreeType::GetFontDescriptor(FontDescriptorOutput aCb
,
75 aCb(reinterpret_cast<const uint8_t*>(mFile
.data()), mFile
.size(), mIndex
,
80 RefPtr
<SharedFTFace
> UnscaledFontFreeType::InitFace() {
87 mFace
= Factory::NewSharedFTFace(nullptr, mFile
.c_str(), mIndex
);
89 gfxWarning() << "Failed initializing FreeType face from filename";
95 void UnscaledFontFreeType::GetVariationSettingsFromFace(
96 std::vector
<FontVariation
>* aVariations
, FT_Face aFace
) {
97 if (!aFace
|| !(aFace
->face_flags
& FT_FACE_FLAG_MULTIPLE_MASTERS
)) {
101 typedef FT_Error (*GetVarFunc
)(FT_Face
, FT_MM_Var
**);
102 typedef FT_Error (*DoneVarFunc
)(FT_Library
, FT_MM_Var
*);
103 typedef FT_Error (*GetVarDesignCoordsFunc
)(FT_Face
, FT_UInt
, FT_Fixed
*);
104 #if MOZ_TREE_FREETYPE
105 GetVarFunc getVar
= &FT_Get_MM_Var
;
106 DoneVarFunc doneVar
= &FT_Done_MM_Var
;
107 GetVarDesignCoordsFunc getCoords
= &FT_Get_Var_Design_Coordinates
;
109 static GetVarFunc getVar
;
110 static DoneVarFunc doneVar
;
111 static GetVarDesignCoordsFunc getCoords
;
112 static bool firstTime
= true;
115 getVar
= (GetVarFunc
)dlsym(RTLD_DEFAULT
, "FT_Get_MM_Var");
116 doneVar
= (DoneVarFunc
)dlsym(RTLD_DEFAULT
, "FT_Done_MM_Var");
117 getCoords
= (GetVarDesignCoordsFunc
)dlsym(RTLD_DEFAULT
,
118 "FT_Get_Var_Design_Coordinates");
120 if (!getVar
|| !getCoords
) {
125 FT_MM_Var
* mmVar
= nullptr;
126 if ((*getVar
)(aFace
, &mmVar
) == FT_Err_Ok
) {
127 aVariations
->reserve(mmVar
->num_axis
);
128 StackArray
<FT_Fixed
, 32> coords(mmVar
->num_axis
);
129 if ((*getCoords
)(aFace
, mmVar
->num_axis
, coords
.data()) == FT_Err_Ok
) {
130 bool changed
= false;
131 for (uint32_t i
= 0; i
< mmVar
->num_axis
; i
++) {
132 if (coords
[i
] != mmVar
->axis
[i
].def
) {
135 aVariations
->push_back(FontVariation
{uint32_t(mmVar
->axis
[i
].tag
),
136 float(coords
[i
] / 65536.0)});
139 aVariations
->clear();
143 (*doneVar
)(aFace
->glyph
->library
, mmVar
);
150 void UnscaledFontFreeType::ApplyVariationsToFace(
151 const FontVariation
* aVariations
, uint32_t aNumVariations
, FT_Face aFace
) {
152 if (!aFace
|| !(aFace
->face_flags
& FT_FACE_FLAG_MULTIPLE_MASTERS
)) {
156 typedef FT_Error (*SetVarDesignCoordsFunc
)(FT_Face
, FT_UInt
, FT_Fixed
*);
157 #ifdef MOZ_TREE_FREETYPE
158 SetVarDesignCoordsFunc setCoords
= &FT_Set_Var_Design_Coordinates
;
160 typedef FT_Error (*SetVarDesignCoordsFunc
)(FT_Face
, FT_UInt
, FT_Fixed
*);
161 static SetVarDesignCoordsFunc setCoords
;
162 static bool firstTime
= true;
165 setCoords
= (SetVarDesignCoordsFunc
)dlsym(RTLD_DEFAULT
,
166 "FT_Set_Var_Design_Coordinates");
173 StackArray
<FT_Fixed
, 32> coords(aNumVariations
);
174 for (uint32_t i
= 0; i
< aNumVariations
; i
++) {
175 coords
[i
] = std::round(aVariations
[i
].mValue
* 65536.0f
);
177 if ((*setCoords
)(aFace
, aNumVariations
, coords
.data()) != FT_Err_Ok
) {
178 // ignore the problem?
182 #ifdef MOZ_WIDGET_ANDROID
184 already_AddRefed
<ScaledFont
> UnscaledFontFreeType::CreateScaledFont(
185 Float aGlyphSize
, const uint8_t* aInstanceData
,
186 uint32_t aInstanceDataLength
, const FontVariation
* aVariations
,
187 uint32_t aNumVariations
) {
188 if (aInstanceDataLength
< sizeof(ScaledFontFreeType::InstanceData
)) {
189 gfxWarning() << "FreeType scaled font instance data is truncated.";
192 const ScaledFontFreeType::InstanceData
& instanceData
=
193 *reinterpret_cast<const ScaledFontFreeType::InstanceData
*>(aInstanceData
);
195 RefPtr
<SharedFTFace
> face(InitFace());
197 gfxWarning() << "Attempted to deserialize FreeType scaled font without "
202 if (aNumVariations
> 0 && face
->GetData()) {
203 if (RefPtr
<SharedFTFace
> varFace
= face
->GetData()->CloneFace()) {
208 // Only apply variations if we have an explicitly cloned face.
209 if (aNumVariations
> 0 && face
!= GetFace()) {
210 ApplyVariationsToFace(aVariations
, aNumVariations
, face
->GetFace());
213 RefPtr
<ScaledFontFreeType
> scaledFont
= new ScaledFontFreeType(
214 std::move(face
), this, aGlyphSize
, instanceData
.mApplySyntheticBold
);
216 return scaledFont
.forget();
219 already_AddRefed
<ScaledFont
> UnscaledFontFreeType::CreateScaledFontFromWRFont(
220 Float aGlyphSize
, const wr::FontInstanceOptions
* aOptions
,
221 const wr::FontInstancePlatformOptions
* aPlatformOptions
,
222 const FontVariation
* aVariations
, uint32_t aNumVariations
) {
223 ScaledFontFreeType::InstanceData
instanceData(aOptions
, aPlatformOptions
);
224 return CreateScaledFont(aGlyphSize
, reinterpret_cast<uint8_t*>(&instanceData
),
225 sizeof(instanceData
), aVariations
, aNumVariations
);
228 already_AddRefed
<UnscaledFont
> UnscaledFontFreeType::CreateFromFontDescriptor(
229 const uint8_t* aData
, uint32_t aDataLength
, uint32_t aIndex
) {
230 if (aDataLength
== 0) {
231 gfxWarning() << "FreeType font descriptor is truncated.";
234 const char* path
= reinterpret_cast<const char*>(aData
);
235 RefPtr
<UnscaledFont
> unscaledFont
=
236 new UnscaledFontFreeType(std::string(path
, aDataLength
), aIndex
);
237 return unscaledFont
.forget();
240 #endif // MOZ_WIDGET_ANDROID
242 } // namespace mozilla::gfx