Back to index

lightning-sunbird  0.9+nobinonly
nsFontConfigUtils.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is Christopher Blizzard
00018  * <blizzard@mozilla.org>.  Portions created by the Initial Developer
00019  * are Copyright (C) 2002 the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either of the GNU General Public License Version 2 or later (the "GPL"),
00025  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 #include "nsServiceManagerUtils.h"
00038 #include "nsIPrefService.h"
00039 #include "nsIPrefBranch.h"
00040 #include "nsFontConfigUtils.h"
00041 
00042 const MozGtkLangGroup MozGtkLangGroups[] = {
00043     { "x-western",      (const FcChar8 *)"en" },
00044     { "x-central-euro", (const FcChar8 *)"pl" },
00045     { "x-cyrillic",     (const FcChar8 *)"ru" },
00046     { "x-baltic",       (const FcChar8 *)"lv" },
00047     { "x-devanagari",   (const FcChar8 *)"hi" },
00048     { "x-tamil",        (const FcChar8 *)"ta" },
00049     { "x-armn",         (const FcChar8 *)"hy" },
00050     { "x-beng",         (const FcChar8 *)"bn" },
00051     { "x-cans",         (const FcChar8 *)"iu" },
00052     { "x-ethi",         (const FcChar8 *)"am" },
00053     { "x-geor",         (const FcChar8 *)"ka" },
00054     { "x-gujr",         (const FcChar8 *)"gu" },
00055     { "x-guru",         (const FcChar8 *)"pa" },
00056     { "x-khmr",         (const FcChar8 *)"km" },
00057     { "x-mlym",         (const FcChar8 *)"ml" },
00058     { "x-unicode",                       0    },
00059     { "x-user-def",                      0    },
00060 };
00061 
00062 #define NUM_GTK_LANG_GROUPS (sizeof (MozGtkLangGroups) / \
00063                              sizeof (MozGtkLangGroups[0]))
00064 
00065 static 
00066 void FFREToFamily(nsACString &aFFREName, nsACString &oFamily);
00067 
00068 const MozGtkLangGroup*
00069 NS_FindFCLangGroup (nsACString &aLangGroup)
00070 {
00071     for (unsigned int i=0; i < NUM_GTK_LANG_GROUPS; ++i) {
00072         if (aLangGroup.Equals(MozGtkLangGroups[i].mozLangGroup,
00073                               nsCaseInsensitiveCStringComparator())) {
00074             return &MozGtkLangGroups[i];
00075         }
00076     }
00077 
00078     return nsnull;
00079 }
00080 
00081 int
00082 NS_CalculateSlant(PRUint8 aStyle)
00083 {
00084     int fcSlant;
00085 
00086     switch(aStyle) {
00087     case NS_FONT_STYLE_ITALIC:
00088         fcSlant = FC_SLANT_ITALIC;
00089         break;
00090     case NS_FONT_STYLE_OBLIQUE:
00091         fcSlant = FC_SLANT_OBLIQUE;
00092         break;
00093     default:
00094         fcSlant = FC_SLANT_ROMAN;
00095         break;
00096     }
00097 
00098     return fcSlant;
00099 }
00100 
00101 int
00102 NS_CalculateWeight (PRUint16 aWeight)
00103 {
00104     /*
00105      * weights come in two parts crammed into one
00106      * integer -- the "base" weight is weight / 100,
00107      * the rest of the value is the "offset" from that
00108      * weight -- the number of steps to move to adjust
00109      * the weight in the list of supported font weights,
00110      * this value can be negative or positive.
00111      */
00112     PRInt32 baseWeight = (aWeight + 50) / 100;
00113     PRInt32 offset = aWeight - baseWeight * 100;
00114 
00115     /* clip weights to range 0 to 9 */
00116     if (baseWeight < 0)
00117         baseWeight = 0;
00118     if (baseWeight > 9)
00119         baseWeight = 9;
00120 
00121     /* Map from weight value to fcWeights index */
00122     static int fcWeightLookup[10] = {
00123         0, 0, 0, 0, 1, 1, 2, 3, 3, 4,
00124     };
00125 
00126     PRInt32 fcWeight = fcWeightLookup[baseWeight];
00127 
00128     /*
00129      * adjust by the offset value, make sure we stay inside the
00130      * fcWeights table
00131      */
00132     fcWeight += offset;
00133     if (fcWeight < 0)
00134         fcWeight = 0;
00135     if (fcWeight > 4)
00136         fcWeight = 4;
00137 
00138     /* Map to final FC_WEIGHT value */
00139     static int fcWeights[5] = {
00140         FC_WEIGHT_LIGHT,      /* 0 */
00141         FC_WEIGHT_MEDIUM,     /* 1 */
00142         FC_WEIGHT_DEMIBOLD,   /* 2 */
00143         FC_WEIGHT_BOLD,       /* 3 */
00144         FC_WEIGHT_BLACK,      /* 4 */
00145     };
00146 
00147     return fcWeights[fcWeight];
00148 }
00149 
00150 void
00151 NS_AddLangGroup(FcPattern *aPattern, nsIAtom *aLangGroup)
00152 {
00153     // Find the FC lang group for this lang group
00154     nsCAutoString cname;
00155     aLangGroup->ToUTF8String(cname);
00156 
00157     // see if the lang group needs to be translated from mozilla's
00158     // internal mapping into fontconfig's
00159     const struct MozGtkLangGroup *langGroup;
00160     langGroup = NS_FindFCLangGroup(cname);
00161 
00162     // if there's no lang group, just use the lang group as it was
00163     // passed to us
00164     //
00165     // we're casting away the const here for the strings - should be
00166     // safe.
00167     if (!langGroup)
00168         FcPatternAddString(aPattern, FC_LANG, (FcChar8 *)cname.get());
00169     else if (langGroup->Lang)
00170         FcPatternAddString(aPattern, FC_LANG, (FcChar8 *)langGroup->Lang);
00171 }
00172 
00173 void
00174 NS_AddFFRE(FcPattern *aPattern, nsCString *aFamily, PRBool aWeak)
00175 {
00176     nsCAutoString family;
00177     FFREToFamily(*aFamily, family);
00178 
00179     FcValue v;
00180     v.type = FcTypeString;
00181     // casting away the const here, should be safe
00182     v.u.s = (FcChar8 *)family.get();
00183 
00184     if (aWeak)
00185         FcPatternAddWeak(aPattern, FC_FAMILY, v, FcTrue);
00186     else
00187         FcPatternAdd(aPattern, FC_FAMILY, v, FcTrue);
00188 }
00189 
00190 /* static */
00191 void
00192 FFREToFamily(nsACString &aFFREName, nsACString &oFamily)
00193 {
00194   if (NS_FFRECountHyphens(aFFREName) == 3) {
00195       PRInt32 familyHyphen = aFFREName.FindChar('-') + 1;
00196       PRInt32 registryHyphen = aFFREName.FindChar('-',familyHyphen);
00197       oFamily.Append(Substring(aFFREName, familyHyphen,
00198                                registryHyphen-familyHyphen));
00199   }
00200   else {
00201       oFamily.Append(aFFREName);
00202   }
00203 }
00204 
00205 int
00206 NS_FFRECountHyphens (nsACString &aFFREName)
00207 {
00208     int h = 0;
00209     PRInt32 hyphen = 0;
00210     while ((hyphen = aFFREName.FindChar('-', hyphen)) >= 0) {
00211         ++h;
00212         ++hyphen;
00213     }
00214     return h;
00215 }
00216 
00217 inline static void 
00218 AddFFREandLog(FcPattern *aPattern, nsCString aFamily,
00219               const PRLogModuleInfo *aLogModule)
00220 {
00221     // we ignore prefs that have three hypens since they are X
00222     // style prefs.
00223     if (NS_FFRECountHyphens(aFamily) >= 3)
00224         return;
00225 
00226     if (aLogModule && PR_LOG_TEST(aLogModule, PR_LOG_DEBUG)) {
00227         printf("\tadding generic font from preferences: %s\n",
00228                aFamily.get());
00229     }
00230 
00231     NS_AddFFRE(aPattern, &aFamily, PR_FALSE);
00232 }
00233 
00234 // Add prefs (font.name.[generic].[lang] and font.name-list.[generic].[lang])
00235 // for the generic if they're set.
00236 void 
00237 NS_AddGenericFontFromPref(const nsCString *aGenericFont,
00238                           nsIAtom *aLangGroup, FcPattern *aPattern, 
00239                           const PRLogModuleInfo *aLogModule)
00240 {
00241     nsCOMPtr<nsIPrefService> prefService;
00242     prefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
00243     if (!prefService)
00244         return;
00245     nsCOMPtr<nsIPrefBranch> pref;
00246     if (NS_FAILED(prefService->GetBranch("font.", getter_AddRefs(pref))))
00247         return;
00248 
00249     nsCAutoString genericDotLangGroup(aGenericFont->get());
00250     genericDotLangGroup.Append('.');
00251     nsAutoString langGroup;
00252     aLangGroup->ToString(langGroup);
00253     LossyAppendUTF16toASCII(langGroup, genericDotLangGroup);
00254 
00255     nsCAutoString name("name.");
00256     name.Append(genericDotLangGroup);
00257 
00258     // prefs file always uses (must use) UTF-8 and fontconfig
00259     // expects to get a UTF-8 string so that using |GetCharPref|
00260     // is fine.
00261     nsresult rv;
00262     nsXPIDLCString value;
00263     rv = pref->GetCharPref(name.get(), getter_Copies(value));
00264 
00265     if (NS_SUCCEEDED(rv)) {
00266         AddFFREandLog(aPattern, value, aLogModule);
00267     }
00268 
00269     nsCAutoString nameList("name-list.");
00270     nameList.Append(genericDotLangGroup);
00271     rv = pref->GetCharPref(nameList.get(), getter_Copies(value));
00272 
00273     if (NS_SUCCEEDED(rv)) {
00274         PRInt32 prevCommaPos = -1;
00275         PRInt32 commaPos; 
00276         nsCAutoString family;
00277 
00278         while ((commaPos = value.FindChar(',', prevCommaPos + 1)) > 0) {
00279             family = Substring(value, prevCommaPos + 1, 
00280                                commaPos - prevCommaPos - 1);
00281             prevCommaPos = commaPos;
00282             AddFFREandLog(aPattern, family, aLogModule);
00283         }
00284 
00285         family = Substring(value, prevCommaPos + 1);
00286         AddFFREandLog(aPattern, family, aLogModule);
00287     }
00288 }