From 679218d2f4192feaf640bad7891cc63afd13f1e0 Mon Sep 17 00:00:00 2001 From: "erik%netscape.com" Date: Mon, 22 Nov 1999 19:39:13 +0000 Subject: [PATCH] bug 8801; new font enumerator for font prefs UI; r=ftang --- gfx/src/windows/nsFontMetricsWin.cpp | 254 +++++++++++++++++++++++++-- gfx/src/windows/nsFontMetricsWin.h | 15 +- gfx/src/windows/nsGfxFactoryWin.cpp | 6 + 3 files changed, 258 insertions(+), 17 deletions(-) diff --git a/gfx/src/windows/nsFontMetricsWin.cpp b/gfx/src/windows/nsFontMetricsWin.cpp index 459c8794a3db..4225874c7a2e 100644 --- a/gfx/src/windows/nsFontMetricsWin.cpp +++ b/gfx/src/windows/nsFontMetricsWin.cpp @@ -21,6 +21,7 @@ */ #include "nsFontMetricsWin.h" +#include "nsQuickSort.h" #include "prmem.h" #include "plhash.h" @@ -950,6 +951,13 @@ static int CALLBACK enumProc(const LOGFONT* logFont, const TEXTMETRIC* metrics, return 1; } + for (int i = 0; i < nsFontMetricsWin::gGlobalFontsCount; i++) { + if (!strcmp(nsFontMetricsWin::gGlobalFonts[i].logFont.lfFaceName, + logFont->lfFaceName)) { + return 1; + } + } + // XXX make this smarter: don't add font to list if we already have a font // with the same font signature -- erik if (nsFontMetricsWin::gGlobalFontsCount == gGlobalFontsAlloc) { @@ -979,6 +987,7 @@ static int CALLBACK enumProc(const LOGFONT* logFont, const TEXTMETRIC* metrics, font->map = nsnull; font->logFont = *logFont; font->skip = 0; + font->signature = ((NEWTEXTMETRICEX*) metrics)->ntmFontSig; return 1; } @@ -2271,6 +2280,7 @@ struct nsCharSetInfo { char* mName; PRUint16 mCodePage; + char* mLangGroup; void (*GenerateMap)(nsCharSetInfo* aSelf); PRUint8* mMap; }; @@ -2320,21 +2330,21 @@ GenerateMultiByte(nsCharSetInfo* aSelf) static nsCharSetInfo gCharSetInfo[eCharSet_COUNT] = { - { "DEFAULT", 0, GenerateDefault }, - { "ANSI", 1252, GenerateSingleByte }, - { "EASTEUROPE", 1250, GenerateSingleByte }, - { "RUSSIAN", 1251, GenerateSingleByte }, - { "GREEK", 1253, GenerateSingleByte }, - { "TURKISH", 1254, GenerateSingleByte }, - { "HEBREW", 1255, GenerateSingleByte }, - { "ARABIC", 1256, GenerateSingleByte }, - { "BALTIC", 1257, GenerateSingleByte }, - { "THAI", 874, GenerateSingleByte }, - { "SHIFTJIS", 932, GenerateMultiByte }, - { "GB2312", 936, GenerateMultiByte }, - { "HANGEUL", 949, GenerateMultiByte }, - { "CHINESEBIG5", 950, GenerateMultiByte }, - { "JOHAB", 1361, GenerateMultiByte } + { "DEFAULT", 0, "", GenerateDefault }, + { "ANSI", 1252, "x-western", GenerateSingleByte }, + { "EASTEUROPE", 1250, "x-central-euro", GenerateSingleByte }, + { "RUSSIAN", 1251, "x-cyrillic", GenerateSingleByte }, + { "GREEK", 1253, "el", GenerateSingleByte }, + { "TURKISH", 1254, "tr", GenerateSingleByte }, + { "HEBREW", 1255, "he", GenerateSingleByte }, + { "ARABIC", 1256, "ar", GenerateSingleByte }, + { "BALTIC", 1257, "x-baltic", GenerateSingleByte }, + { "THAI", 874, "th", GenerateSingleByte }, + { "SHIFTJIS", 932, "ja", GenerateMultiByte }, + { "GB2312", 936, "zh-CN", GenerateMultiByte }, + { "HANGEUL", 949, "ko", GenerateMultiByte }, + { "CHINESEBIG5", 950, "zh-TW", GenerateMultiByte }, + { "JOHAB", 1361, "ko-XXX", GenerateMultiByte } }; static int @@ -2653,3 +2663,217 @@ nsFontMetricsWinA::FindGlobalFont(HDC aDC, PRUnichar c) return nsnull; } + + +// The Font Enumerator + +nsFontEnumeratorWin::nsFontEnumeratorWin() +{ + NS_INIT_REFCNT(); +} + +NS_IMPL_ISUPPORTS(nsFontEnumeratorWin, + nsCOMTypeInfo::GetIID()); + +static int gInitializedFontEnumerator = 0; + +static int +InitializeFontEnumerator(void) +{ + gInitializedFontEnumerator = 1; + + if (!nsFontMetricsWin::gGlobalFonts) { + HDC dc = ::GetDC(nsnull); + if (!nsFontMetricsWin::InitializeGlobalFonts(dc)) { + ::ReleaseDC(nsnull, dc); + return 0; + } + ::ReleaseDC(nsnull, dc); + } + + return 1; +} + +static int +CompareFontNames(const void* aArg1, const void* aArg2, void* aClosure) +{ + const PRUnichar* str1 = *((const PRUnichar**) aArg1); + const PRUnichar* str2 = *((const PRUnichar**) aArg2); + + // XXX add nsICollation stuff + + return nsCRT::strcmp(str1, str2); +} + +NS_IMETHODIMP +nsFontEnumeratorWin::EnumerateAllFonts(PRUint32* aCount, PRUnichar*** aResult) +{ + if ((!aCount) || (!aResult)) { + return NS_ERROR_NULL_POINTER; + } + + if (!gInitializedFontEnumerator) { + if (!InitializeFontEnumerator()) { + return NS_ERROR_FAILURE; + } + } + + PRUnichar** array = (PRUnichar**) + nsAllocator::Alloc(nsFontMetricsWin::gGlobalFontsCount * sizeof(PRUnichar*)); + if (!array) { + return NS_ERROR_OUT_OF_MEMORY; + } + for (int i = 0; i < nsFontMetricsWin::gGlobalFontsCount; i++) { + PRUnichar* str = nsFontMetricsWin::gGlobalFonts[i].name->ToNewUnicode(); + if (!str) { + for (i = i - 1; i >= 0; i--) { + nsAllocator::Free(array[i]); + } + nsAllocator::Free(array); + return NS_ERROR_OUT_OF_MEMORY; + } + array[i] = str; + } + + NS_QuickSort(array, nsFontMetricsWin::gGlobalFontsCount, sizeof(PRUnichar*), + CompareFontNames, nsnull); + + *aCount = nsFontMetricsWin::gGlobalFontsCount; + *aResult = array; + + return NS_OK; +} + +static int +SignatureMatchesLangGroup(FONTSIGNATURE* aSignature, + const char* aLangGroup) +{ + int dword; + DWORD* array = aSignature->fsCsb; + int i = 0; + for (dword = 0; dword < 2; dword++) { + for (int bit = 0; bit < sizeof(DWORD) * 8; bit++) { + if ((array[dword] >> bit) & 1) { + if (!strcmp(gCharSetInfo[gCharSetToIndex[bitToCharSet[i]]].mLangGroup, + aLangGroup)) { + return 1; + } + } + i++; + } + } + + return 0; +} + +static int +FontMatchesGenericType(nsGlobalFont* aFont, const char* aGeneric, + const char* aLangGroup) +{ + if (!strcmp(aLangGroup, "ja")) { + return 1; + } + else if (!strcmp(aLangGroup, "zh-TW")) { + return 1; + } + else if (!strcmp(aLangGroup, "zh-CN")) { + return 1; + } + else if (!strcmp(aLangGroup, "ko")) { + return 1; + } + else if (!strcmp(aLangGroup, "th")) { + return 1; + } + else if (!strcmp(aLangGroup, "he")) { + return 1; + } + else if (!strcmp(aLangGroup, "ar")) { + return 1; + } + + switch (aFont->logFont.lfPitchAndFamily & 0xF0) { + case FF_DONTCARE: + return 0; + case FF_ROMAN: + if (!strcmp(aGeneric, "serif")) { + return 1; + } + return 0; + case FF_SWISS: + if (!strcmp(aGeneric, "sans-serif")) { + return 1; + } + return 0; + case FF_MODERN: + if (!strcmp(aGeneric, "monospace")) { + return 1; + } + return 0; + case FF_SCRIPT: + if (!strcmp(aGeneric, "cursive")) { + return 1; + } + return 0; + case FF_DECORATIVE: + if (!strcmp(aGeneric, "fantasy")) { + return 1; + } + return 0; + default: + return 0; + } + + return 0; +} + +NS_IMETHODIMP +nsFontEnumeratorWin::EnumerateFonts(const char* aLangGroup, + const char* aGeneric, PRUint32* aCount, PRUnichar*** aResult) +{ + if ((!aLangGroup) || (!aGeneric) || (!aCount) || (!aResult)) { + return NS_ERROR_NULL_POINTER; + } + + if ((!strcmp(aLangGroup, "x-unicode")) || + (!strcmp(aLangGroup, "x-user-def"))) { + return EnumerateAllFonts(aCount, aResult); + } + + if (!gInitializedFontEnumerator) { + if (!InitializeFontEnumerator()) { + return NS_ERROR_FAILURE; + } + } + + PRUnichar** array = (PRUnichar**) + nsAllocator::Alloc(nsFontMetricsWin::gGlobalFontsCount * sizeof(PRUnichar*)); + if (!array) { + return NS_ERROR_OUT_OF_MEMORY; + } + int j = 0; + for (int i = 0; i < nsFontMetricsWin::gGlobalFontsCount; i++) { + if (SignatureMatchesLangGroup(&nsFontMetricsWin::gGlobalFonts[i].signature, + aLangGroup) && + FontMatchesGenericType(&nsFontMetricsWin::gGlobalFonts[i], aGeneric, + aLangGroup)) { + PRUnichar* str = nsFontMetricsWin::gGlobalFonts[i].name->ToNewUnicode(); + if (!str) { + for (j = j - 1; j >= 0; j--) { + nsAllocator::Free(array[j]); + } + nsAllocator::Free(array); + return NS_ERROR_OUT_OF_MEMORY; + } + array[j] = str; + j++; + } + } + + NS_QuickSort(array, j, sizeof(PRUnichar*), CompareFontNames, nsnull); + + *aCount = j; + *aResult = array; + + return NS_OK; +} diff --git a/gfx/src/windows/nsFontMetricsWin.h b/gfx/src/windows/nsFontMetricsWin.h index bf1708ac70f2..5133bd15a2b5 100644 --- a/gfx/src/windows/nsFontMetricsWin.h +++ b/gfx/src/windows/nsFontMetricsWin.h @@ -23,6 +23,7 @@ #include "plhash.h" #include "nsIFontMetrics.h" +#include "nsIFontEnumerator.h" #include "nsFont.h" #include "nsString.h" #include "nsUnitConversion.h" @@ -69,6 +70,7 @@ typedef struct nsGlobalFont LOGFONT logFont; PRUint8* map; PRUint8 skip; + FONTSIGNATURE signature; } nsGlobalFont; class nsFontMetricsWin : public nsIFontMetrics @@ -119,6 +121,8 @@ public: static nsGlobalFont* gGlobalFonts; static int gGlobalFontsCount; + static nsGlobalFont* InitializeGlobalFonts(HDC aDC); + static void SetFontWeight(PRInt32 aWeight, PRUint16* aWeightTable); static PRBool IsFontWeightAvailable(PRInt32 aWeight, PRUint16 aWeightTable); @@ -171,12 +175,19 @@ protected: static PLHashTable* gFamilyNames; static PLHashTable* gFontWeights; - static nsGlobalFont* InitializeGlobalFonts(HDC aDC); - static PRUint8* GetCMAP(HDC aDC, const char* aShortName, int* aIsUnicode); }; +class nsFontEnumeratorWin : public nsIFontEnumerator +{ +public: + nsFontEnumeratorWin(); + NS_DECL_ISUPPORTS + NS_DECL_NSIFONTENUMERATOR +}; + + // The following is a workaround for a Japanse Windows 95 problem. typedef struct nsFontWinA nsFontWinA; diff --git a/gfx/src/windows/nsGfxFactoryWin.cpp b/gfx/src/windows/nsGfxFactoryWin.cpp index 9535edaca972..d0576e89ab45 100644 --- a/gfx/src/windows/nsGfxFactoryWin.cpp +++ b/gfx/src/windows/nsGfxFactoryWin.cpp @@ -35,6 +35,7 @@ #include "nsScriptableRegion.h" static NS_DEFINE_IID(kCFontMetrics, NS_FONT_METRICS_CID); +static NS_DEFINE_IID(kCFontEnumerator, NS_FONT_ENUMERATOR_CID); static NS_DEFINE_IID(kCRenderingContext, NS_RENDERING_CONTEXT_CID); static NS_DEFINE_IID(kCImage, NS_IMAGE_CID); static NS_DEFINE_IID(kCBlender, NS_BLENDER_CID); @@ -200,6 +201,11 @@ nsresult nsGfxFactoryWin::CreateInstance(nsISupports *aOuter, inst = (nsISupports *)scriptableRgn; } } + else if (mClassID.Equals(kCFontEnumerator)) { + nsFontEnumeratorWin* fe; + NS_NEWXPCOM(fe, nsFontEnumeratorWin); + inst = (nsISupports *)fe; + } if (inst == NULL) {