33#include <fontconfig/fontconfig.h>
51#ifndef FC_POSTSCRIPT_NAME
52# define FC_POSTSCRIPT_NAME "postscriptname"
77static SkMutex& f_c_mutex() {
78 static SkMutex& mutex = *(
new SkMutex);
83 inline static constexpr int FontConfigThreadSafeVersion = 21393;
87 if (FcGetVersion() < FontConfigThreadSafeVersion) {
88 f_c_mutex().acquire();
93 if (FcGetVersion() < FontConfigThreadSafeVersion) {
94 f_c_mutex().release();
99 FCLocker() { lock(); }
100 ~FCLocker() { unlock(); }
103 if (FcGetVersion() < FontConfigThreadSafeVersion) {
104 f_c_mutex().assertHeld();
112 FCLocker::AssertHeld();
115template <
typename T, T* (*C)(),
void (*D)(T*)>
class SkAutoFc
120 T* obj = this->
operator T*();
135static bool get_bool(FcPattern* pattern,
const char object[],
bool missing =
false) {
137 if (FcPatternGetBool(pattern,
object, 0, &
value) != FcResultMatch) {
143static int get_int(FcPattern* pattern,
const char object[],
int missing) {
145 if (FcPatternGetInteger(pattern,
object, 0, &
value) != FcResultMatch) {
151static const char*
get_string(FcPattern* pattern,
const char object[],
const char* missing =
"") {
153 if (FcPatternGetString(pattern,
object, 0, &
value) != FcResultMatch) {
156 return (
const char*)
value;
159static const FcMatrix*
get_matrix(FcPattern* pattern,
const char object[]) {
161 if (FcPatternGetMatrix(pattern,
object, 0, &
matrix) != FcResultMatch) {
183 FCLocker::AssertHeld();
190 SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
192 for (
int i = 0; hasId &&
i <
id; ++
i) {
193 hasId = FcPatternRemove(minimal,
object, 0);
200 if (
result != FcResultMatch) {
204 hasId = FcPatternRemove(minimal,
object, 1);
213 FcLangSetAdd(strongLangSet, (
const FcChar8*)
"nomatchlang");
215 FcPatternAddLangSet(strong, FC_LANG, strongLangSet);
218 FcLangSetAdd(weakLangSet, (
const FcChar8*)
"matchlang");
220 FcPatternAddString(weak,
object, (
const FcChar8*)
"nomatchstring");
221 FcPatternAddLangSet(weak, FC_LANG, weakLangSet);
223 FcFontSetAdd(fontSet, strong.release());
224 FcFontSetAdd(fontSet, weak.release());
227 FcPatternAddLangSet(minimal, FC_LANG, weakLangSet);
236 FcFontSet* fontSets[1] = { fontSet };
240 FcLangSet* matchLangSet;
241 FcPatternGetLangSet(
match, FC_LANG, 0, &matchLangSet);
242 return FcLangEqual == FcLangSetHasLang(matchLangSet, (
const FcChar8*)
"matchlang")
251 FCLocker::AssertHeld();
254 SkAutoFcPattern minimal(FcPatternFilter(pattern, requestedObjectOnly));
256 int lastStrongId = -1;
259 for (
int id = 0; ; ++
id) {
272 if (lastStrongId < 0) {
277 for (
int id = lastStrongId + 1;
id < numIds; ++
id) {
278 SkAssertResult(FcPatternRemove(pattern,
object, lastStrongId + 1));
288 return new_min + ((
value - old_min) * (new_max - new_min) / (old_max - old_min));
298 if (val < ranges[0].old_val) {
303 for (
int i = 0;
i < rangesCount - 1; ++
i) {
304 if (val < ranges[
i+1].old_val) {
305 return map_range(val, ranges[
i].old_val, ranges[
i+1].old_val,
306 ranges[
i].new_val, ranges[
i+1].new_val);
312 return ranges[rangesCount-1].
new_val;
315#ifndef FC_WEIGHT_DEMILIGHT
316#define FC_WEIGHT_DEMILIGHT 65
323 static constexpr MapRanges weightRanges[] = {
324 { FC_WEIGHT_THIN, SkFS::kThin_Weight },
325 { FC_WEIGHT_EXTRALIGHT, SkFS::kExtraLight_Weight },
326 { FC_WEIGHT_LIGHT, SkFS::kLight_Weight },
328 { FC_WEIGHT_BOOK, 380 },
329 { FC_WEIGHT_REGULAR, SkFS::kNormal_Weight },
330 { FC_WEIGHT_MEDIUM, SkFS::kMedium_Weight },
331 { FC_WEIGHT_DEMIBOLD, SkFS::kSemiBold_Weight },
332 { FC_WEIGHT_BOLD, SkFS::kBold_Weight },
333 { FC_WEIGHT_EXTRABOLD, SkFS::kExtraBold_Weight },
334 { FC_WEIGHT_BLACK, SkFS::kBlack_Weight },
335 { FC_WEIGHT_EXTRABLACK, SkFS::kExtraBlack_Weight },
340 static constexpr MapRanges widthRanges[] = {
341 { FC_WIDTH_ULTRACONDENSED, SkFS::kUltraCondensed_Width },
342 { FC_WIDTH_EXTRACONDENSED, SkFS::kExtraCondensed_Width },
343 { FC_WIDTH_CONDENSED, SkFS::kCondensed_Width },
344 { FC_WIDTH_SEMICONDENSED, SkFS::kSemiCondensed_Width },
345 { FC_WIDTH_NORMAL, SkFS::kNormal_Width },
346 { FC_WIDTH_SEMIEXPANDED, SkFS::kSemiExpanded_Width },
347 { FC_WIDTH_EXPANDED, SkFS::kExpanded_Width },
348 { FC_WIDTH_EXTRAEXPANDED, SkFS::kExtraExpanded_Width },
349 { FC_WIDTH_ULTRAEXPANDED, SkFS::kUltraExpanded_Width },
354 SkFS::Slant slant = SkFS::kUpright_Slant;
355 switch (
get_int(pattern, FC_SLANT, FC_SLANT_ROMAN)) {
356 case FC_SLANT_ROMAN: slant = SkFS::kUpright_Slant;
break;
357 case FC_SLANT_ITALIC : slant = SkFS::kItalic_Slant ;
break;
358 case FC_SLANT_OBLIQUE: slant = SkFS::kOblique_Slant;
break;
366 FCLocker::AssertHeld();
371 static constexpr MapRanges weightRanges[] = {
372 { SkFS::kThin_Weight, FC_WEIGHT_THIN },
373 { SkFS::kExtraLight_Weight, FC_WEIGHT_EXTRALIGHT },
374 { SkFS::kLight_Weight, FC_WEIGHT_LIGHT },
376 { 380, FC_WEIGHT_BOOK },
377 { SkFS::kNormal_Weight, FC_WEIGHT_REGULAR },
378 { SkFS::kMedium_Weight, FC_WEIGHT_MEDIUM },
379 { SkFS::kSemiBold_Weight, FC_WEIGHT_DEMIBOLD },
380 { SkFS::kBold_Weight, FC_WEIGHT_BOLD },
381 { SkFS::kExtraBold_Weight, FC_WEIGHT_EXTRABOLD },
382 { SkFS::kBlack_Weight, FC_WEIGHT_BLACK },
383 { SkFS::kExtraBlack_Weight, FC_WEIGHT_EXTRABLACK },
387 static constexpr MapRanges widthRanges[] = {
388 { SkFS::kUltraCondensed_Width, FC_WIDTH_ULTRACONDENSED },
389 { SkFS::kExtraCondensed_Width, FC_WIDTH_EXTRACONDENSED },
390 { SkFS::kCondensed_Width, FC_WIDTH_CONDENSED },
391 { SkFS::kSemiCondensed_Width, FC_WIDTH_SEMICONDENSED },
392 { SkFS::kNormal_Width, FC_WIDTH_NORMAL },
393 { SkFS::kSemiExpanded_Width, FC_WIDTH_SEMIEXPANDED },
394 { SkFS::kExpanded_Width, FC_WIDTH_EXPANDED },
395 { SkFS::kExtraExpanded_Width, FC_WIDTH_EXTRAEXPANDED },
396 { SkFS::kUltraExpanded_Width, FC_WIDTH_ULTRAEXPANDED },
400 int slant = FC_SLANT_ROMAN;
401 switch (style.
slant()) {
402 case SkFS::kUpright_Slant: slant = FC_SLANT_ROMAN ;
break;
403 case SkFS::kItalic_Slant : slant = FC_SLANT_ITALIC ;
break;
404 case SkFS::kOblique_Slant: slant = FC_SLANT_OBLIQUE;
break;
408 FcPatternAddInteger(pattern, FC_WEIGHT, weight);
409 FcPatternAddInteger(pattern, FC_WIDTH ,
width);
410 FcPatternAddInteger(pattern, FC_SLANT , slant);
437 std::unique_ptr<SkStreamAsset>
onOpenStream(
int* ttcIndex)
const override {
445 resolvedFilename += filename;
447 filename = resolvedFilename.
c_str();
460 if (fcOutline && fcMatrix) {
464 fm.
setAll(fcMatrix->xx,-fcMatrix->xy, 0,
465 -fcMatrix->yx, fcMatrix->yy, 0,
484 std::unique_ptr<SkAdvancedTypefaceMetrics>
info =
504 return sk_make_sp<SkTypeface_FreeTypeStream>(
515 return std::make_unique<SkFontData>(std::move(
stream), index, 0,
nullptr, 0,
nullptr, 0);
527 FC_PROPORTIONAL !=
get_int(pattern, FC_SPACING, FC_PROPORTIONAL))
543 : fFontMgr(std::move(parent))
544 , fFontSet(std::move(fontSet))
547 ~StyleSet()
override {
553 int count()
override {
return fFontSet->nfont; }
556 if (index < 0 || fFontSet->nfont <= index) {
565 *styleName =
get_string(fFontSet->fonts[index], FC_STYLE);
570 if (index < 0 || fFontSet->nfont <= index) {
575 FcPatternReference(fFontSet->fonts[index]);
576 return fFontSet->fonts[index];
578 return fFontMgr->createTypefaceFromFcPattern(std::move(
match));
587 FcConfigSubstitute(fFontMgr->fFC, pattern, FcMatchPattern);
588 FcDefaultSubstitute(pattern);
591 FcFontSet* fontSets[1] = { fFontSet };
592 return FcFontSetMatch(fFontMgr->fFC,
597 return fFontMgr->createTypefaceFromFcPattern(std::move(
match));
608 if (!strcmp(list[
i], str)) {
621 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
622 for (
int setIndex = 0; setIndex < (
int)
std::size(fcNameSet); ++setIndex) {
624 FcFontSet* allFonts(FcConfigGetFonts(fcconfig, fcNameSet[setIndex]));
625 if (
nullptr == allFonts) {
629 for (
int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
630 FcPattern* current = allFonts->fonts[fontIndex];
631 for (
int id = 0; ; ++
id) {
632 FcChar8* fcFamilyName;
633 FcResult
result = FcPatternGetString(current, FC_FAMILY,
id, &fcFamilyName);
634 if (FcResultNoId ==
result) {
637 if (FcResultMatch !=
result) {
640 const char* familyName =
reinterpret_cast<const char*
>(fcFamilyName);
641 if (familyName && !FindName(
names, familyName)) {
642 *
names.append() = familyName;
643 *sizes.
append() = strlen(familyName) + 1;
653 static bool FindByFcPattern(
SkTypeface* cached,
void* ctx) {
655 FcPattern* ctxPattern =
static_cast<FcPattern*
>(ctx);
656 return FcTrue == FcPatternEqual(cshFace->
fPattern, ctxPattern);
659 mutable SkMutex fTFCacheMutex;
692 : fFC(config ? config : FcInitLoadConfigAndFonts())
693 , fSysroot(reinterpret_cast<const char*>(FcConfigGetSysRoot(fFC)))
694 , fFamilyNames(GetFamilyNames(fFC)) { }
704 return fFamilyNames->
count();
708 familyName->
set(fFamilyNames->
atStr(index));
721 static constexpr const int maxId = 65536;
722 for (
int patternId = 0; patternId < maxId; ++patternId) {
723 FcChar8* patternString;
724 FcResult
result = FcPatternGetString(
p,
object, patternId, &patternString);
725 if (
result == FcResultNoId) {
728 if (
result == FcResultMatch) {
729 strings.push_back(patternString);
733 auto compareStrings = [](FcChar8*
a, FcChar8*
b) ->
bool {
734 return FcStrCmpIgnoreCase(
a,
b) < 0;
739 getStrings(
font,
object, fontStrings);
740 getStrings(pattern,
object, patternStrings);
745 FcChar8** fontString = fontStrings.
begin();
746 FcChar8** patternString = patternStrings.
begin();
747 while (fontString != fontStrings.
end() && patternString != patternStrings.
end()) {
748 int cmp = FcStrCmpIgnoreCase(*fontString, *patternString);
751 }
else if (cmp > 0) {
763 if (
nullptr == filename) {
778 resolvedFilename = fSysroot;
779 resolvedFilename += filename;
793 FcCharSet* matchCharSet;
794 for (
int charSetId = 0; ; ++charSetId) {
795 result = FcPatternGetCharSet(
font, FC_CHARSET, charSetId, &matchCharSet);
796 if (FcResultNoId ==
result) {
799 if (FcResultMatch !=
result) {
802 if (FcCharSetHasChar(matchCharSet,
character)) {
816 FcPatternAddString(pattern, FC_FAMILY, (
const FcChar8*)familyName);
817 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
818 FcDefaultSubstitute(pattern);
820 FcPattern* matchPattern;
823 strongPattern.reset(FcPatternDuplicate(pattern));
825 matchPattern = strongPattern;
827 matchPattern = pattern;
834 static const FcSetName fcNameSet[] = { FcSetSystem, FcSetApplication };
835 for (
int setIndex = 0; setIndex < (
int)
std::size(fcNameSet); ++setIndex) {
837 FcFontSet* allFonts(FcConfigGetFonts(fFC, fcNameSet[setIndex]));
838 if (
nullptr == allFonts) {
842 for (
int fontIndex = 0; fontIndex < allFonts->nfont; ++fontIndex) {
843 FcPattern*
font = allFonts->fonts[fontIndex];
845 FcFontSetAdd(
matches, FcFontRenderPrepare(fFC, pattern,
font));
860 FcPatternAddString(pattern, FC_FAMILY, (
const FcChar8*)familyName);
862 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
863 FcDefaultSubstitute(pattern);
873 FcPattern* matchPattern;
876 strongPattern.reset(FcPatternDuplicate(pattern));
878 matchPattern = strongPattern;
880 matchPattern = pattern;
890 return createTypefaceFromFcPattern(std::move(
font));
904 FcValue familyNameValue;
905 familyNameValue.type = FcTypeString;
906 familyNameValue.u.s =
reinterpret_cast<const FcChar8*
>(familyName);
907 FcPatternAddWeak(pattern, FC_FAMILY, familyNameValue, FcFalse);
913 FcPatternAddCharSet(pattern, FC_CHARSET, charSet);
915 if (bcp47Count > 0) {
918 for (
int i = bcp47Count;
i --> 0;) {
919 FcLangSetAdd(langSet, (
const FcChar8*)bcp47[
i]);
921 FcPatternAddLangSet(pattern, FC_LANG, langSet);
924 FcConfigSubstitute(fFC, pattern, FcMatchPattern);
925 FcDefaultSubstitute(pattern);
934 return createTypefaceFromFcPattern(std::move(
font));
938 int ttcIndex)
const override {
953 return this->
makeFromStream(std::make_unique<SkMemoryStream>(std::move(
data)), ttcIndex);
971 return sk_make_sp<SkFontMgr_fontconfig>(fc);
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
#define SkASSERT_RELEASE(cond)
SkAutoFc< FcFontSet, FcFontSetCreate, FcFontSetDestroy > SkAutoFcFontSet
static const FcMatrix * get_matrix(FcPattern *pattern, const char object[])
static void remove_weak(FcPattern *pattern, const char object[])
static bool get_bool(FcPattern *pattern, const char object[], bool missing=false)
static int get_int(FcPattern *pattern, const char object[], int missing)
SkAutoFc< FcPattern, FcPatternCreate, FcPatternDestroy > SkAutoFcPattern
#define FC_POSTSCRIPT_NAME
static SkFontStyle skfontstyle_from_fcpattern(FcPattern *pattern)
#define FC_WEIGHT_DEMILIGHT
static SkWeakReturn is_weak(FcPattern *pattern, const char object[], int id)
SkAutoFc< FcConfig, FcConfigCreate, FcConfigDestroy > SkAutoFcConfig
sk_sp< SkFontMgr > SkFontMgr_New_FontConfig(FcConfig *fc)
static SkScalar map_ranges(SkScalar val, MapRanges const ranges[], int rangesCount)
static int map_range(SkScalar value, SkScalar old_min, SkScalar old_max, SkScalar new_min, SkScalar new_max)
static void fcpattern_from_skfontstyle(SkFontStyle style, FcPattern *pattern)
SkAutoFc< FcObjectSet, FcObjectSetCreate, FcObjectSetDestroy > SkAutoFcObjectSet
SkAutoFc< FcLangSet, FcLangSetCreate, FcLangSetDestroy > SkAutoFcLangSet
SkAutoFc< FcCharSet, FcCharSetCreate, FcCharSetDestroy > SkAutoFcCharSet
static const char * get_string(FcPattern *pattern, const char object[], const char *missing="")
bool sk_exists(const char *path, SkFILE_Flags=(SkFILE_Flags) 0)
sk_sp< T > sk_ref_sp(T *obj)
#define SkScalarRoundToInt(x)
void SkTQSort(T *begin, T *end, const C &lessThan)
#define SK_NO_THREAD_SAFETY_ANALYSIS
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
SkAutoFc(const SkAutoFc &)=delete
SkAutoFc(SkAutoFc &&that)
const char * atStr(int index) const
static sk_sp< SkDataTable > MakeCopyArrays(const void *const *ptrs, const size_t sizes[], int count)
void setFactoryId(SkTypeface::FactoryId factoryId)
bool FontAccessible(FcPattern *font) const
~SkFontMgr_fontconfig() override
sk_sp< SkTypeface > onLegacyMakeTypeface(const char familyName[], SkFontStyle style) const override
void onGetFamilyName(int index, SkString *familyName) const override
sk_sp< SkTypeface > onMakeFromStreamIndex(std::unique_ptr< SkStreamAsset > stream, int ttcIndex) const override
sk_sp< SkFontStyleSet > onMatchFamily(const char familyName[]) const override
SkFontMgr_fontconfig(FcConfig *config)
sk_sp< SkTypeface > onMakeFromData(sk_sp< SkData > data, int ttcIndex) const override
sk_sp< SkTypeface > onMatchFamilyStyle(const char familyName[], const SkFontStyle &style) const override
sk_sp< SkFontStyleSet > onCreateStyleSet(int index) const override
static bool FontFamilyNameMatches(FcPattern *font, FcPattern *pattern)
static bool FontContainsCharacter(FcPattern *font, uint32_t character)
sk_sp< SkTypeface > onMatchFamilyStyleCharacter(const char familyName[], const SkFontStyle &style, const char *bcp47[], int bcp47Count, SkUnichar character) const override
int onCountFamilies() const override
sk_sp< SkTypeface > onMakeFromFile(const char path[], int ttcIndex) const override
sk_sp< SkTypeface > onMakeFromStreamArgs(std::unique_ptr< SkStreamAsset > stream, const SkFontArguments &args) const override
static bool AnyStringMatching(FcPattern *font, FcPattern *pattern, const char *object)
sk_sp< SkTypeface > makeFromStream(std::unique_ptr< SkStreamAsset >, int ttcIndex=0) const
sk_sp< SkTypeface > matchFamilyStyle(const char familyName[], const SkFontStyle &) const
SkScalar getSkewY() const
SkMatrix & setAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar persp0, SkScalar persp1, SkScalar persp2)
SkScalar getSkewX() const
SkScalar getScaleX() const
SkMatrix & preConcat(const SkMatrix &other)
SkScalar getScaleY() const
static std::unique_ptr< SkStreamAsset > MakeFromFile(const char path[])
void set(const SkString &src)
const char * c_str() const
sk_sp< SkTypeface > findByProcAndRef(FindProc proc, void *ctx) const
void add(sk_sp< SkTypeface >)
std::unique_ptr< SkAdvancedTypefaceMetrics > onGetAdvancedMetrics() const override
std::unique_ptr< SkFontData > cloneFontData(const SkFontArguments &, SkFontStyle *style) const
void onFilterRec(SkScalerContextRec *) const override
SkTypeface_FreeType(const SkFontStyle &style, bool isFixedPitch)
static sk_sp< SkTypeface > MakeFromStream(std::unique_ptr< SkStreamAsset >, const SkFontArguments &)
std::unique_ptr< SkFontData > onMakeFontData() const override
~SkTypeface_fontconfig() override
void onFilterRec(SkScalerContextRec *rec) const override
void onGetFontDescriptor(SkFontDescriptor *desc, bool *serialize) const override
static sk_sp< SkTypeface_fontconfig > Make(SkAutoFcPattern pattern, SkString sysroot)
void onGetFamilyName(SkString *familyName) const override
std::unique_ptr< SkStreamAsset > onOpenStream(int *ttcIndex) const override
std::unique_ptr< SkAdvancedTypefaceMetrics > onGetAdvancedMetrics() const override
sk_sp< SkTypeface > onMakeClone(const SkFontArguments &args) const override
void getFamilyName(SkString *name) const
SkFontStyle fontStyle() const
void serialize(SkWStream *, SerializeBehavior=SerializeBehavior::kIncludeDataIfLocal) const
bool isFixedPitch() const
void reset(T *ptr=nullptr)
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
unsigned useCenter Optional< SkMatrix > matrix
static const char *const names[]
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
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
font
Font Metadata and Metrics.
void getMatrixFrom2x2(SkMatrix *) const
std::shared_ptr< const fml::Mapping > data