Flutter Engine
The Flutter Engine
Public Member Functions | Static Public Member Functions | List of all members
SkFontScanner_FreeType Class Reference

#include <SkTypeface_FreeType.h>

Inheritance diagram for SkFontScanner_FreeType:
SkFontScanner SkNoncopyable

Public Member Functions

 SkFontScanner_FreeType ()
 
 ~SkFontScanner_FreeType () override
 
bool scanFile (SkStreamAsset *stream, int *numFaces) const override
 
bool scanFace (SkStreamAsset *stream, int faceIndex, int *numInstances) const override
 
bool scanInstance (SkStreamAsset *stream, int faceIndex, int instanceIndex, SkString *name, SkFontStyle *style, bool *isFixedPitch, AxisDefinitions *axes) const override
 
- Public Member Functions inherited from SkFontScanner
virtual ~SkFontScanner ()=default
 
virtual bool scanFile (SkStreamAsset *stream, int *numFaces) const =0
 
virtual bool scanFace (SkStreamAsset *stream, int faceIndex, int *numInstances) const =0
 
virtual bool scanInstance (SkStreamAsset *stream, int faceIndex, int instanceIndex, SkString *name, SkFontStyle *style, bool *isFixedPitch, AxisDefinitions *axes) const =0
 
- Public Member Functions inherited from SkNoncopyable
 SkNoncopyable ()=default
 
 SkNoncopyable (SkNoncopyable &&)=default
 
SkNoncopyableoperator= (SkNoncopyable &&)=default
 

Static Public Member Functions

static void computeAxisValues (AxisDefinitions axisDefinitions, const SkFontArguments::VariationPosition position, SkFixed *axisValues, const SkString &name, SkFontStyle *style, const SkFontArguments::VariationPosition::Coordinate *currentPosition=nullptr)
 
static bool GetAxes (FT_Face face, AxisDefinitions *axes)
 

Additional Inherited Members

- Public Types inherited from SkFontScanner
typedef skia_private::STArray< 4, AxisDefinition, trueAxisDefinitions
 

Detailed Description

Definition at line 110 of file SkTypeface_FreeType.h.

Constructor & Destructor Documentation

◆ SkFontScanner_FreeType()

SkFontScanner_FreeType::SkFontScanner_FreeType ( )

Definition at line 2022 of file SkFontHost_FreeType.cpp.

2022 : fLibrary(nullptr) {
2023 if (FT_New_Library(&gFTMemory, &fLibrary)) {
2024 return;
2025 }
2026 FT_Add_Default_Modules(fLibrary);
2027 FT_Set_Default_Properties(fLibrary);
2028}
FT_MemoryRec_ gFTMemory

◆ ~SkFontScanner_FreeType()

SkFontScanner_FreeType::~SkFontScanner_FreeType ( )
override

Definition at line 2030 of file SkFontHost_FreeType.cpp.

2030 {
2031 if (fLibrary) {
2032 FT_Done_Library(fLibrary);
2033 }
2034}

Member Function Documentation

◆ computeAxisValues()

void SkFontScanner_FreeType::computeAxisValues ( AxisDefinitions  axisDefinitions,
const SkFontArguments::VariationPosition  position,
SkFixed axisValues,
const SkString name,
SkFontStyle style,
const SkFontArguments::VariationPosition::Coordinate currentPosition = nullptr 
)
static

Definition at line 2277 of file SkFontHost_FreeType.cpp.

