Back to index

lightning-sunbird  0.9+nobinonly
nsUnicodeMappingUtil.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsIServiceManager.h"
00040 #include "nsTextFormatter.h"
00041 #include "nsUnicodeMappingUtil.h"
00042 #include "nsUnicodeFontMappingMac.h"
00043 #include "nsDeviceContextMac.h"
00044 #include "nsReadableUtils.h"
00045 #include "nsString.h"
00046 #include "nsCRT.h"
00047 
00048 static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
00049 
00050 //--------------------------------------------------------------------------
00051 
00052 nsUnicodeMappingUtil *nsUnicodeMappingUtil::gSingleton = nsnull;
00053 //--------------------------------------------------------------------------
00054 
00055 #ifdef DEBUG
00056 static int gUnicodeMappingUtilCount = 0;
00057 #endif
00058 
00059 int PR_CALLBACK nsUnicodeMappingUtil::PrefChangedCallback( const char* aPrefName, void* instance_data)
00060 {
00061        //printf("PrefChangeCallback \n");
00062        nsUnicodeMappingUtil::GetSingleton()->Reset();
00063        return 0;
00064 }
00065 
00066 MOZ_DECL_CTOR_COUNTER(nsUnicodeMappingUtil)
00067 
00068 nsUnicodeMappingUtil::nsUnicodeMappingUtil()
00069 {
00070        Init();
00071        MOZ_COUNT_CTOR(nsUnicodeMappingUtil);
00072 #ifdef DEBUG
00073        ++gUnicodeMappingUtilCount;
00074        NS_ASSERTION(gUnicodeMappingUtilCount == 1, "not singleton");
00075 #endif
00076 }
00077 void nsUnicodeMappingUtil::Reset()
00078 {
00079        CleanUp();
00080        Init();
00081 }
00082 void nsUnicodeMappingUtil::Init()
00083 {
00084        InitGenericFontMapping();
00085        InitFromPref();
00086        InitScriptFontMapping();
00087        InitBlockToScriptMapping();
00088 }
00089 void nsUnicodeMappingUtil::CleanUp()
00090 {
00091        for(int i= 0 ; i < smPseudoTotalScripts; i ++) {
00092               for(int j=0; j < 5; j++) {
00093                      if(mGenericFontMapping[i][j])
00094                       delete mGenericFontMapping[i][j];
00095               }
00096        }
00097 }
00098 //--------------------------------------------------------------------------
00099 
00100 nsUnicodeMappingUtil::~nsUnicodeMappingUtil()
00101 {
00102        CleanUp();
00103 
00104 #ifdef DEBUG
00105        --gUnicodeMappingUtilCount;
00106 #endif
00107        mPref->UnregisterCallback("font.name.", nsUnicodeMappingUtil::PrefChangedCallback, (void*) nsnull);
00108        MOZ_COUNT_DTOR(nsUnicodeMappingUtil);
00109 }
00110 
00111 //--------------------------------------------------------------------------
00112 
00113 void nsUnicodeMappingUtil::InitGenericFontMapping()
00114 {
00115        for(int i= 0 ; i < smPseudoTotalScripts; i ++)
00116               for(int j=0; j < 5; j++)
00117                       mGenericFontMapping[i][j] = nsnull;
00118 
00119        // We probabaly should put the following info into resource ....
00120        // smRoman
00121        mGenericFontMapping[smRoman][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Times") );
00122        mGenericFontMapping[smRoman][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Helvetica") ); // note: MRJ use Geneva for Sans-Serif
00123        mGenericFontMapping[smRoman][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Courier") );
00124        mGenericFontMapping[smRoman][kCursive]   = new nsAutoString( NS_LITERAL_STRING("Zapf Chancery") );
00125        mGenericFontMapping[smRoman][kFantasy]   = new nsAutoString( NS_LITERAL_STRING("New Century Schlbk") );
00126 
00127        // smJapanese
00128        static PRUnichar jfontname1[] = {
00129        0x672C, 0x660E, 0x671D, 0x2212, 0xFF2D, 0x0000 //    –{–¾’©|‚l
00130        };
00131        static PRUnichar jfontname2[] = {
00132        0x4E38, 0x30B4, 0x30B7, 0x30C3, 0x30AF, 0x2212, 0xFF2D, 0x0000 //    ŠÛƒSƒVƒbƒN|‚l
00133        };
00134        static PRUnichar jfontname3[] = {
00135        0x004F, 0x0073, 0x0061, 0x006B, 0x0061, 0x2212, 0x7B49, 0x5E45, 0x0000 //    Osaka|“™•
00136        };   
00137 
00138        mGenericFontMapping[smJapanese][kSerif]     = new nsAutoString(jfontname1);
00139        mGenericFontMapping[smJapanese][kSansSerif] = new nsAutoString(jfontname2); 
00140        mGenericFontMapping[smJapanese][kMonospace] = new nsAutoString(jfontname3);
00141 
00142        // smTradChinese
00143        mGenericFontMapping[smTradChinese][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Apple LiSung Light") );
00144        mGenericFontMapping[smTradChinese][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Apple LiGothic Medium") );
00145        mGenericFontMapping[smTradChinese][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Apple LiGothic Medium") );
00146 
00147        // smKorean
00148        mGenericFontMapping[smKorean][kSerif]     = new nsAutoString( NS_LITERAL_STRING("AppleMyungjo") );
00149        mGenericFontMapping[smKorean][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("AppleGothic") );
00150        mGenericFontMapping[smKorean][kMonospace] = new nsAutoString( NS_LITERAL_STRING("AppleGothic") );
00151 
00152        // smArabic  
00153        mGenericFontMapping[smArabic][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Lucida Grande") );
00154        mGenericFontMapping[smArabic][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Lucida Grande") );
00155        mGenericFontMapping[smArabic][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Monaco") );
00156 
00157        // smHebrew
00158        mGenericFontMapping[smHebrew][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Lucida Grande") );
00159        mGenericFontMapping[smHebrew][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Lucida Grande") );
00160        mGenericFontMapping[smHebrew][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Monaco") );
00161 
00162        // smCyrillic
00163        mGenericFontMapping[smCyrillic][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Latinski") );
00164        mGenericFontMapping[smCyrillic][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Pryamoy Prop") );
00165        mGenericFontMapping[smCyrillic][kMonospace] = new nsAutoString( NS_LITERAL_STRING("APC Courier") );
00166 
00167        // smDevanagari
00168        mGenericFontMapping[smDevanagari][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Devanagari MT") );
00169        mGenericFontMapping[smDevanagari][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Devanagari MT") );
00170        mGenericFontMapping[smDevanagari][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Devanagari MT") );
00171 
00172        // smGurmukhi
00173        mGenericFontMapping[smGurmukhi][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Gurmukhi MT") );
00174        mGenericFontMapping[smGurmukhi][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Gurmukhi MT") );
00175        mGenericFontMapping[smGurmukhi][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Gurmukhi MT") );
00176 
00177        // smGujarati
00178        mGenericFontMapping[smGujarati][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Gujarati MT") );
00179        mGenericFontMapping[smGujarati][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Gujarati MT") );
00180        mGenericFontMapping[smGujarati][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Gujarati MT") );
00181 
00182        // smThai
00183        mGenericFontMapping[smThai][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Thonburi") );
00184        mGenericFontMapping[smThai][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Krungthep") );
00185        mGenericFontMapping[smThai][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Ayuthaya") );
00186 
00187        // smSimpChinese
00188        mGenericFontMapping[smSimpChinese][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Song") );
00189        mGenericFontMapping[smSimpChinese][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Hei") );
00190        mGenericFontMapping[smSimpChinese][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Hei") );
00191 
00192        // smCentralEuroRoman
00193        mGenericFontMapping[smCentralEuroRoman][kSerif]     = new nsAutoString( NS_LITERAL_STRING("Times CE") );
00194        mGenericFontMapping[smCentralEuroRoman][kSansSerif] = new nsAutoString( NS_LITERAL_STRING("Helvetica CE") );
00195        mGenericFontMapping[smCentralEuroRoman][kMonospace] = new nsAutoString( NS_LITERAL_STRING("Courier CE") );
00196 }
00197 //--------------------------------------------------------------------------
00198 
00199 //--------------------------------------------------------------------------
00200 //     nsUnicodeMappingUtil::MapLangGroupToScriptCode
00201 //
00202 //     This method normally returns ScriptCode values, but CAN RETURN pseudo-
00203 //     ScriptCode values for Unicode (32) and User-Defined (33)
00204 //--------------------------------------------------------------------------
00205 ScriptCode nsUnicodeMappingUtil::MapLangGroupToScriptCode(const char* aLangGroup)
00206 {
00207        if(0==nsCRT::strcmp(aLangGroup,  "x-western")) {
00208               return smRoman;
00209        }
00210        if(0==nsCRT::strcmp(aLangGroup,  "x-central-euro")) {
00211               return smCentralEuroRoman;
00212        }
00213        if(0==nsCRT::strcmp(aLangGroup,  "x-cyrillic")) {
00214               return smCyrillic;
00215        }
00216        if(0==nsCRT::strcmp(aLangGroup,  "el")) {
00217               return smGreek;
00218        }
00219        if(0==nsCRT::strcmp(aLangGroup,  "tr")) {
00220               return smRoman;
00221        }
00222        if(0==nsCRT::strcmp(aLangGroup,  "he")) {
00223               return smHebrew;
00224        }
00225        if(0==nsCRT::strcmp(aLangGroup,  "ar")) {
00226               return smArabic;
00227        }
00228        if(0==nsCRT::strcmp(aLangGroup,  "x-baltic")) {
00229               return smRoman;
00230        }
00231        if(0==nsCRT::strcmp(aLangGroup,  "th")) {
00232               return smThai;
00233        }
00234        if(0==nsCRT::strcmp(aLangGroup,  "ja")) {
00235               return smJapanese;
00236        }
00237        if(0==nsCRT::strcmp(aLangGroup,  "zh-CN")) {
00238               return smSimpChinese;
00239        }
00240        if(0==nsCRT::strcmp(aLangGroup,  "ko")) {
00241               return smKorean;
00242        }
00243        if(0==nsCRT::strcmp(aLangGroup,  "zh-TW")) {
00244               return smTradChinese;
00245        }
00246     // No separate script code for zh-HK. Use smTradChinese.
00247        if(0==nsCRT::strcmp(aLangGroup,  "zh-HK")) {
00248               return smTradChinese;
00249        }
00250        if(0==nsCRT::strcmp(aLangGroup,  "x-devanag")) {
00251               return smDevanagari;
00252        }
00253        if(0==nsCRT::strcmp(aLangGroup,  "x-tamil")) {
00254               return smTamil;
00255        }
00256        if(0==nsCRT::strcmp(aLangGroup,  "x-beng")) {
00257               return smBengali;;
00258        }
00259        if(0==nsCRT::strcmp(aLangGroup,  "x-armn")) {
00260               return smArmenian;
00261        }
00262        if(0==nsCRT::strcmp(aLangGroup,  "x-geor")) {
00263               return smGeorgian;;
00264        }
00265        if(0==nsCRT::strcmp(aLangGroup,  "x-gujr")) {
00266               return smGujarati;
00267        }
00268        if(0==nsCRT::strcmp(aLangGroup,  "x-guru")) {
00269               return smGurmukhi;
00270        }
00271        if(0==nsCRT::strcmp(aLangGroup,  "x-mlym")) {
00272               return smMalayalam;
00273        }
00274        if(0==nsCRT::strcmp(aLangGroup,  "x-khmr")) {
00275               return smKhmer;
00276        }
00277        if(0==nsCRT::strcmp(aLangGroup,  "x-ethi")) {
00278               return smEthiopic;
00279        }
00280        if(0==nsCRT::strcmp(aLangGroup,  "x-cans")) {
00281               return (smPseudoUnicode);  // XXX : no script code for UCA
00282        }
00283        if(0==nsCRT::strcmp(aLangGroup,  "x-unicode")) {
00284               return (smPseudoUnicode);
00285        }
00286        if(0==nsCRT::strcmp(aLangGroup,  "x-user-def")) {
00287               return (smPseudoUserDef);
00288        }
00289        {
00290               return smRoman;
00291        }
00292 }
00293 
00294 #define FACESIZE 255 // font name is Str255 in Mac script code
00295 void PR_CALLBACK
00296 nsUnicodeMappingUtil::PrefEnumCallback(const char* aName, void* aClosure)
00297 {      
00298   nsUnicodeMappingUtil* Self = (nsUnicodeMappingUtil*)aClosure;
00299   nsCAutoString curPrefName(aName);
00300   
00301   PRInt32 p1 = curPrefName.RFindChar('.');
00302   if(-1==p1)
00303        return;
00304   PRInt32 p2 = curPrefName.RFindChar('.', p1-1);
00305   if(-1==p1)
00306        return;
00307   
00308   nsCAutoString genName("");
00309   nsCAutoString langGroup("");
00310   
00311   curPrefName.Mid(langGroup,  p1+1, curPrefName.Length()-p1-1);
00312   curPrefName.Mid(genName, p2+1, p1-p2-1);
00313   
00314   ScriptCode script = Self->MapLangGroupToScriptCode(langGroup.get());
00315   if(script >= (smPseudoTotalScripts))
00316   {
00317        // Because of the pseudo-scripts of Unicode and User-Defined, we have to handle
00318        // the expanded ScriptCode value.
00319        return;
00320   }
00321   if((script == smRoman) && !langGroup.Equals(nsCAutoString("x-western"))) {
00322        // need special processing for t,r x-baltic, x-usr-defined
00323        return;
00324   }
00325   
00326   nsString genNameString;
00327   genNameString.AssignWithConversion(genName);
00328   nsGenericFontNameType type = Self->MapGenericFontNameType(genNameString);
00329   if(type >= kUknownGenericFontName)
00330        return;
00331        
00332   char* valueInUTF8 = nsnull;
00333   Self->mPref->CopyCharPref(aName, &valueInUTF8);
00334   if(!valueInUTF8)
00335     return;
00336   if(!*valueInUTF8)
00337   {
00338     Recycle(valueInUTF8);
00339     return;
00340   }
00341   PRUnichar valueInUCS2[FACESIZE]= { 0 };
00342   PRUnichar format[] = { '%', 's', 0 };
00343   PRUint32 n = nsTextFormatter::snprintf(valueInUCS2, FACESIZE, format, valueInUTF8);
00344   Recycle(valueInUTF8);
00345   if(n == 0)
00346        return;     
00347   nsString *fontname = new nsAutoString(valueInUCS2);
00348   if(nsnull == fontname)
00349        return;
00350   if( Self->mGenericFontMapping[script][type] )
00351        delete Self->mGenericFontMapping[script][type];
00352   Self->mGenericFontMapping[script][type] = fontname;
00353 #ifdef DEBUG_ftang_font
00354   char* utf8 = ToNewUTF8String(*fontname);
00355   printf("font %d %d %s= %s\n",script , type, aName,utf8);
00356   if (utf8)
00357     Recycle(utf8); 
00358 #endif
00359 }
00360 void nsUnicodeMappingUtil::InitFromPref()
00361 {
00362   if (!mPref) {
00363     mPref = do_GetService(kPrefCID);
00364     if (!mPref)
00365       return;
00366     mPref->RegisterCallback("font.name.", nsUnicodeMappingUtil::PrefChangedCallback, (void*) nsnull);
00367   }
00368   mPref->EnumerateChildren("font.name.", nsUnicodeMappingUtil::PrefEnumCallback, this);
00369   
00370 }
00371 //--------------------------------------------------------------------------
00372 
00373 void nsUnicodeMappingUtil::InitScriptFontMapping()
00374 {
00375        // Get font from Script manager
00376        for(ScriptCode script = 0; script< smPseudoTotalScripts ; script++)
00377        {
00378               mScriptFontMapping[script] = BAD_FONT_NUM;                     
00379               short fontNum;
00380               if ((smPseudoUnicode == script) || (smPseudoUserDef == script))
00381               {
00382                      char   *theNeededPreference;
00383 
00384                      if (smPseudoUnicode == script)
00385                             theNeededPreference = "font.name.serif.x-unicode";
00386                      else
00387                             theNeededPreference = "font.name.serif.x-user-def";
00388 
00389                      char   *valueInUTF8 = nsnull;
00390 
00391                      mPref->CopyCharPref (theNeededPreference,&valueInUTF8);
00392 
00393                      if (valueInUTF8)
00394                      {
00395                             if (!*valueInUTF8)
00396                                    Recycle (valueInUTF8);
00397                             else
00398                             {
00399                                    PRUnichar     valueInUCS2[FACESIZE]= { 0 };
00400                                    PRUnichar     format[] = { '%', 's', 0 };
00401                                    PRUint32      n = nsTextFormatter::snprintf(valueInUCS2, FACESIZE, format, valueInUTF8);
00402 
00403                                    Recycle (valueInUTF8);
00404                                    if (n != 0)
00405                                    {
00406                                           nsString      *fontname = new nsAutoString (valueInUCS2);
00407 
00408                                           if (nsnull != fontname)
00409                                           {
00410                                                  short  fontID = 0;
00411 
00412                                                  if (nsDeviceContextMac::GetMacFontNumber (*fontname,fontID))
00413                                                         mScriptFontMapping[script] = fontID;
00414 
00415                                                  delete fontname;
00416                                           }
00417                                    }
00418                             }
00419                      }
00420               }
00421               else {
00422                      long fondsize = ::GetScriptVariable(script, smScriptPrefFondSize);
00423                      if (!fondsize)
00424                        fondsize = ::GetScriptVariable(smUnicodeScript, smScriptPrefFondSize);
00425 
00426                      if((fondsize) && ((fondsize >> 16))) {
00427                             fontNum = (fondsize >> 16);
00428                             mScriptFontMapping[script] = fontNum;
00429                      }
00430               }
00431        }
00432 }
00433 //--------------------------------------------------------------------------
00434 void nsUnicodeMappingUtil::InitBlockToScriptMapping()
00435 {
00436        static ScriptCode prebuildMapping[kUnicodeBlockSize] = 
00437        {
00438               // start the fixed section
00439               smGreek,      smCyrillic,          smArmenian, 
00440               smHebrew,     smArabic,     smDevanagari, smBengali,    
00441               smGurmukhi, smGujarati, smOriya,          smTamil,      
00442               smTelugu,     smKannada,    smMalayalam,  smThai,
00443               smLao,        smTibetan,    smGeorgian,          smKorean,
00444               smTradChinese, smEthiopic, smKhmer,
00445               smPseudoUnicode,  // for Unified Canadian Syllable
00446               smPseudoUserDef,
00447               
00448               // start the variable section
00449               smRoman,      smRoman,      smJapanese,   smJapanese,          smJapanese,
00450               smRoman
00451        };
00452        for(PRUint32 i= 0; i < kUnicodeBlockSize; i++) 
00453        {
00454     mBlockToScriptMapping[i] = prebuildMapping[i];
00455   }
00456 }
00457 
00458 //--------------------------------------------------------------------------
00459 nsGenericFontNameType nsUnicodeMappingUtil::MapGenericFontNameType(const nsString& aGenericName)
00460 {
00461        if (aGenericName.LowerCaseEqualsLiteral("serif"))
00462          return kSerif;
00463        if (aGenericName.LowerCaseEqualsLiteral("sans-serif"))
00464          return kSansSerif;
00465        if (aGenericName.LowerCaseEqualsLiteral("monospace"))
00466          return kMonospace;
00467        if (aGenericName.LowerCaseEqualsLiteral("-moz-fixed"))
00468          return kMonospace;
00469        if (aGenericName.LowerCaseEqualsLiteral("cursive"))
00470          return kCursive;
00471        if (aGenericName.LowerCaseEqualsLiteral("fantasy"))
00472          return kFantasy;
00473          
00474        return kUknownGenericFontName;                   
00475 }
00476 
00477 //--------------------------------------------------------------------------
00478 
00479 
00480 //--------------------------------------------------------------------------
00481 
00482 nsUnicodeMappingUtil* nsUnicodeMappingUtil::GetSingleton()
00483 {
00484        if( ! gSingleton)
00485               gSingleton = new nsUnicodeMappingUtil();
00486        return gSingleton;
00487 }
00488 
00489 /* static */ void
00490 nsUnicodeMappingUtil::FreeSingleton()
00491 {
00492     delete gSingleton;
00493     gSingleton = nsnull;
00494 }
00495 
00496 //--------------------------------------------------------------------------