2 Copyright (c) 2002 Craig Drummond <craig@kde.org>
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
20 #include "kxftconfig.h"
21 #ifdef HAVE_FONTCONFIG
38 #include <fontconfig/fontconfig.h>
43 QString
KXftConfig::contractHome(QString path
)
45 if (!path
.isEmpty() && '/'==path
[0])
47 QString
home(QDir::homePath());
49 if(path
.startsWith(home
))
51 int len
= home
.length();
53 if(path
.length() == len
|| path
[len
] == '/')
54 return path
.replace(0, len
, QLatin1String("~"));
61 QString
KXftConfig::expandHome(QString path
)
63 if(!path
.isEmpty() && '~'==path
[0])
64 return 1==path
.length() ? QDir::homePath() : path
.replace(0, 1, QDir::homePath());
69 static int point2Pixel(double point
)
71 return (int)(((point
*QX11Info::appDpiY())/72.0)+0.5);
74 static int pixel2Point(double pixel
)
76 return (int)(((pixel
*72.0)/(double)QX11Info::appDpiY())+0.5);
79 static bool equal(double d1
, double d2
)
81 return (fabs(d1
- d2
) < 0.0001);
84 static QString
dirSyntax(const QString
&d
)
90 ds
.replace("//", "/");
92 int slashPos
=ds
.lastIndexOf('/');
94 if(slashPos
!=(((int)ds
.length())-1))
103 static QString
xDirSyntax(const QString
&d
)
108 int slashPos
=ds
.lastIndexOf('/');
110 if(slashPos
==(((int)ds
.length())-1))
111 ds
.remove(slashPos
, 1);
118 static bool check(const QString
&path
, unsigned int fmt
, bool checkW
=false)
120 KDE_struct_stat info
;
121 QByteArray
pathC(QFile::encodeName(path
));
123 return 0==KDE_lstat(pathC
, &info
) && (info
.st_mode
&S_IFMT
)==fmt
&&
124 (!checkW
|| 0==::access(pathC
, W_OK
));
127 inline bool fExists(const QString
&p
)
129 return check(p
, S_IFREG
, false);
132 inline bool dWritable(const QString
&p
)
134 return check(p
, S_IFDIR
, true);
137 inline bool dExists(const QString
&p
)
139 return check(p
, S_IFDIR
, false);
142 static QString
getDir(const QString
&f
)
146 int slashPos
=d
.lastIndexOf('/');
149 d
.remove(slashPos
+1, d
.length());
154 static time_t getTimeStamp(const QString
&item
)
156 KDE_struct_stat info
;
158 return !item
.isNull() && 0==KDE_lstat(QFile::encodeName(item
), &info
) ? info
.st_mtime
: 0;
161 inline QString
fileSyntax(const QString
&f
) { return xDirSyntax(f
); }
163 // Obtain location of config file to use.
165 // For system, prefer the following:
167 // <...>/config.d/00kde.conf = preferred method from FontConfig >= 2.3
170 // Non-system, prefer:
172 // $HOME/<...>/.fonts.conf
173 // $HOME/<...>/fonts.conf
175 QString
getConfigFile(bool system
)
177 #if (FC_VERSION>=20300)
178 static const char * constKdeRootFcFile
="00kde.conf";
181 FcStrList
*list
=FcConfigGetConfigFiles(FcConfigGetCurrent());
184 QString
home(dirSyntax(QDir::homePath()));
186 while((file
=FcStrListNext(list
)))
188 QString
f((const char *)file
);
192 // For nonsystem, only consider file within $HOME
193 if(system
|| 0==fileSyntax(f
).indexOf(home
))
196 #if (FC_VERSION>=20300)
197 if(system
&& dExists(f
) && (f
.contains(QRegExp("/conf\\.d/?$")) ||
198 f
.contains(QRegExp("/conf\\.d?$"))) )
199 return dirSyntax(f
)+constKdeRootFcFile
; // This ones good enough for me!
204 // Go through list of files, looking for the preferred one...
207 QStringList::const_iterator
it(files
.begin()),
211 if(-1!=(*it
).indexOf(QRegExp(system
? "/local\\.conf$" : "/\\.?fonts\\.conf$")))
213 return files
.front(); // Just return the 1st one...
215 else // Hmmm... no known files?
216 return system
? "/etc/fonts/local.conf" : fileSyntax(home
+"/.fonts.conf");
219 static QString
getEntry(QDomElement element
, const char *type
, unsigned int numAttributes
, ...)
221 if(numAttributes
==element
.attributes().length())
227 va_start(args
, numAttributes
);
229 for(arg
=0; arg
<numAttributes
&& ok
; ++arg
)
231 const char *attr
=va_arg(args
, const char *);
232 const char *val
=va_arg(args
, const char *);
234 if(!attr
|| !val
|| val
!=element
.attribute(attr
))
242 QDomNode n
=element
.firstChild();
246 QDomElement e
= n
.toElement();
248 if(!e
.isNull() && type
==e
.tagName())
257 static KXftConfig::SubPixel::Type
strToType(const char *str
)
259 if(0==strcmp(str
, "rgb"))
260 return KXftConfig::SubPixel::Rgb
;
261 else if(0==strcmp(str
, "bgr"))
262 return KXftConfig::SubPixel::Bgr
;
263 else if(0==strcmp(str
, "vrgb"))
264 return KXftConfig::SubPixel::Vrgb
;
265 else if(0==strcmp(str
, "vbgr"))
266 return KXftConfig::SubPixel::Vbgr
;
268 return KXftConfig::SubPixel::None
;
271 static KXftConfig::Hint::Style
strToStyle(const char *str
)
273 if(0==strcmp(str
, "hintslight"))
274 return KXftConfig::Hint::Slight
;
275 else if(0==strcmp(str
, "hintmedium"))
276 return KXftConfig::Hint::Medium
;
277 else if(0==strcmp(str
, "hintfull"))
278 return KXftConfig::Hint::Full
;
280 return KXftConfig::Hint::None
;
283 KXftConfig::KXftConfig(int required
, bool system
)
284 : m_doc("fontconfig"),
285 m_required(required
),
288 m_file
=getConfigFile(system
);
289 kDebug(1208) << "Using fontconfig file:" << m_file
;
290 m_antiAliasing
= aliasingEnabled();
294 KXftConfig::~KXftConfig()
298 bool KXftConfig::reset()
306 m_excludeRange
.reset();
307 m_excludePixelRange
.reset();
312 if(f
.open(QIODevice::ReadOnly
))
314 m_time
=getTimeStamp(m_file
);
318 if(m_doc
.setContent(&f
))
323 ok
=!fExists(m_file
) && dWritable(getDir(m_file
));
325 if(m_doc
.documentElement().isNull())
326 m_doc
.appendChild(m_doc
.createElement("fontconfig"));
328 if(ok
&& m_required
&ExcludeRange
)
331 // Check exclude range values - i.e. size and pixel size...
332 // If "size" range is set, ensure "pixelsize" matches...
333 if(!equal(0, m_excludeRange
.from
) || !equal(0, m_excludeRange
.to
))
335 double pFrom
=(double)point2Pixel(m_excludeRange
.from
),
336 pTo
=(double)point2Pixel(m_excludeRange
.to
);
338 if(!equal(pFrom
, m_excludePixelRange
.from
) || !equal(pTo
, m_excludePixelRange
.to
))
340 m_excludePixelRange
.from
=pFrom
;
341 m_excludePixelRange
.to
=pTo
;
346 else if(!equal(0, m_excludePixelRange
.from
) || !equal(0, m_excludePixelRange
.to
))
348 // "pixelsize" set, but not "size" !!!
349 m_excludeRange
.from
=(int)pixel2Point(m_excludePixelRange
.from
);
350 m_excludeRange
.to
=(int)pixel2Point(m_excludePixelRange
.to
);
359 bool KXftConfig::apply()
366 // Check if file has been written since we last read it. If it has, then re-read and add any
368 if(fExists(m_file
) && getTimeStamp(m_file
)!=m_time
)
370 KXftConfig
newConfig(m_required
, m_system
);
374 QStringList
list(getDirList());
375 QStringList::const_iterator
it(list
.begin()),
378 for(it
=list
.constBegin(); it
!=list
.constEnd(); ++it
)
379 newConfig
.addDir(*it
);
382 if(m_required
&ExcludeRange
)
383 newConfig
.setExcludeRange(m_excludeRange
.from
, m_excludeRange
.to
);
384 if(m_required
&SubPixelType
)
385 newConfig
.setSubPixelType(m_subPixel
.type
);
386 if(m_required
&HintStyle
)
387 newConfig
.setHintStyle(m_hint
.style
);
388 if(m_required
&AntiAlias
)
389 newConfig
.setAntiAliasing(m_antiAliasing
.set
);
391 ok
=newConfig
.changed() ? newConfig
.apply() : true;
395 m_time
=getTimeStamp(m_file
);
399 if(m_required
&ExcludeRange
)
401 // Ensure these are always equal...
402 m_excludePixelRange
.from
=(int)point2Pixel(m_excludeRange
.from
);
403 m_excludePixelRange
.to
=(int)point2Pixel(m_excludeRange
.to
);
406 FcAtomic
*atomic
=FcAtomicCreate((const unsigned char *)(QFile::encodeName(m_file
).data()));
411 if(FcAtomicLock(atomic
))
413 FILE *f
=fopen((char *)FcAtomicNewFile(atomic
), "w");
422 if(m_required
&SubPixelType
)
424 if(m_required
&HintStyle
)
426 if(m_required
&AntiAlias
)
428 if(m_required
&ExcludeRange
)
430 applyExcludeRange(false);
431 applyExcludeRange(true);
435 // Check document syntax...
436 static const char * qtXmlHeader
= "<?xml version = '1.0'?>";
437 static const char * xmlHeader
= "<?xml version=\"1.0\"?>";
438 static const char * qtDocTypeLine
= "<!DOCTYPE fontconfig>";
439 static const char * docTypeLine
= "<!DOCTYPE fontconfig SYSTEM "
442 QString
str(m_doc
.toString());
445 if(0!=str
.indexOf("<?xml"))
446 str
.insert(0, xmlHeader
);
447 else if(0==str
.indexOf(qtXmlHeader
))
448 str
.replace(0, strlen(qtXmlHeader
), xmlHeader
);
450 if(-1!=(idx
=str
.indexOf(qtDocTypeLine
)))
451 str
.replace(idx
, strlen(qtDocTypeLine
), docTypeLine
);
455 fputs(str
.toUtf8(), f
);
458 if(FcAtomicReplaceOrig(atomic
))
461 reset(); // Re-read contents..
464 FcAtomicDeleteNew(atomic
);
466 FcAtomicUnlock(atomic
);
468 FcAtomicDestroy(atomic
);
476 bool KXftConfig::getSubPixelType(SubPixel::Type
&type
)
478 type
=m_subPixel
.type
;
479 return SubPixel::None
!=m_subPixel
.type
;
482 void KXftConfig::setSubPixelType(SubPixel::Type type
)
484 if(type
!=m_subPixel
.type
)
486 m_subPixel
.type
=type
;
491 bool KXftConfig::getHintStyle(Hint::Style
&style
)
493 if(Hint::NotSet
!=m_hint
.style
&& !m_hint
.toBeRemoved
)
502 void KXftConfig::setHintStyle(Hint::Style style
)
504 if((Hint::NotSet
==style
&& Hint::NotSet
!=m_hint
.style
&& !m_hint
.toBeRemoved
) ||
505 (Hint::NotSet
!=style
&& (style
!=m_hint
.style
|| m_hint
.toBeRemoved
)) )
507 m_hint
.toBeRemoved
=(Hint::NotSet
==style
);
512 if(Hint::NotSet
!=style
)
513 setHinting(Hint::None
!=m_hint
.style
);
516 void KXftConfig::setHinting(bool set
)
518 if(set
!=m_hinting
.set
)
525 bool KXftConfig::getExcludeRange(double &from
, double &to
)
527 if(!equal(0, m_excludeRange
.from
) || !equal(0,m_excludeRange
.to
))
529 from
=m_excludeRange
.from
;
530 to
=m_excludeRange
.to
;
538 void KXftConfig::setExcludeRange(double from
, double to
)
540 double f
=from
<to
? from
: to
,
541 t
=from
<to
? to
: from
;
543 if(!equal(f
, m_excludeRange
.from
) || !equal(t
,m_excludeRange
.to
))
545 m_excludeRange
.from
=f
;
551 void KXftConfig::addDir(const QString
&d
)
553 QString
dir(dirSyntax(d
));
555 if(dExists(dir
) && !hasDir(dir
))
557 m_dirs
.append(ListItem(d
));
562 void KXftConfig::removeDir(const QString
&d
)
564 QList
<ListItem
>::Iterator
it(m_dirs
.begin()),
570 QList
<ListItem
>::Iterator dir
=it
;
576 (*dir
).toBeRemoved
=true;
582 QString
KXftConfig::description(SubPixel::Type t
)
594 return i18n("Vertical RGB");
596 return i18n("Vertical BGR");
600 const char * KXftConfig::toStr(SubPixel::Type t
)
618 QString
KXftConfig::description(Hint::Style s
)
624 return i18n("Medium");
630 return i18n("Slight");
636 const char * KXftConfig::toStr(Hint::Style s
)
652 bool KXftConfig::hasDir(const QString
&d
)
654 QString
dir(dirSyntax(d
));
656 QList
<ListItem
>::Iterator
it(m_dirs
.begin()),
660 if(0==dir
.indexOf((*it
).str
))
666 QStringList
KXftConfig::getDirList()
669 QList
<ListItem
>::Iterator
it(m_dirs
.begin()),
673 if(!(*it
).toBeRemoved
)
674 res
.append((*it
).str
);
679 void KXftConfig::readContents()
681 QDomNode n
= m_doc
.documentElement().firstChild();
685 QDomElement e
= n
.toElement();
689 if("dir"==e
.tagName())
692 m_dirs
.append(ListItem(expandHome(dirSyntax(e
.text())), n
));
694 else if("match"==e
.tagName())
698 switch(e
.childNodes().count())
701 if(m_required
&SubPixelType
&& "font"==e
.attribute("target"))
703 QDomElement ene
=e
.firstChild().toElement();
705 if(!ene
.isNull() && "edit"==ene
.tagName())
707 if(!(str
=getEntry(ene
, "const", 2, "name", "rgba", "mode",
711 m_subPixel
.type
=strToType(str
.toLatin1());
713 else if(!(str
=getEntry(ene
, "const", 2, "name", "hintstyle", "mode",
717 m_hint
.style
=strToStyle(str
.toLatin1());
719 else if(!(str
=getEntry(ene
, "bool", 2, "name", "hinting", "mode",
723 m_hinting
.set
=str
.toLower()!="false";
725 else if(!(str
=getEntry(ene
, "bool", 2, "name", "antialias", "mode",
728 m_antiAliasing
.node
=n
;
729 m_antiAliasing
.set
=str
.toLower()!="false";
734 case 3: // CPD: Is target "font" or "pattern" ????
735 if(m_required
&ExcludeRange
&& "font"==e
.attribute("target"))
737 bool foundFalse
=false;
738 QDomNode en
=e
.firstChild();
747 QDomElement ene
=en
.toElement();
751 if("test"==ene
.tagName())
753 // kcmfonts used to write incorrectly more or less instead of
754 // more_eq and less_eq, so read both,
755 // first the old (wrong) one then the right one
756 if(!(str
=getEntry(ene
, "double", 3, "qual", "any", "name",
757 "size", "compare", "more")).isNull())
759 if(!(str
=getEntry(ene
, "double", 3, "qual", "any", "name",
760 "size", "compare", "more_eq")).isNull())
762 if(!(str
=getEntry(ene
, "double", 3, "qual", "any", "name",
763 "size", "compare", "less")).isNull())
765 if(!(str
=getEntry(ene
, "double", 3, "qual", "any", "name",
766 "size", "compare", "less_eq")).isNull())
768 if(!(str
=getEntry(ene
, "double", 3, "qual", "any", "name",
769 "pixelsize", "compare", "more")).isNull())
770 pixelFrom
=str
.toDouble();
771 if(!(str
=getEntry(ene
, "double", 3, "qual", "any", "name",
772 "pixelsize", "compare",
773 "more_eq")).isNull())
774 pixelFrom
=str
.toDouble();
775 if(!(str
=getEntry(ene
, "double", 3, "qual", "any", "name",
776 "pixelsize", "compare", "less")).isNull())
777 pixelTo
=str
.toDouble();
778 if(!(str
=getEntry(ene
, "double", 3, "qual", "any", "name",
779 "pixelsize", "compare",
780 "less_eq")).isNull())
781 pixelTo
=str
.toDouble();
783 else if("edit"==ene
.tagName() &&
784 "false"==getEntry(ene
, "bool", 2, "name", "antialias",
792 if((from
>=0 || to
>=0) && foundFalse
)
794 m_excludeRange
.from
=from
< to
? from
: to
;
795 m_excludeRange
.to
=from
< to
? to
: from
;
796 m_excludeRange
.node
=n
;
798 else if((pixelFrom
>=0 || pixelTo
>=0) && foundFalse
)
800 m_excludePixelRange
.from
=pixelFrom
< pixelTo
? pixelFrom
: pixelTo
;
801 m_excludePixelRange
.to
=pixelFrom
< pixelTo
? pixelTo
: pixelFrom
;
802 m_excludePixelRange
.node
=n
;
815 void KXftConfig::applyDirs()
817 QList
<ListItem
>::Iterator
it(m_dirs
.begin()),
821 if(!(*it
).toBeRemoved
&& (*it
).node
.isNull())
823 QDomElement newNode
= m_doc
.createElement("dir");
824 QDomText text
= m_doc
.createTextNode(contractHome(xDirSyntax((*it
).str
)));
826 newNode
.appendChild(text
);
827 m_doc
.documentElement().appendChild(newNode
);
831 void KXftConfig::applySubPixelType()
833 QDomElement matchNode
= m_doc
.createElement("match"),
834 typeNode
= m_doc
.createElement("const"),
835 editNode
= m_doc
.createElement("edit");
836 QDomText typeText
= m_doc
.createTextNode(toStr(m_subPixel
.type
));
838 matchNode
.setAttribute("target", "font");
839 editNode
.setAttribute("mode", "assign");
840 editNode
.setAttribute("name", "rgba");
841 editNode
.appendChild(typeNode
);
842 typeNode
.appendChild(typeText
);
843 matchNode
.appendChild(editNode
);
844 if(m_subPixel
.node
.isNull())
845 m_doc
.documentElement().appendChild(matchNode
);
847 m_doc
.documentElement().replaceChild(matchNode
, m_subPixel
.node
);
848 m_subPixel
.node
=matchNode
;
851 void KXftConfig::applyHintStyle()
855 if(Hint::NotSet
==m_hint
.style
|| m_hint
.toBeRemoved
)
857 if(!m_hint
.node
.isNull())
859 m_doc
.documentElement().removeChild(m_hint
.node
);
865 QDomElement matchNode
= m_doc
.createElement("match"),
866 typeNode
= m_doc
.createElement("const"),
867 editNode
= m_doc
.createElement("edit");
868 QDomText typeText
= m_doc
.createTextNode(toStr(m_hint
.style
));
870 matchNode
.setAttribute("target", "font");
871 editNode
.setAttribute("mode", "assign");
872 editNode
.setAttribute("name", "hintstyle");
873 editNode
.appendChild(typeNode
);
874 typeNode
.appendChild(typeText
);
875 matchNode
.appendChild(editNode
);
876 if(m_hint
.node
.isNull())
877 m_doc
.documentElement().appendChild(matchNode
);
879 m_doc
.documentElement().replaceChild(matchNode
, m_hint
.node
);
880 m_hint
.node
=matchNode
;
884 void KXftConfig::applyHinting()
886 QDomElement matchNode
= m_doc
.createElement("match"),
887 typeNode
= m_doc
.createElement("bool"),
888 editNode
= m_doc
.createElement("edit");
889 QDomText typeText
= m_doc
.createTextNode(m_hinting
.set
? "true" : "false");
891 matchNode
.setAttribute("target", "font");
892 editNode
.setAttribute("mode", "assign");
893 editNode
.setAttribute("name", "hinting");
894 editNode
.appendChild(typeNode
);
895 typeNode
.appendChild(typeText
);
896 matchNode
.appendChild(editNode
);
897 if(m_hinting
.node
.isNull())
898 m_doc
.documentElement().appendChild(matchNode
);
900 m_doc
.documentElement().replaceChild(matchNode
, m_hinting
.node
);
901 m_hinting
.node
=matchNode
;
904 void KXftConfig::applyExcludeRange(bool pixel
)
906 Exclude
&range
=pixel
? m_excludePixelRange
: m_excludeRange
;
908 if(equal(range
.from
, 0) && equal(range
.to
, 0))
910 if(!range
.node
.isNull())
912 m_doc
.documentElement().removeChild(range
.node
);
921 fromString
.setNum(range
.from
);
922 toString
.setNum(range
.to
);
924 QDomElement matchNode
= m_doc
.createElement("match"),
925 fromTestNode
= m_doc
.createElement("test"),
926 fromNode
= m_doc
.createElement("double"),
927 toTestNode
= m_doc
.createElement("test"),
928 toNode
= m_doc
.createElement("double"),
929 editNode
= m_doc
.createElement("edit"),
930 boolNode
= m_doc
.createElement("bool");
931 QDomText fromText
= m_doc
.createTextNode(fromString
),
932 toText
= m_doc
.createTextNode(toString
),
933 boolText
= m_doc
.createTextNode("false");
935 matchNode
.setAttribute("target", "font"); // CPD: Is target "font" or "pattern" ????
936 fromTestNode
.setAttribute("qual", "any");
937 fromTestNode
.setAttribute("name", pixel
? "pixelsize" : "size");
938 fromTestNode
.setAttribute("compare", "more_eq");
939 fromTestNode
.appendChild(fromNode
);
940 fromNode
.appendChild(fromText
);
941 toTestNode
.setAttribute("qual", "any");
942 toTestNode
.setAttribute("name", pixel
? "pixelsize" : "size");
943 toTestNode
.setAttribute("compare", "less_eq");
944 toTestNode
.appendChild(toNode
);
945 toNode
.appendChild(toText
);
946 editNode
.setAttribute("mode", "assign");
947 editNode
.setAttribute("name", "antialias");
948 editNode
.appendChild(boolNode
);
949 boolNode
.appendChild(boolText
);
950 matchNode
.appendChild(fromTestNode
);
951 matchNode
.appendChild(toTestNode
);
952 matchNode
.appendChild(editNode
);
954 if(!m_antiAliasing
.node
.isNull())
955 m_doc
.documentElement().removeChild(range
.node
);
956 m_doc
.documentElement().appendChild(matchNode
);
957 range
.node
=matchNode
;
961 void KXftConfig::removeDirs()
963 QDomElement docElem
= m_doc
.documentElement();
964 QList
<ListItem
>::Iterator
it(m_dirs
.begin()),
968 if((*it
).toBeRemoved
&& !(*it
).node
.isNull())
969 docElem
.removeChild((*it
).node
);
972 bool KXftConfig::getAntiAliasing() const
974 return m_antiAliasing
.set
;
977 void KXftConfig::setAntiAliasing( bool set
)
979 if(set
!=m_antiAliasing
.set
)
981 m_antiAliasing
.set
= set
;
982 m_madeChanges
= true;
986 void KXftConfig::applyAntiAliasing()
988 QDomElement matchNode
= m_doc
.createElement("match"),
989 typeNode
= m_doc
.createElement("bool"),
990 editNode
= m_doc
.createElement("edit");
991 QDomText typeText
= m_doc
.createTextNode(m_antiAliasing
.set
? "true" : "false");
993 matchNode
.setAttribute("target", "font");
994 editNode
.setAttribute("mode", "assign");
995 editNode
.setAttribute("name", "antialias");
996 editNode
.appendChild(typeNode
);
997 typeNode
.appendChild(typeText
);
998 matchNode
.appendChild(editNode
);
999 if(!m_antiAliasing
.node
.isNull())
1000 m_doc
.documentElement().removeChild(m_antiAliasing
.node
);
1001 m_doc
.documentElement().appendChild(matchNode
);
1002 m_antiAliasing
.node
=matchNode
;
1005 // KXftConfig only parses one config file, user's .fonts.conf usually.
1006 // If that one doesn't exist, then KXftConfig doesn't know if antialiasing
1007 // is enabled or not. So try to find out the default value from the default font.
1008 // Maybe there's a better way *shrug*.
1009 bool KXftConfig::aliasingEnabled()
1011 FcPattern
*pattern
= FcPatternCreate();
1012 FcConfigSubstitute(0, pattern
, FcMatchPattern
);
1013 FcDefaultSubstitute(pattern
);
1015 FcPattern
*f
= FcFontMatch( 0, pattern
, &result
);
1016 FcBool antialiased
= FcTrue
;
1017 FcPatternGetBool( f
, FC_ANTIALIAS
, 0, &antialiased
);
1018 FcPatternDestroy( f
);
1019 FcPatternDestroy( pattern
);
1020 return antialiased
== FcTrue
;