2284{
2285 static constexpr SkFourByteTag wghtTag = SkSetFourByteTag('w', 'g', 'h', 't');
2286 static constexpr SkFourByteTag wdthTag = SkSetFourByteTag('w', 'd', 't', 'h');
2287 static constexpr SkFourByteTag slntTag = SkSetFourByteTag('s', 'l', 'n', 't');
2288 int weight = SkFontStyle::kNormal_Weight;
2291 if (style) {
2292 weight = style->weight();
2293 width = style->width();
2294 slant = style->slant();
2295 }
2296
2297 for (int i = 0; i < axisDefinitions.size(); ++i) {
2298 const AxisDefinition& axisDefinition = axisDefinitions[i];
2299 const SkScalar axisMin = axisDefinition.fMinimum;
2300 const SkScalar axisMax = axisDefinition.fMaximum;
2301
2302 // Start with the default value.
2303 axisValues[i] = SkScalarToFixed(axisDefinition.fDefault);
2304
2305 // Then the current value.
2306 if (current) {
2307 for (int j = 0; j < axisDefinitions.size(); ++j) {
2308 const auto& coordinate = current[j];
2309 if (axisDefinition.fTag == coordinate.axis) {
2310 const SkScalar axisValue = SkTPin(coordinate.value, axisMin, axisMax);
2311 axisValues[i] = SkScalarToFixed(axisValue);
2312 break;
2313 }
2314 }
2315 }
2316
2317 // Then the requested value.
2318 // The position may be over specified. If there are multiple values for a given axis,
2319 // use the last one since that's what css-fonts-4 requires.
2320 for (int j = position.coordinateCount; j --> 0;) {
2321 const auto& coordinate = position.coordinates[j];
2322 if (axisDefinition.fTag == coordinate.axis) {
2323 const SkScalar axisValue = SkTPin(coordinate.value, axisMin, axisMax);
2324 if (coordinate.value != axisValue) {
2325 LOG_INFO("Requested font axis value out of range: "
2326 "%s '%c%c%c%c' %f; pinned to %f.\n",
2327 name.c_str(),
2328 (axisDefinition.fTag >> 24) & 0xFF,
2329 (axisDefinition.fTag >> 16) & 0xFF,
2330 (axisDefinition.fTag >> 8) & 0xFF,
2331 (axisDefinition.fTag ) & 0xFF,
2332 SkScalarToDouble(coordinate.value),
2333 SkScalarToDouble(axisValue));
2334 }
2335 axisValues[i] = SkScalarToFixed(axisValue);
2336 break;
2337 }
2338 }
2339
2340 if (style) {
2341 if (axisDefinition.fTag == wghtTag) {
2342 // Rough validity check, is there sufficient spread and are ranges within 0-1000.
2343 SkScalar wghtRange = axisMax - axisMin;
2344 if (wghtRange > 5 && wghtRange <= 1000 && axisMax <= 1000) {
2345 weight = SkFixedRoundToInt(axisValues[i]);
2346 }
2347 }
2348 if (axisDefinition.fTag == wdthTag) {
2349 // Rough validity check, is there a spread and are ranges within 0-500.
2350 SkScalar wdthRange = axisMax - axisMin;
2351 if (wdthRange > 0 && wdthRange <= 500 && axisMax <= 500) {
2352 SkScalar wdthValue = SkFixedToScalar(axisValues[i]);
2354 }
2355 }
2356 if (axisDefinition.fTag == slntTag && slant != SkFontStyle::kItalic_Slant) {
2357 // https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_slnt
2358 // "Scale interpretation: Values can be interpreted as the angle,
2359 // in counter-clockwise degrees, of oblique slant from whatever
2360 // the designer considers to be upright for that font design."
2361 if (axisValues[i] == 0) {
2363 } else {
2365 }
2366 }
2367 }
2368 // TODO: warn on defaulted axis?
2369 }
2370
2371 if (style) {
2372 *style = SkFontStyle(weight, width, slant);
2373 }
2374
2376 // Check for axis specified, but not matched in font.
2377 for (int i = 0; i < position.coordinateCount; ++i) {
2378 SkFourByteTag skTag = position.coordinates[i].axis;
2379 bool found = false;
2380 for (int j = 0; j < axisDefinitions.size(); ++j) {
2381 if (skTag == axisDefinitions[j].fTag) {
2382 found = true;
2383 break;
2384 }
2385 }
2386 if (!found) {
2387 LOG_INFO("Requested font axis not found: %s '%c%c%c%c'\n",
2388 name.c_str(),
2389 (skTag >> 24) & 0xFF,
2390 (skTag >> 16) & 0xFF,
2391 (skTag >> 8) & 0xFF,
2392 (skTag) & 0xFF);
2393 }
2394 }
2395 )
2396}
#define SkScalarToFixed(x)
Definition: SkFixed.h:125
#define SkFixedToScalar(x)
Definition: SkFixed.h:124
#define SkFixedRoundToInt(x)
Definition: SkFixed.h:76
#define LOG_INFO(...)
#define SkScalarToDouble(x)
Definition: SkScalar.h:63
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition: SkTPin.h:19
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
uint32_t SkFourByteTag
Definition: SkTypes.h:166
static constexpr SkFourByteTag SkSetFourByteTag(char a, char b, char c, char d)
Definition: SkTypes.h:167
static SkFontStyle::Width SkFontStyleWidthForWidthAxisValue(SkScalar width)
Slant slant() const
Definition: SkFontStyle.h:64
int width() const
Definition: SkFontStyle.h:63
int weight() const
Definition: SkFontStyle.h:62
float SkScalar
Definition: extension.cpp:12
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
int32_t width

