Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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
 
- 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, true > AxisDefinitions
 

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) {
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 SkDEBUGCODE(...)
Definition SkDebug.h:23
#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
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
const char * name
Definition fuchsia.cc:50
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

◆ 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

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