r=pedemonte, a=blizzard
OK, here's the major font checkin. There's some debug code in here.
This commit is contained in:
mkaply%us.ibm.com 2000-10-02 19:00:52 +00:00
Родитель 69cf2ac5bc
Коммит 37770f863b
5 изменённых файлов: 677 добавлений и 257 удалений

Просмотреть файл

@ -23,12 +23,20 @@
// Revision by someone who *really* understands OS/2 fonts.
#include "nsGfxDefs.h"
#include "nsDeviceContextOS2.h"
#include "nsIPref.h"
#include "nsIServiceManager.h"
#include "nsICharsetConverterManager.h"
#include "nsICharsetConverterManager2.h"
#include "nsICharRepresentable.h"
#include "nsFontMetricsOS2.h"
#include "nsString.h"
#include "nsFont.h"
#include "nsQuickSort.h"
#include "nsTextFormatter.h"
#include "prmem.h"
#include "plhash.h"
#include "prprf.h"
#undef USER_DEFINED
#define USER_DEFINED "x-user-def"
enum nsCharSet
{
@ -59,26 +67,53 @@ struct nsCharSetInfo
PRUint32* mMap;
};
static PRUint32 gUserDefinedMap[2048];
static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
static NS_DEFINE_IID(kIFontMetricsIID, NS_IFONT_METRICS_IID);
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
nsGlobalFont* nsFontMetricsOS2::gGlobalFonts = nsnull;
static int gGlobalFontsAlloc = 0;
int nsFontMetricsOS2::gGlobalFontsCount = 0;
PLHashTable* nsFontMetricsOS2::gFontMaps = nsnull;
PLHashTable* nsFontMetricsOS2::gFamilyNames = nsnull;
//-- Font weight
PLHashTable* nsFontMetricsOS2::gFontWeights = nsnull;
#define NS_MAX_FONT_WEIGHT 900
#define NS_MIN_FONT_WEIGHT 100
#undef CHAR_BUFFER_SIZE
#define CHAR_BUFFER_SIZE 1024
static nsICharsetConverterManager2* gCharSetManager = nsnull;
static nsIPref* gPref = nsnull;
static nsIUnicodeEncoder* gUserDefinedConverter = nsnull;
static nsIAtom* gUserDefined = nsnull;
static int gFontMetricsOS2Count = 0;
static int gInitialized = 0;
static PRUint32 gUserDefinedMap[2048];
static nsCharSetInfo gCharSetInfo[eCharSet_COUNT] =
{
{ "DEFAULT", 0, 0, "" },
{ "ANSI", FM_DEFN_LATIN1, 1252, "x-western" },
{ "EASTEUROPE", FM_DEFN_LATIN2, 1250, "x-central-euro" },
{ "RUSSIAN", FM_DEFN_CYRILLIC, 1251, "x-cyrillic" },
{ "GREEK", FM_DEFN_GREEK, 1253, "el" },
{ "GREEK", FM_DEFN_GREEK, 813, "el" },
{ "TURKISH", 0, 1254, "tr" },
{ "HEBREW", FM_DEFN_HEBREW, 1255, "he" },
{ "ARABIC", FM_DEFN_ARABIC, 1256, "ar" },
{ "BALTIC", 0, 1257, "x-baltic" },
{ "THAI", FM_DEFN_THAI, 874, "th" },
{ "SHIFTJIS", FM_DEFN_KANA, 932, "ja" },
{ "GB2312", FM_DEFN_KANA, 936, "zh-CN" },
// { "GB2312", FM_DEFN_KANA, 936, "zh-CN" },
{ "GB2312", FM_DEFN_KANA, 1386, "zh-CN" },
{ "HANGEUL", FM_DEFN_KANA, 949, "ko" },
{ "CHINESEBIG5", FM_DEFN_KANA, 950, "zh-TW" },
{ "JOHAB", FM_DEFN_KANA, 1361, "ko-XXX", }
@ -100,10 +135,52 @@ void nsFontHandleOS2::SelectIntoPS( HPS hps, long lcid)
PMERROR("GpiSetCharSet");
}
static void
FreeGlobals(void)
{
// XXX complete this
gInitialized = 0;
NS_IF_RELEASE(gCharSetManager);
NS_IF_RELEASE(gPref);
NS_IF_RELEASE(gUserDefined);
NS_IF_RELEASE(gUserDefinedConverter);
}
static nsresult
InitGlobals(void)
{
nsServiceManager::GetService(kCharsetConverterManagerCID,
NS_GET_IID(nsICharsetConverterManager2), (nsISupports**) &gCharSetManager);
if (!gCharSetManager) {
FreeGlobals();
return NS_ERROR_FAILURE;
}
nsServiceManager::GetService(kPrefCID, NS_GET_IID(nsIPref),
(nsISupports**) &gPref);
if (!gPref) {
FreeGlobals();
return NS_ERROR_FAILURE;
}
gUserDefined = NS_NewAtom(USER_DEFINED);
if (!gUserDefined) {
FreeGlobals();
return NS_ERROR_OUT_OF_MEMORY;
}
gInitialized = 1;
return NS_OK;
}
nsFontMetricsOS2::nsFontMetricsOS2()
{
// members are zeroed by new operator (hmm)
NS_INIT_REFCNT();
++gFontMetricsOS2Count;
// members are zeroed by new operator (hmm) - yeah right
mTriedAllGenerics = 0;
}
nsFontMetricsOS2::~nsFontMetricsOS2()
@ -112,16 +189,26 @@ nsFontMetricsOS2::~nsFontMetricsOS2()
delete mFont;
delete mFontHandle;
if (0 == --gFontMetricsOS2Count) {
FreeGlobals();
}
}
NS_IMPL_ISUPPORTS( nsFontMetricsOS2, nsIFontMetrics::GetIID())
nsresult nsFontMetricsOS2::Init( const nsFont &aFont, nsIAtom* aLangGroup, nsIDeviceContext *aContext)
{
nsresult res;
if (!gInitialized) {
res = InitGlobals();
if (NS_FAILED(res)) {
return res;
}
}
mFont = new nsFont( aFont);
mLangGroup = aLangGroup;
// mIndexOfSubstituteFont = -1;
mContext = (nsDeviceContextOS2 *) aContext;
mDeviceContext = (nsDeviceContextOS2 *) aContext;
nsresult rv = RealizeFont();
return rv;
}
@ -131,73 +218,287 @@ nsresult nsFontMetricsOS2::Destroy()
return NS_OK;
}
// Map CSS font names to something we can understand locally.
// Some conversions are a bit dodgy (fantasy) but there's little option, I
// guess.
// Surely this should be in XP code somewhere?
static void MapGenericFamilyToFont( const nsString &aGenericFamily,
nsIDeviceContext *aDC,
nsString &aFontFace)
static PLHashNumber PR_CALLBACK
HashKey(const void* aString)
{
// the CSS generic names (conversions from Nav for now)
// XXX this need to check availability with the dc
PRBool aliased;
nsAutoString timesRoman; timesRoman.AssignWithConversion("Tms Rmn");
nsAutoString helv; helv.AssignWithConversion("Helv");
nsAutoString script; script.AssignWithConversion("Script");
nsAutoString arial; arial.AssignWithConversion("Arial");
nsAutoString courier; courier.AssignWithConversion("Courier");
if( aGenericFamily.EqualsIgnoreCase( "serif"))
aDC->GetLocalFontName( timesRoman, aFontFace, aliased);
else if( aGenericFamily.EqualsIgnoreCase( "sans-serif"))
aDC->GetLocalFontName( helv, aFontFace, aliased);
else if( aGenericFamily.EqualsIgnoreCase( "Helv")) // !!
aDC->GetLocalFontName( script, aFontFace, aliased);
else if( aGenericFamily.EqualsIgnoreCase( "fantasy")) // !!
aDC->GetLocalFontName( arial, aFontFace, aliased);
else if( aGenericFamily.EqualsIgnoreCase( "monospace"))
aDC->GetLocalFontName( courier, aFontFace, aliased);
else
aFontFace.Truncate();
const nsString* str = (const nsString*)aString;
return (PLHashNumber)
nsCRT::HashCode(str->GetUnicode());
}
struct FontEnumData
static PRIntn PR_CALLBACK
CompareKeys(const void* aStr1, const void* aStr2)
{
FontEnumData( nsIDeviceContext* aContext, char* aFaceName)
: mContext( aContext), mFaceName( aFaceName)
{}
return nsCRT::strcmp(((const nsString*) aStr1)->GetUnicode(),
((const nsString*) aStr2)->GetUnicode()) == 0;
}
nsFontOS2*
nsFontMetricsOS2::LoadFont(HPS aPS, nsString* aName)
{
nsFontOS2* font = nsnull;
char fontName[FACESIZE];
WideCharToMultiByte(0, aName->GetUnicode(), aName->Length() + 1,
fontName, sizeof(fontName));
long lWant = 0;
long lFonts = GpiQueryFonts( aPS, QF_PUBLIC | QF_PRIVATE,
fontName, &lWant, 0, 0);
if (lFonts > 0) {
font = new nsFontOS2();
aName->ToCString(font->mName, sizeof(font->mName));
}
return font;
}
nsIDeviceContext *mContext;
char *mFaceName;
nsFontOS2*
nsFontMetricsOS2::FindUserDefinedFont(HPS aPS, PRUnichar aChar)
{
if (mIsUserDefined) {
nsFontOS2* font = LoadFont(aPS, &mUserDefined);
#ifdef XP_OS2
if (font) {
#else
if (font && FONT_HAS_GLYPH(font->mMap, aChar)) {
#endif
return font;
}
}
return nsnull;
}
typedef struct nsFontFamilyName
{
char* mName;
char* mWinName;
} nsFontFamilyName;
static nsFontFamilyName gFamilyNameTable[] =
{
#ifdef MOZ_MATHML
{ "-moz-math-text", "Times New Roman" },
{ "-moz-math-symbol", "Symbol" },
#endif
{ "times", "Times New Roman" },
{ "times roman", "Times New Roman" },
{ "times new roman", "Times New Roman" },
{ "arial", "Arial" },
{ "helvetica", "Helv" },
{ "courier", "Courier" },
{ "courier new", "Courier New" },
{ nsnull, nsnull }
};
// callback for each of the faces in the nsFont (use the first we can match)
static PRBool FontEnumCallback( const nsString& aFamily, PRBool aGeneric, void *aData)
PLHashTable*
nsFontMetricsOS2::InitializeFamilyNames(void)
{
FontEnumData *data = (FontEnumData*)aData;
PRBool rc = PR_TRUE;
if( aGeneric)
{
nsAutoString realFace;
MapGenericFamilyToFont( aFamily, data->mContext, realFace);
realFace.ToCString( data->mFaceName, FACESIZE);
rc = PR_FALSE; // stop
}
else
{
nsAutoString realFace;
PRBool aliased;
data->mContext->GetLocalFontName( aFamily, realFace, aliased);
if( aliased || (NS_OK == data->mContext->CheckFontExistence( realFace)))
{
realFace.ToCString(data->mFaceName, FACESIZE);
rc = PR_FALSE; // stop
static int gInitializedFamilyNames = 0;
if (!gInitializedFamilyNames) {
gInitializedFamilyNames = 1;
gFamilyNames = PL_NewHashTable(0, HashKey, CompareKeys, nsnull, nsnull,
nsnull);
if (!gFamilyNames) {
return nsnull;
}
nsFontFamilyName* f = gFamilyNameTable;
while (f->mName) {
nsString* name = new nsString;
nsString* winName = new nsString;
if (name && winName) {
name->AssignWithConversion(f->mName);
winName->AssignWithConversion(f->mWinName);
PL_HashTableAdd(gFamilyNames, name, (void*) winName);
}
}
f++;
}
}
return PR_TRUE;
return gFamilyNames;
}
nsFontOS2*
nsFontMetricsOS2::FindLocalFont(HPS aPS, PRUnichar aChar)
{
if (!gFamilyNames) {
if (!InitializeFamilyNames()) {
return nsnull;
}
}
while (mFontsIndex < mFonts.Count()) {
if (mFontIsGeneric[mFontsIndex]) {
return nsnull;
}
nsString* name = mFonts.StringAt(mFontsIndex++);
nsAutoString low(*name);
low.ToLowerCase();
nsString* winName = (nsString*) PL_HashTableLookup(gFamilyNames, &low);
if (!winName) {
winName = name;
}
nsFontOS2* font = LoadFont(aPS, winName);
#ifdef XP_OS2
if (font) {
#else
if (font && FONT_HAS_GLYPH(font->mMap, aChar)) {
#endif
return font;
}
}
return nsnull;
}
nsFontOS2*
nsFontMetricsOS2::LoadGenericFont(HPS aPS, PRUnichar aChar, char** aName)
{
if (*aName) {
int found = 0;
int i;
#ifndef XP_OS2
for (i = 0; i < mLoadedFontsCount; i++) {
nsFontOS2* font = mLoadedFonts[i];
if (!strcmp(font->mName, *aName)) {
found = 1;
break;
}
}
if (found) {
nsMemory::Free(*aName);
*aName = nsnull;
return nsnull;
}
#endif
PRUnichar name[FACESIZE] = { 0 };
PRUnichar format[] = { '%', 's', 0 };
PRUint32 n = nsTextFormatter::snprintf(name, FACESIZE, format, *aName);
nsMemory::Free(*aName);
*aName = nsnull;
if (n && (n != (PRUint32) -1)) {
nsAutoString fontName(name);
nsFontOS2* font = LoadFont(aPS, &fontName);
#ifdef XP_OS2
if (font) {
#else
if (font && FONT_HAS_GLYPH(font->mMap, aChar)) {
#endif
return font;
}
}
}
return nsnull;
}
typedef struct PrefEnumInfo
{
PRUnichar mChar;
HPS mPS;
nsFontOS2* mFont;
nsFontMetricsOS2* mMetrics;
} PrefEnumInfo;
void
PrefEnumCallback(const char* aName, void* aClosure)
{
PrefEnumInfo* info = (PrefEnumInfo*) aClosure;
if (info->mFont) {
return;
}
PRUnichar ch = info->mChar;
HPS ps = info->mPS;
nsFontMetricsOS2* metrics = info->mMetrics;
char* value = nsnull;
gPref->CopyCharPref(aName, &value);
nsFontOS2* font = metrics->LoadGenericFont(ps, ch, &value);
if (font) {
info->mFont = font;
}
else {
gPref->CopyDefaultCharPref(aName, &value);
font = metrics->LoadGenericFont(ps, ch, &value);
if (font) {
info->mFont = font;
}
}
}
nsFontOS2*
nsFontMetricsOS2::FindGenericFont(HDC aPS, PRUnichar aChar)
{
if (mTriedAllGenerics) {
return nsnull;
}
nsAutoString prefix;
prefix.AssignWithConversion("font.name.");
prefix.Append(*mGeneric);
char name[128];
if (mLangGroup) {
nsAutoString pref = prefix;
pref.AppendWithConversion('.');
const PRUnichar* langGroup = nsnull;
mLangGroup->GetUnicode(&langGroup);
pref.Append(langGroup);
pref.ToCString(name, sizeof(name));
char* value = nsnull;
gPref->CopyCharPref(name, &value);
nsFontOS2* font = LoadGenericFont(aPS, aChar, &value);
if (font) {
return font;
}
gPref->CopyDefaultCharPref(name, &value);
font = LoadGenericFont(aPS, aChar, &value);
if (font) {
return font;
}
}
prefix.ToCString(name, sizeof(name));
PrefEnumInfo info = { aChar, aPS, nsnull, this };
gPref->EnumerateChildren(name, PrefEnumCallback, &info);
if (info.mFont) {
return info.mFont;
}
mTriedAllGenerics = 1;
return nsnull;
}
nsFontOS2*
nsFontMetricsOS2::FindFont(HPS aPS, PRUnichar aChar)
{
nsFontOS2* font = FindUserDefinedFont(aPS, aChar);
if (!font) {
font = FindLocalFont(aPS, aChar);
if (!font) {
font = FindGenericFont(aPS, aChar);
#ifndef XP_OS2
if (!font) {
font = FindGlobalFont(aPS, aChar);
if (!font) {
font = FindSubstituteFont(aPS, aChar);
}
}
#endif
}
}
return font;
}
static PRBool
FontEnumCallback(const nsString& aFamily, PRBool aGeneric, void *aData)
{
nsFontMetricsOS2* metrics = (nsFontMetricsOS2*) aData;
metrics->mFonts.AppendString(aFamily);
metrics->mFontIsGeneric.AppendElement((void*) aGeneric);
if (aGeneric) {
metrics->mGeneric = metrics->mFonts.StringAt(metrics->mFonts.Count() - 1);
return PR_FALSE; // stop
}
return PR_TRUE; // don't stop
}
// Current strategy wrt. image/outline fonts:
@ -231,26 +532,99 @@ static PFONTMETRICS getMetrics( long &lFonts, PCSZ facename, HPS hps)
nsresult nsFontMetricsOS2::RealizeFont()
{
nsresult res;
HWND win = NULL;
HDC ps = NULL;
if (NULL != mDeviceContext->mDC){
ps = mDeviceContext->mPS;
} else {
win = (HWND)mDeviceContext->mWidget;
ps = ::WinGetPS(win);
}
mFont->EnumerateFamilies(FontEnumCallback, this);
PRUnichar* value = nsnull;
if (!mGeneric) {
gPref->CopyUnicharPref("font.default", &value);
if (value) {
mDefaultFont = value;
nsMemory::Free(value);
value = nsnull;
}
else {
mDefaultFont.AssignWithConversion("serif");
}
mGeneric = &mDefaultFont;
}
#ifndef XP_OS2
if (mLangGroup.get() == gUserDefined) {
if (!gUserDefinedConverter) {
nsCOMPtr<nsIAtom> charset;
res = gCharSetManager->GetCharsetAtom2("x-user-defined",
getter_AddRefs(charset));
if (NS_SUCCEEDED(res)) {
res = gCharSetManager->GetUnicodeEncoder(charset,
&gUserDefinedConverter);
if (NS_SUCCEEDED(res)) {
res = gUserDefinedConverter->SetOutputErrorBehavior(
gUserDefinedConverter->kOnError_Replace, nsnull, '?');
nsCOMPtr<nsICharRepresentable> mapper =
do_QueryInterface(gUserDefinedConverter);
if (mapper) {
res = mapper->FillInfo(gUserDefinedMap);
}
}
else {
return res;
}
}
else {
return res;
}
}
nsCAutoString name("font.name.");
name.AppendWithConversion(*mGeneric);
name.Append('.');
name.Append(USER_DEFINED);
gPref->CopyUnicharPref(name.GetBuffer(), &value);
if (value) {
mUserDefined = value;
nsMemory::Free(value);
value = nsnull;
mIsUserDefined = 1;
}
}
#endif
nsFontOS2* font = FindFont(ps, 'a');
if (!font) {
return NS_ERROR_FAILURE;
}
char szFamily[FACESIZE] = "";
strcpy(szFamily, font->mName);
delete font;
if (!strcmp(szFamily, "Verdana")) {
return NS_ERROR_FAILURE;
} /* endif */
nsFontHandleOS2 *fh = new nsFontHandleOS2;
if (!fh)
return NS_ERROR_OUT_OF_MEMORY;
// 1) Find family name
char szFamily[ FACESIZE] = "";
FontEnumData data( mContext, szFamily);
mFont->EnumerateFamilies( FontEnumCallback, &data);
// sanity check - no way of telling whether we want a fixed or prop font..
if( !szFamily[0])
strcpy( szFamily, "System Proportional");
// 2) Get a representative PS for doing font queries into
HPS hps;
if (NULL != mContext->mDC){
hps = mContext->mPS;
if (NULL != mDeviceContext->mDC){
hps = mDeviceContext->mPS;
} else {
hps = WinGetPS((HWND)mContext->mWidget);
hps = WinGetPS((HWND)mDeviceContext->mWidget);
}
// 3) Work out what our options are wrt. image/outline, prefer image.
@ -293,19 +667,32 @@ nsresult nsFontMetricsOS2::RealizeFont()
// 6) Encoding
// There doesn't seem to be any encoding stuff yet, so guess.
// (XXX unicode hack; use same codepage as converter!)
fh->fattrs.usCodePage = gModuleData.ulCodepage;
char name[128];
const PRUnichar* langGroup = nsnull;
mLangGroup->GetUnicode(&langGroup);
nsAutoString langName = langGroup;
langName.ToCString(name, sizeof(name));
for (int j=0; j < eCharSet_COUNT; j++ ) {
if (name[0] == gCharSetInfo[j].mLangGroup[0]) {
if (!strcmp(name, gCharSetInfo[j].mLangGroup)) {
fh->fattrs.usCodePage = gCharSetInfo[j].mCodePage;
mCodePage = gCharSetInfo[j].mCodePage;
} /* endif */
} /* endif */
} /* endfor */
// fh->fattrs.usCodePage = gModuleData.ulCodepage;
// 7) Find the point size for the font, and set up the charbox too
float app2dev, app2twip, twip2dev;
mContext->GetAppUnitsToDevUnits( app2dev);
mContext->GetDevUnitsToTwips( app2twip);
mContext->GetTwipsToDevUnits( twip2dev);
mDeviceContext->GetAppUnitsToDevUnits( app2dev);
mDeviceContext->GetDevUnitsToTwips( app2twip);
mDeviceContext->GetTwipsToDevUnits( twip2dev);
// !! Windows wants to mply up here. I don't think I do. If fonts
// !! ever begin to look `squished', try enabling the following code
#if 0
float scale;
mContext->GetCanonicalPixelScale(scale);
mDeviceContext->GetCanonicalPixelScale(scale);
app2twip *= app2dev * scale;
#else
app2twip *= app2dev;
@ -378,7 +765,7 @@ nsresult nsFontMetricsOS2::RealizeFont()
GpiQueryFontMetrics( hps, sizeof fm, &fm);
float dev2app;
mContext->GetDevUnitsToAppUnits( dev2app);
mDeviceContext->GetDevUnitsToAppUnits( dev2app);
// PM includes the internal leading in the max ascender. So the max
// ascender we tell raptor about should be lMaxAscent - lInternalLeading.
@ -416,7 +803,7 @@ nsresult nsFontMetricsOS2::RealizeFont()
GpiSetCharSet( hps, LCID_DEFAULT);
if( !GpiDeleteSetId( hps, 1))
PMERROR( "GpiDeleteSetID (FM)");
if (NULL == mContext->mDC)
if (NULL == mDeviceContext->mDC)
WinReleasePS(hps);
return NS_OK;
@ -618,7 +1005,8 @@ nsFontMetricsOS2::InitializeGlobalFonts(HPS aPS)
}
}
nsGlobalFont* font = &nsFontMetricsOS2::gGlobalFonts[nsFontMetricsOS2::gGlobalFontsCount++];
nsGlobalFont* font = &nsFontMetricsOS2::gGlobalFonts[nsFontMetricsOS2::gGlobalFontsCount];
nsFontMetricsOS2::gGlobalFontsCount++;
// PRUnichar name[FACESIZE*2];
// name[0] = 0;
@ -627,6 +1015,7 @@ nsFontMetricsOS2::InitializeGlobalFonts(HPS aPS)
font->name->AssignWithConversion(pFontMetrics[i].szFamilyname);
if (!font->name) {
nsFontMetricsOS2::gGlobalFontsCount--;
continue;
}
font->map = nsnull;
font->fontMetrics = pFontMetrics[i];
@ -635,6 +1024,7 @@ nsFontMetricsOS2::InitializeGlobalFonts(HPS aPS)
nsFontMetricsOS2::gGlobalFonts[i].signature = pFontMetrics[i].fsDefn;
} /* endwhile */
gInitializedGlobalFonts = 1;
nsMemory::Free(pFontMetrics);
}
return gGlobalFonts;
@ -683,6 +1073,32 @@ CompareFontNames(const void* aArg1, const void* aArg2, void* aClosure)
NS_IMETHODIMP
nsFontEnumeratorOS2::EnumerateAllFonts(PRUint32* aCount, PRUnichar*** aResult)
{
#ifndef XP_OS2
*aCount = 18;
PRUnichar** newarray = (PRUnichar**)
nsMemory::Alloc(18 * sizeof(PRUnichar*));
newarray[0] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[1] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[2] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[3] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[4] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[5] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[6] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[7] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[8] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[9] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[10] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[11] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[12] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[13] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[14] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[15] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[16] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[17] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
*aResult = newarray;
return NS_OK;
#endif
if (aCount) {
*aCount = 0;
}
@ -816,6 +1232,33 @@ NS_IMETHODIMP
nsFontEnumeratorOS2::EnumerateFonts(const char* aLangGroup,
const char* aGeneric, PRUint32* aCount, PRUnichar*** aResult)
{
#ifndef XP_OS2
*aCount = 18;
PRUnichar** newarray = (PRUnichar**)
nsMemory::Alloc(18 * sizeof(PRUnichar*));
newarray[0] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[1] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[2] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[3] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[4] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[5] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[6] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[7] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[8] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[9] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[10] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[11] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[12] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[13] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[14] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[15] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[16] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
newarray[17] = nsString(NS_ConvertASCIItoUCS2("Tms Rmn")).ToNewUnicode();
*aResult = newarray;
return NS_OK;
#endif
if ((!aLangGroup) || (!aGeneric)) {
return NS_ERROR_NULL_POINTER;
}

Просмотреть файл

@ -30,16 +30,21 @@
#ifndef _nsFontMetricsOS2_h
#define _nsFontMetricsOS2_h
#define INCL_WIN
#define INCL_GPI
#include <os2.h>
#include "plhash.h"
#include "nsIFontMetrics.h"
#include "nsIFontEnumerator.h"
#include "nsFont.h"
#include "nsString.h"
#include "nsUnitConversion.h"
#include "nsIDeviceContext.h"
#include "nsCRT.h"
#include "nsIAtom.h"
#include "nsCOMPtr.h" //HCT-M15
class nsIRenderingContext;
class nsDeviceContextOS2;
class nsString;
#include "nsDeviceContextOS2.h"
#include "nsCOMPtr.h"
#include "nsVoidArray.h"
// An nsFontHandle is actually a pointer to one of these.
// It knows how to select itself into a ps.
@ -70,6 +75,13 @@ struct nsFontHandleOS2
#define FM_DEFN_UGL1105 0x3FF0 /* Chars in bitmap fonts */
#endif
class nsFontOS2
{
public:
char mName[FACESIZE];
};
typedef struct nsGlobalFont
{
nsString* name;
@ -113,6 +125,16 @@ class nsFontMetricsOS2 : public nsIFontMetrics
NS_IMETHOD GetLangGroup(nsIAtom** aLangGroup);
NS_IMETHOD GetFontHandle( nsFontHandle &aHandle);
#ifndef XP_OS2
virtual nsFontOS2* FindGlobalFont(HPS aPS, PRUnichar aChar);
#endif
virtual nsFontOS2* FindGenericFont(HPS aPS, PRUnichar aChar);
virtual nsFontOS2* FindLocalFont(HPS aPS, PRUnichar aChar);
virtual nsFontOS2* FindUserDefinedFont(HPS aPS, PRUnichar aChar);
nsFontOS2* FindFont(HPS aPS, PRUnichar aChar);
virtual nsFontOS2* LoadGenericFont(HPS aPS, PRUnichar aChar, char** aName);
virtual nsFontOS2* LoadFont(HPS aPS, nsString* aName);
// for drawing text
PRUint32 GetDevMaxAscender() const { return mDevMaxAscent; }
nscoord GetSpaceWidth( nsIRenderingContext *aRContext);
@ -122,6 +144,7 @@ class nsFontMetricsOS2 : public nsIFontMetrics
static int gGlobalFontsCount;
static nsGlobalFont* InitializeGlobalFonts(HPS aPS);
int mCodePage;
protected:
nsresult RealizeFont();
@ -148,10 +171,24 @@ class nsFontMetricsOS2 : public nsIFontMetrics
PRUint32 mDevMaxAscent;
nsFontHandleOS2 *mFontHandle;
nsDeviceContextOS2 *mContext; // sigh.. broken broken broken XP interfaces...
nsDeviceContextOS2 *mDeviceContext;
nsCOMPtr<nsIAtom> mLangGroup;
public:
nsStringArray mFonts;
PRUint16 mFontsIndex;
nsVoidArray mFontIsGeneric;
nsAutoString mDefaultFont;
nsString *mGeneric;
nsCOMPtr<nsIAtom> mLangGroup;
nsAutoString mUserDefined;
PRUint8 mTriedAllGenerics;
PRUint8 mIsUserDefined;
protected:
static PLHashTable* InitializeFamilyNames(void);
static PLHashTable* gFamilyNames;
static PLHashTable* gFontWeights;
};
class nsFontEnumeratorOS2 : public nsIFontEnumerator

Просмотреть файл

@ -39,6 +39,33 @@ void PMERROR(const char *str);
class nsString;
class nsIDeviceContext;
struct nsUconvInfo
{
char* mCharset;
PRUint16 mCodePage;
UconvObject mConverter;
};
static nsUconvInfo gUconvInfo[15 /* eCharSet_COUNT from nsFontMetricsOS2.cpp */ ] =
{
{ "DEFAULT", 0, NULL },
{ "ANSI", 1252, NULL },
{ "EASTEUROPE", 1250, NULL },
{ "RUSSIAN", 1251, NULL },
{ "GREEK", 1253, NULL },
{ "TURKISH", 1254, NULL },
{ "HEBREW", 1255, NULL },
{ "ARABIC", 1256, NULL },
{ "BALTIC", 1257, NULL },
{ "THAI", 874, NULL },
{ "SHIFTJIS", 932, NULL },
{ "GB2312", 936, NULL },
{ "HANGEUL", 949, NULL },
{ "CHINESEBIG5", 950, NULL },
{ "JOHAB", 1361, NULL }
};
// Module data
struct nsGfxModuleData
{
@ -49,25 +76,11 @@ struct nsGfxModuleData
nsGfxModuleData();
~nsGfxModuleData();
// XXX XXX XXX this is a hack copied from the widget library (where it's
// not a hack but perfectly valid) until font-switching comes
// on-line.
// Unicode->local cp. conversions
char *ConvertFromUcs( const PRUnichar *pText, ULONG ulLength, char *szBuffer, ULONG ulSize);
char *ConvertFromUcs( const nsString &aStr, char *szBuffer, ULONG ulSize);
// these methods use a single static buffer
const char *ConvertFromUcs( const PRUnichar *pText, ULONG ulLength);
const char *ConvertFromUcs( const nsString &aStr);
UconvObject converter;
BOOL supplantConverter;
PRUint32 renderingHints;
ULONG ulCodepage;
// XXX XXX XXX end hack
void Init();
};
int WideCharToMultiByte( int CodePage, const PRUnichar *pText, ULONG ulLength, char* szBuffer, ULONG ulSize );
extern nsGfxModuleData gModuleData;
#ifndef min

Просмотреть файл

@ -304,150 +304,63 @@ void nsGfxModuleData::Init()
hpsScreen = WinGetScreenPS( HWND_DESKTOP);
HDC hdc = GpiQueryDevice( hpsScreen);
DevQueryCaps( hdc, CAPS_COLOR_BITCOUNT, 1, &lDisplayDepth);
// XXX XXX temp hack XXX XXX XXX
converter = 0;
supplantConverter = FALSE;
if( !getenv( "MOZ_DONT_DRAW_UNICODE"))
{
ULONG ulDummy = 0;
renderingHints = 0;
DosQueryCp( 4, &ulCodepage, &ulDummy);
}
else
{
renderingHints = NS_RENDERING_HINT_FAST_8BIT_TEXT;
ulCodepage = 1004;
}
// XXX XXX end temp hack XXX XXX XXX
}
nsGfxModuleData::~nsGfxModuleData()
{
// XXX XXX temp hack XXX XXX XXX
if( converter)
UniFreeUconvObject( converter);
// XXX XXX end temp hack XXX XXX XXX
/* Free any converters that were created */
for (int i=0; i < 15 /* eCharSet_COUNT from nsFontMetricsOS2.cpp */ ; i++ ) {
if (gUconvInfo[i].mConverter) {
UniFreeUconvObject(gUconvInfo[i].mConverter);
} /* endif */
} /* endfor */
PrnTerminate();
if( hModResources)
DosFreeModule( hModResources);
WinReleasePS( hpsScreen);
PrnTerminate();
if( hModResources)
DosFreeModule( hModResources);
WinReleasePS( hpsScreen);
}
nsGfxModuleData gModuleData;
// XXX XXX XXX XXX Temp hack until font-switching comes on-line XXX XXX XXX XXX
// Conversion from unicode to appropriate codepage
char *nsGfxModuleData::ConvertFromUcs( const PRUnichar *pText, ULONG ulLength,
char *szBuffer, ULONG ulSize)
int WideCharToMultiByte( int CodePage, const PRUnichar *pText, ULONG ulLength, char* szBuffer, ULONG ulSize )
{
if( supplantConverter)
{
// We couldn't create a converter for some reason, so do this 'by hand'.
// Note this algorithm is fine for most of most western charsets, but
// fails dismally for various glyphs, baltic, points east...
ULONG ulCount = 0;
char *szSave = szBuffer;
while( *pText && ulCount < ulSize - 1) // (one for terminator)
{
*szBuffer = (char) *pText;
szBuffer++;
pText++;
ulCount++;
}
UconvObject* pConverter = 0;
/* Free any converters that were created */
for (int i=0; i < 15 /* eCharSet_COUNT from nsFontMetricsOS2.cpp */ ; i++ ) {
if (gUconvInfo[i].mCodePage == CodePage) {
if (!gUconvInfo[i].mConverter) {
UniChar codepage[20];
int unirc = UniMapCpToUcsCp( CodePage, codepage, 20);
UniCreateUconvObject( codepage, &gUconvInfo[i].mConverter);
break;
} /* endif */
pConverter = &gUconvInfo[i].mConverter;
} /* endif */
} /* endfor */
if (!pConverter) {
pConverter = &gUconvInfo[0].mConverter;
} /* endif */
// terminate string
*szBuffer = '\0';
UniChar *ucsString = (UniChar*) pText;
size_t ucsLen = ulLength;
size_t cplen = ulSize;
size_t cSubs = 0;
return szSave;
}
char *tmp = szBuffer; // function alters the out pointer
if( !converter)
{
// Create a converter from unicode to a codepage which PM can display.
UniChar codepage[20];
int unirc = UniMapCpToUcsCp( 0, codepage, 20);
if( unirc == ULS_SUCCESS)
{
unirc = UniCreateUconvObject( codepage, &converter);
// XXX do we need to set substitution options here?
}
if( unirc != ULS_SUCCESS)
{
supplantConverter = TRUE;
renderingHints = NS_RENDERING_HINT_FAST_8BIT_TEXT;
ulCodepage = 1004;
printf( "Couldn't create gfx unicode converter.\n");
return ConvertFromUcs( nsString(pText), szBuffer, ulSize);
}
}
// Have converter, now get it to work...
UniChar *ucsString = (UniChar*) pText;
size_t ucsLen = ulLength;
size_t cplen = ulSize;
size_t cSubs = 0;
char *tmp = szBuffer; // function alters the out pointer
int unirc = UniUconvFromUcs( converter, &ucsString, &ucsLen,
int unirc = UniUconvFromUcs( *pConverter, &ucsString, &ucsLen,
(void**) &tmp, &cplen, &cSubs);
if( unirc == UCONV_E2BIG) // k3w1
{
// terminate output string (truncating)
*(szBuffer + ulSize - 1) = '\0';
}
else if( unirc != ULS_SUCCESS)
{
printf( "UniUconvFromUcs failed, rc %X\n", unirc);
supplantConverter = TRUE;
szBuffer = ConvertFromUcs( nsString(pText), szBuffer, ulSize);
supplantConverter = FALSE;
}
return szBuffer;
if( unirc == UCONV_E2BIG) // k3w1
{
// terminate output string (truncating)
*(szBuffer + ulSize - 1) = '\0';
}
else if( unirc != ULS_SUCCESS)
{
printf("very bad");
}
return ulSize - cplen;
}
char *nsGfxModuleData::ConvertFromUcs( const nsString &aString,
char *szBuffer, ULONG ulSize)
{
char *szRet = 0;
const PRUnichar *pUnicode = aString.GetUnicode();
if( pUnicode)
szRet = ConvertFromUcs( pUnicode, aString.Length() + 1, szBuffer, ulSize);
else
szRet = aString.ToCString( szBuffer, ulSize);
return szRet;
}
const char *nsGfxModuleData::ConvertFromUcs( const PRUnichar *pText, ULONG ulLength)
{
// This is probably okay; longer strings will be truncated but istr there's
// a PM limit on things like windowtext
// (which these routines are usually used for)
static char buffer[1024]; // XXX (multithread)
*buffer = '\0';
return ConvertFromUcs( pText, ulLength, buffer, 1024);
}
const char *nsGfxModuleData::ConvertFromUcs( const nsString &aString)
{
const char *szRet = 0;
const PRUnichar *pUnicode = aString.GetUnicode();
if( pUnicode)
szRet = ConvertFromUcs( pUnicode, aString.Length() + 1);
else
szRet = aString.GetBuffer(); // hrm.
return szRet;
}
// XXX XXX XXX XXX End Temp hack until font-switching comes on-line XXX XXX XXX

Просмотреть файл

@ -321,7 +321,8 @@ nsresult nsRenderingContextOS2::CommonInit()
::GpiSelectPalette(mSurface->mPS, (HPAL)palInfo.palette);
::WinRealizePalette((HWND)mDCOwner->GetNativeData(NS_NATIVE_WINDOW),mSurface->mPS, &cclr);
} else if (!palInfo.isPaletteDevice && palInfo.palette) {
GpiCreateLogColorTable( mSurface->mPS, LCOL_RESET | LCOL_PURECOLOR,
// GpiCreateLogColorTable( mSurface->mPS, LCOL_RESET | LCOL_PURECOLOR,
GpiCreateLogColorTable( mSurface->mPS, LCOL_RESET,
LCOLF_CONSECRGB, 0,
palInfo.sizePalette, (PLONG) palInfo.palette);
free(palInfo.palette);
@ -329,7 +330,8 @@ nsresult nsRenderingContextOS2::CommonInit()
}
else
{
GpiCreateLogColorTable( mSurface->mPS, LCOL_PURECOLOR,
// GpiCreateLogColorTable( mSurface->mPS, LCOL_PURECOLOR,
GpiCreateLogColorTable( mSurface->mPS, 0,
LCOLF_RGB, 0, 0, 0);
}
return NS_OK;
@ -888,8 +890,10 @@ void nsRenderingContextOS2::SetupDrawingColor( BOOL bForce)
areaBundle.lBackColor = 0x00FFFFFF; //OS2TODO
lineBundle.lBackColor = 0x00FFFFFF;
areaBundle.usMixMode = FM_LEAVEALONE;
areaBundle.usBackMixMode = BM_LEAVEALONE;
// areaBundle.usMixMode = FM_LEAVEALONE;
// areaBundle.usBackMixMode = BM_LEAVEALONE;
areaBundle.usMixMode = FM_OVERPAINT;
areaBundle.usBackMixMode = BM_OVERPAINT;
lLineFlags = lLineFlags | LBB_BACK_COLOR ;
@ -1226,8 +1230,11 @@ void nsRenderingContextOS2::PMDrawArc( nsRect &rect, PRBool bFilled,
NS_IMETHODIMP nsRenderingContextOS2::GetHints(PRUint32& aResult)
{
aResult = gModuleData.renderingHints;
return NS_OK;
PRUint32 result = 0;
aResult = result;
return NS_OK;
}
nsresult nsRenderingContextOS2::DrawString( const char *aString,
@ -1259,15 +1266,16 @@ nsresult nsRenderingContextOS2::DrawString( const char *aString,
GpiMove( mSurface->mPS, &ptl);
PRUint32 lLength = aLength;
// GpiCharString has a max length of 512 chars at a time...
while( aLength)
while( lLength)
{
ULONG thislen = min( aLength, 512);
ULONG thislen = min( lLength, 512);
GpiCharStringPos( mSurface->mPS, nsnull,
aSpacing == nsnull ? 0 : CHS_VECTOR,
thislen, (PCH)aString,
aSpacing == nsnull ? nsnull : (PLONG) dx0);
aLength -= thislen;
lLength -= thislen;
aString += thislen;
dx0 += thislen;
}
@ -1280,9 +1288,11 @@ nsresult nsRenderingContextOS2::DrawString( const PRUnichar *aString, PRUint32 a
PRInt32 aFontID,
const nscoord* aSpacing)
{
// XXX unicode hack XXX
return DrawString( gModuleData.ConvertFromUcs( aString, aLength),
aLength, aX, aY, aSpacing);
char buf[1024];
int newLength = WideCharToMultiByte( ((nsFontMetricsOS2*)mFontMetrics)->mCodePage, aString, aLength, buf, sizeof(buf));
return DrawString( buf, newLength, aX, aY, aSpacing);
}
nsresult nsRenderingContextOS2::DrawString( const nsString& aString,
@ -1341,17 +1351,18 @@ NS_IMETHODIMP nsRenderingContextOS2::GetWidth( const char* aString,
nscoord &aWidth)
{
PRUint32 sum = 0;
PRUint32 lLength = aLength;
SetupFontAndColor(); // select font
POINTL ptls[ 4];
while( aLength) // max data to gpi function is 512 chars.
while( lLength) // max data to gpi function is 512 chars.
{
ULONG thislen = min( aLength, 512);
ULONG thislen = min( lLength, 512);
GpiQueryTextBox( mSurface->mPS, thislen, (PCH) aString, 4, ptls);
sum += ptls[ TXTBOX_TOPRIGHT].x;
aLength -= thislen;
lLength -= thislen;
aString += thislen;
}
@ -1365,9 +1376,12 @@ NS_IMETHODIMP nsRenderingContextOS2::GetWidth( const PRUnichar *aString,
nscoord &aWidth,
PRInt32 *aFontID)
{
// XXX unicode hack XXX
return GetWidth( gModuleData.ConvertFromUcs( aString, aLength),
aLength, aWidth);
nsresult temp;
char buf[1024];
int newLength = WideCharToMultiByte( ((nsFontMetricsOS2*)mFontMetrics)->mCodePage, aString, aLength, buf, sizeof(buf));
temp = GetWidth( buf, newLength, aWidth);
return temp;
}
// Image drawing: just proxy on to the image object, so no worries yet.