◆ GetAxes()

bool SkFontScanner_FreeType::GetAxes ( FT_Face  face,
AxisDefinitions axes 
)
static

Definition at line 2253 of file SkFontHost_FreeType.cpp.

2253 {
2254 SkASSERT(face && axes);
2255 if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS) {
2256 FT_MM_Var* variations = nullptr;
2257 FT_Error err = FT_Get_MM_Var(face, &variations);
2258 if (err) {
2259 LOG_INFO("INFO: font %s claims to have variations, but none found.\n",
2260 face->family_name);
2261 return false;
2262 }
2263 UniqueVoidPtr autoFreeVariations(variations);
2264
2265 axes->reset(variations->num_axis);
2266 for (FT_UInt i = 0; i < variations->num_axis; ++i) {
2267 const FT_Var_Axis& ftAxis = variations->axis[i];
2268 (*axes)[i].fTag = ftAxis.tag;
2269 (*axes)[i].fMinimum = SkFT_FixedToScalar(ftAxis.minimum);
2270 (*axes)[i].fDefault = SkFT_FixedToScalar(ftAxis.def);
2271 (*axes)[i].fMaximum = SkFT_FixedToScalar(ftAxis.maximum);
2272 }
2273 }
2274 return true;
2275}
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkScalar SkFT_FixedToScalar(FT_Fixed x)
std::unique_ptr< void, SkOverloadedFunctionObject< void(void *), sk_free > > UniqueVoidPtr
Definition: SkTemplates.h:431

◆ scanFace()

bool SkFontScanner_FreeType::scanFace ( SkStreamAsset stream,
int  faceIndex,
int numInstances 
) const
overridevirtual

Implements SkFontScanner.

Definition at line 2083 of file SkFontHost_FreeType.cpp.

2085 {
2086 SkAutoMutexExclusive libraryLock(fLibraryMutex);
2087
2088 FT_StreamRec streamRec;
2089 SkUniqueFTFace face(this->openFace(stream, -(faceIndex + 1), &streamRec));
2090 if (!face) {
2091 return false;
2092 }
2093
2094 *numInstances = face->style_flags >> 16;
2095 return true;
2096}

◆ scanFile()

bool SkFontScanner_FreeType::scanFile ( SkStreamAsset stream,
int numFaces 
) const
overridevirtual

Implements SkFontScanner.

Definition at line 2070 of file SkFontHost_FreeType.cpp.

2070 {
2071 SkAutoMutexExclusive libraryLock(fLibraryMutex);
2072
2073 FT_StreamRec streamRec;
2074 SkUniqueFTFace face(this->openFace(stream, -1, &streamRec));
2075 if (!face) {
2076 return false;
2077 }
2078
2079 *numFaces = face->num_faces;
2080 return true;
2081}

◆ scanInstance()

bool SkFontScanner_FreeType::scanInstance ( SkStreamAsset stream,
int  faceIndex,
int  instanceIndex,
SkString name,
SkFontStyle style,
bool *  isFixedPitch,
AxisDefinitions axes 
) const
overridevirtual

Implements SkFontScanner.

Definition at line 2098 of file SkFontHost_FreeType.cpp.

2104 {
2105
2106 SkAutoMutexExclusive libraryLock(fLibraryMutex);
2107
2108 FT_StreamRec streamRec;
2109 SkUniqueFTFace face(this->openFace(stream, (instanceIndex << 16) + faceIndex, &streamRec));
2110 if (!face) {
2111 return false;
2112 }
2113
2114 int weight = SkFontStyle::kNormal_Weight;
2117 if (face->style_flags & FT_STYLE_FLAG_BOLD) {
2119 }
2120 if (face->style_flags & FT_STYLE_FLAG_ITALIC) {
2122 }
2123
2124 bool hasAxes = face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS;
2125 TT_OS2* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face.get(), ft_sfnt_os2));
2126 bool hasOs2 = os2 && os2->version != 0xffff;
2127
2128 PS_FontInfoRec psFontInfo;
2129
2130 if (hasOs2) {
2131 weight = os2->usWeightClass;
2132 width = os2->usWidthClass;
2133
2134 // OS/2::fsSelection bit 9 indicates oblique.
2135 if (SkToBool(os2->fsSelection & (1u << 9))) {
2137 }
2138 }
2139
2140 // Let variable axes override properties from the OS/2 table.
2141 if (hasAxes) {
2142 AxisDefinitions axisDefinitions;
2143 if (GetAxes(face.get(), &axisDefinitions)) {
2144 size_t numAxes = axisDefinitions.size();
2145 static constexpr SkFourByteTag wghtTag = SkSetFourByteTag('w', 'g', 'h', 't');
2146 static constexpr SkFourByteTag wdthTag = SkSetFourByteTag('w', 'd', 't', 'h');
2147 static constexpr SkFourByteTag slntTag = SkSetFourByteTag('s', 'l', 'n', 't');
2148 std::optional<size_t> wghtIndex;
2149 std::optional<size_t> wdthIndex;
2150 std::optional<size_t> slntIndex;
2151 for(size_t i = 0; i < numAxes; ++i) {
2152 if (axisDefinitions[i].fTag == wghtTag) {
2153 // Rough validity check, sufficient spread and ranges within 0-1000.
2154 SkScalar wghtRange = axisDefinitions[i].fMaximum - axisDefinitions[i].fMinimum;
2155 if (wghtRange > 5 && wghtRange <= 1000 && axisDefinitions[i].fMaximum <= 1000) {
2156 wghtIndex = i;
2157 }
2158 }
2159 if (axisDefinitions[i].fTag == wdthTag) {
2160 // Rough validity check, sufficient spread and are ranges within 0-500.
2161 SkScalar wdthRange = axisDefinitions[i].fMaximum - axisDefinitions[i].fMinimum;
2162 if (wdthRange > 0 && wdthRange <= 500 && axisDefinitions[i].fMaximum <= 500) {
2163 wdthIndex = i;
2164 }
2165 }
2166 if (axisDefinitions[i].fTag == slntTag) {
2167 slntIndex = i;
2168 }
2169 }
2170 AutoSTMalloc<4, FT_Fixed> coords(numAxes);
2171 if ((wghtIndex || wdthIndex || slntIndex) &&
2172 !FT_Get_Var_Design_Coordinates(face.get(), numAxes, coords.get())) {
2173 if (wghtIndex) {
2174 SkASSERT(*wghtIndex < numAxes);
2175 weight = SkFixedRoundToInt(coords[*wghtIndex]);
2176 }
2177 if (wdthIndex) {
2178 SkASSERT(*wdthIndex < numAxes);
2179 SkScalar wdthValue = SkFixedToScalar(coords[*wdthIndex]);
2181 }
2182 if (slntIndex) {
2183 SkASSERT(*slntIndex < numAxes);
2184 // https://docs.microsoft.com/en-us/typography/opentype/spec/dvaraxistag_slnt
2185 // "Scale interpretation: Values can be interpreted as the angle,
2186 // in counter-clockwise degrees, of oblique slant from whatever
2187 // the designer considers to be upright for that font design."
2188 if (SkFixedToScalar(coords[*slntIndex]) < 0) {
2190 }
2191 }
2192 }
2193 }
2194 }
2195
2196 if (!hasOs2 && !hasAxes && 0 == FT_Get_PS_Font_Info(face.get(), &psFontInfo) && psFontInfo.weight) {
2197 static const struct {
2198 char const * const name;
2199 int const weight;
2200 } commonWeights [] = {
2201 // There are probably more common names, but these are known to exist.
2202 { "all", SkFontStyle::kNormal_Weight }, // Multiple Masters usually default to normal.
2203 { "black", SkFontStyle::kBlack_Weight },
2204 { "bold", SkFontStyle::kBold_Weight },
2207 { "demibold", SkFontStyle::kSemiBold_Weight },
2208 { "extra", SkFontStyle::kExtraBold_Weight },
2209 { "extrabold", SkFontStyle::kExtraBold_Weight },
2210 { "extralight", SkFontStyle::kExtraLight_Weight },
2211 { "hairline", SkFontStyle::kThin_Weight },
2212 { "heavy", SkFontStyle::kBlack_Weight },
2213 { "light", SkFontStyle::kLight_Weight },
2214 { "medium", SkFontStyle::kMedium_Weight },
2215 { "normal", SkFontStyle::kNormal_Weight },
2216 { "plain", SkFontStyle::kNormal_Weight },
2217 { "regular", SkFontStyle::kNormal_Weight },
2218 { "roman", SkFontStyle::kNormal_Weight },
2219 { "semibold", SkFontStyle::kSemiBold_Weight },
2220 { "standard", SkFontStyle::kNormal_Weight },
2221 { "thin", SkFontStyle::kThin_Weight },
2222 { "ultra", SkFontStyle::kExtraBold_Weight },
2223 { "ultrablack", SkFontStyle::kExtraBlack_Weight },
2224 { "ultrabold", SkFontStyle::kExtraBold_Weight },
2225 { "ultraheavy", SkFontStyle::kExtraBlack_Weight },
2226 { "ultralight", SkFontStyle::kExtraLight_Weight },
2227 };
2228 int const index = SkStrLCSearch(&commonWeights[0].name, std::size(commonWeights),
2229 psFontInfo.weight, sizeof(commonWeights[0]));
2230 if (index >= 0) {
2231 weight = commonWeights[index].weight;
2232 } else {
2233 LOG_INFO("Do not know weight for: %s (%s) \n", face->family_name, psFontInfo.weight);
2234 }
2235 }
2236
2237 if (name != nullptr) {
2238 name->set(face->family_name);
2239 }
2240 if (style != nullptr) {
2241 *style = SkFontStyle(weight, width, slant);
2242 }
2243 if (isFixedPitch != nullptr) {
2244 *isFixedPitch = FT_IS_FIXED_WIDTH(face);
2245 }
2246
2247 if (axes != nullptr && !GetAxes(face.get(), axes)) {
2248 return false;
2249 }
2250 return true;
2251}
int SkStrLCSearch(const char *const *base, int count, const char target[], size_t len, size_t elemSize)
Definition: SkTSearch.cpp:64
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
static bool GetAxes(FT_Face face, AxisDefinitions *axes)
skia_private::STArray< 4, AxisDefinition, true > AxisDefinitions
Definition: SkFontScanner.h:29
@ kSemiBold_Weight
Definition: SkFontStyle.h:25
@ kExtraBlack_Weight
Definition: SkFontStyle.h:29
@ kExtraBold_Weight
Definition: SkFontStyle.h:27
@ kExtraLight_Weight
Definition: SkFontStyle.h:21
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259

The documentation for this class was generated from the following files: