2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Foundation code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Mozilla Foundation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2005
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Stuart Parmenter <stuart@mozilla.com>
|
|
|
|
* Vladimir Vukicevic <vladimir@pobox.com>
|
|
|
|
* Masayuki Nakano <masayuki@d-toybox.com>
|
|
|
|
* Masatoshi Kimura <VYV03354@nifty.ne.jp>
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "gfxWindowsPlatform.h"
|
|
|
|
|
|
|
|
#include "gfxImageSurface.h"
|
|
|
|
#include "gfxWindowsSurface.h"
|
|
|
|
|
|
|
|
#include "nsUnicharUtils.h"
|
|
|
|
|
|
|
|
#include "nsIPref.h"
|
|
|
|
#include "nsServiceManagerUtils.h"
|
|
|
|
|
|
|
|
#include "nsIWindowsRegKey.h"
|
|
|
|
|
2007-04-02 12:06:16 -07:00
|
|
|
#include "gfxWindowsFonts.h"
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#include <string>
|
|
|
|
|
2007-07-23 15:02:17 -07:00
|
|
|
#include "lcms.h"
|
|
|
|
|
2007-05-29 17:07:03 -07:00
|
|
|
//#define DEBUG_CMAP_SIZE 1
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
static nsresult ReadCMAP(HDC hdc, FontEntry *aFontEntry);
|
|
|
|
|
2007-08-24 12:41:16 -07:00
|
|
|
int PR_CALLBACK
|
|
|
|
gfxWindowsPlatform::PrefChangedCallback(const char *aPrefName, void *closure)
|
|
|
|
{
|
2007-08-24 17:00:41 -07:00
|
|
|
// XXX this could be made to only clear out the cache for the prefs that were changed
|
|
|
|
// but it probably isn't that big a deal.
|
2007-08-24 12:41:16 -07:00
|
|
|
gfxWindowsPlatform *plat = static_cast<gfxWindowsPlatform *>(closure);
|
|
|
|
plat->mPrefFonts.Clear();
|
|
|
|
return 0;
|
|
|
|
}
|
2007-05-29 17:07:03 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
gfxWindowsPlatform::gfxWindowsPlatform()
|
|
|
|
{
|
|
|
|
mFonts.Init(200);
|
|
|
|
mFontAliases.Init(20);
|
|
|
|
mFontSubstitutes.Init(50);
|
2007-08-24 12:41:16 -07:00
|
|
|
mPrefFonts.Init(10);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
UpdateFontList();
|
2007-08-24 12:41:16 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIPref> pref = do_GetService(NS_PREF_CONTRACTID);
|
|
|
|
pref->RegisterCallback("font.", PrefChangedCallback, this);
|
|
|
|
pref->RegisterCallback("font.name-list.", PrefChangedCallback, this);
|
2007-08-24 17:00:41 -07:00
|
|
|
pref->RegisterCallback("intl.accept_languages", PrefChangedCallback, this);
|
2007-08-24 12:41:16 -07:00
|
|
|
// don't bother unregistering. We'll get shutdown after the pref service
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
gfxWindowsPlatform::~gfxWindowsPlatform()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<gfxASurface>
|
|
|
|
gfxWindowsPlatform::CreateOffscreenSurface(const gfxIntSize& size,
|
|
|
|
gfxASurface::gfxImageFormat imageFormat)
|
|
|
|
{
|
|
|
|
gfxASurface *surf = new gfxWindowsSurface(size, imageFormat);
|
|
|
|
NS_IF_ADDREF(surf);
|
|
|
|
return surf;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CALLBACK
|
|
|
|
gfxWindowsPlatform::FontEnumProc(const ENUMLOGFONTEXW *lpelfe,
|
|
|
|
const NEWTEXTMETRICEXW *nmetrics,
|
|
|
|
DWORD fontType, LPARAM data)
|
|
|
|
{
|
2008-03-18 17:06:55 -07:00
|
|
|
FontTable *ht = reinterpret_cast<FontTable*>(data);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
const NEWTEXTMETRICW& metrics = nmetrics->ntmTm;
|
2008-03-18 17:06:55 -07:00
|
|
|
LOGFONTW logFont = lpelfe->elfLogFont;
|
2007-06-25 14:51:15 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Ignore vertical fonts
|
|
|
|
if (logFont.lfFaceName[0] == L'@') {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2008-03-21 21:16:00 -07:00
|
|
|
// Some fonts claim to support things > 900, but we don't so clamp the sizes
|
|
|
|
logFont.lfWeight = PR_MAX(PR_MIN(logFont.lfWeight, 900), 100);
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
#ifdef DEBUG_pavlov
|
|
|
|
printf("%s %d %d %d\n", NS_ConvertUTF16toUTF8(nsDependentString(logFont.lfFaceName)).get(),
|
|
|
|
logFont.lfCharSet, logFont.lfItalic, logFont.lfWeight);
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsString name(logFont.lfFaceName);
|
|
|
|
ToLowerCase(name);
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
nsRefPtr<FontFamily> ff;
|
|
|
|
if (!ht->Get(name, &ff)) {
|
|
|
|
ff = new FontFamily(nsDependentString(logFont.lfFaceName));
|
|
|
|
ht->Put(name, ff);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsRefPtr<FontEntry> fe;
|
2008-03-18 17:06:55 -07:00
|
|
|
for (PRUint32 i = 0; i < ff->mVariations.Length(); ++i) {
|
|
|
|
fe = ff->mVariations[i];
|
|
|
|
if (fe->mWeight == logFont.lfWeight &&
|
|
|
|
fe->mItalic == (logFont.lfItalic == 0xFF)) {
|
|
|
|
return 1; /* we already know about this font */
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-03-21 14:22:29 -07:00
|
|
|
fe = new FontEntry(ff->mName);
|
2008-03-18 17:06:55 -07:00
|
|
|
/* don't append it until the end in case of error */
|
|
|
|
|
|
|
|
fe->mItalic = (logFont.lfItalic == 0xFF);
|
|
|
|
fe->mWeight = logFont.lfWeight;
|
|
|
|
|
2008-03-12 21:15:24 -07:00
|
|
|
if (metrics.ntmFlags & NTM_TYPE1)
|
2008-03-21 13:22:58 -07:00
|
|
|
fe->mIsType1 = fe->mForceGDI = PR_TRUE;
|
2008-03-19 17:41:19 -07:00
|
|
|
if (metrics.ntmFlags & (NTM_PS_OPENTYPE | NTM_TT_OPENTYPE))
|
|
|
|
fe->mTrueType = PR_TRUE;
|
2008-03-12 21:15:24 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// mark the charset bit
|
|
|
|
fe->mCharset[metrics.tmCharSet] = 1;
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
fe->mWindowsFamily = logFont.lfPitchAndFamily & 0xF0;
|
|
|
|
fe->mWindowsPitch = logFont.lfPitchAndFamily & 0x0F;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
if (nmetrics->ntmFontSig.fsUsb[0] == 0x00000000 &&
|
|
|
|
nmetrics->ntmFontSig.fsUsb[1] == 0x00000000 &&
|
|
|
|
nmetrics->ntmFontSig.fsUsb[2] == 0x00000000 &&
|
|
|
|
nmetrics->ntmFontSig.fsUsb[3] == 0x00000000) {
|
|
|
|
// no unicode ranges
|
|
|
|
fe->mUnicodeFont = PR_FALSE;
|
|
|
|
} else {
|
|
|
|
fe->mUnicodeFont = PR_TRUE;
|
|
|
|
|
|
|
|
// set the unicode ranges
|
|
|
|
PRUint32 x = 0;
|
|
|
|
for (PRUint32 i = 0; i < 4; ++i) {
|
|
|
|
DWORD range = nmetrics->ntmFontSig.fsUsb[i];
|
|
|
|
for (PRUint32 k = 0; k < 32; ++k) {
|
|
|
|
fe->mUnicodeRanges[x++] = (range & (1 << k)) != 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
/* read in the character map */
|
|
|
|
HDC hdc = GetDC(nsnull);
|
|
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
HFONT font = CreateFontIndirectW(&logFont);
|
|
|
|
|
|
|
|
NS_ASSERTION(font, "This font creation should never ever ever fail");
|
|
|
|
if (font) {
|
|
|
|
HFONT oldFont = (HFONT)SelectObject(hdc, font);
|
|
|
|
|
|
|
|
TEXTMETRIC metrics;
|
|
|
|
GetTextMetrics(hdc, &metrics);
|
|
|
|
if (metrics.tmPitchAndFamily & TMPF_TRUETYPE)
|
|
|
|
fe->mTrueType = PR_TRUE;
|
|
|
|
|
|
|
|
if (NS_FAILED(ReadCMAP(hdc, fe))) {
|
|
|
|
// Type1 fonts aren't necessarily Unicode but
|
|
|
|
// this is the best guess we can make here
|
|
|
|
if (fe->mIsType1)
|
|
|
|
fe->mUnicodeFont = PR_TRUE;
|
|
|
|
else
|
|
|
|
fe->mUnicodeFont = PR_FALSE;
|
|
|
|
|
|
|
|
//printf("%d, %s failed to get cmap\n", aFontEntry->mIsType1, NS_ConvertUTF16toUTF8(aFontEntry->mName).get());
|
|
|
|
}
|
|
|
|
|
|
|
|
SelectObject(hdc, oldFont);
|
|
|
|
DeleteObject(font);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseDC(nsnull, hdc);
|
|
|
|
|
|
|
|
if (!fe->mUnicodeFont) {
|
|
|
|
/* non-unicode fonts.. boy lets just set all code points
|
|
|
|
between 0x20 and 0xFF. All the ones on my system do...
|
|
|
|
If we really wanted to test which characters in this
|
|
|
|
range were supported we could just generate a string with
|
|
|
|
each codepoint and do GetGlyphIndicies or similar to determine
|
|
|
|
what is there.
|
|
|
|
*/
|
|
|
|
fe->mCharacterMap.SetRange(0x20, 0xFF);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* append the variation to the font family */
|
|
|
|
ff->mVariations.AppendElement(fe);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2007-12-27 17:28:26 -08:00
|
|
|
// general cmap reading routines moved to gfxFontUtils.cpp
|
2007-05-29 17:07:03 -07:00
|
|
|
|
|
|
|
static nsresult
|
|
|
|
ReadCMAP(HDC hdc, FontEntry *aFontEntry)
|
|
|
|
{
|
|
|
|
const PRUint32 kCMAP = (('c') | ('m' << 8) | ('a' << 16) | ('p' << 24));
|
|
|
|
|
|
|
|
DWORD len = GetFontData(hdc, kCMAP, 0, nsnull, 0);
|
2007-11-06 20:58:16 -08:00
|
|
|
if (len == GDI_ERROR || len == 0) // not a truetype font --
|
|
|
|
return NS_ERROR_FAILURE; // we'll treat it as a symbol font
|
2007-05-29 17:07:03 -07:00
|
|
|
|
|
|
|
nsAutoTArray<PRUint8,16384> buffer;
|
|
|
|
if (!buffer.AppendElements(len))
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
PRUint8 *buf = buffer.Elements();
|
|
|
|
|
|
|
|
DWORD newLen = GetFontData(hdc, kCMAP, 0, buf, len);
|
|
|
|
NS_ENSURE_TRUE(newLen == len, NS_ERROR_FAILURE);
|
2007-12-27 17:28:26 -08:00
|
|
|
|
|
|
|
return gfxFontUtils::ReadCMAP(buf, len, aFontEntry->mCharacterMap, aFontEntry->mUnicodeRanges,
|
2008-03-18 17:06:55 -07:00
|
|
|
aFontEntry->mUnicodeFont, aFontEntry->mSymbolFont);
|
2007-05-29 17:07:03 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
PLDHashOperator PR_CALLBACK
|
2008-03-18 17:06:55 -07:00
|
|
|
gfxWindowsPlatform::FontGetStylesProc(nsStringHashKey::KeyType aKey,
|
|
|
|
nsRefPtr<FontFamily>& aFontFamily,
|
|
|
|
void* userArg)
|
2007-05-29 17:07:03 -07:00
|
|
|
{
|
2008-03-18 17:06:55 -07:00
|
|
|
NS_ASSERTION(aFontFamily->mVariations.Length() == 1, "We should only have 1 variation here");
|
|
|
|
nsRefPtr<FontEntry> aFontEntry = aFontFamily->mVariations[0];
|
|
|
|
|
2007-05-29 17:07:03 -07:00
|
|
|
HDC hdc = GetDC(nsnull);
|
|
|
|
|
|
|
|
LOGFONTW logFont;
|
|
|
|
memset(&logFont, 0, sizeof(LOGFONTW));
|
|
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
logFont.lfPitchAndFamily = 0;
|
2008-03-18 17:06:55 -07:00
|
|
|
PRUint32 l = PR_MIN(aFontEntry->GetName().Length(), LF_FACESIZE - 1);
|
2007-05-29 17:07:03 -07:00
|
|
|
memcpy(logFont.lfFaceName,
|
2008-03-18 17:06:55 -07:00
|
|
|
nsPromiseFlatString(aFontEntry->GetName()).get(),
|
2007-05-29 17:07:03 -07:00
|
|
|
l * sizeof(PRUnichar));
|
|
|
|
logFont.lfFaceName[l] = 0;
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
EnumFontFamiliesExW(hdc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)userArg, 0);
|
2007-05-29 17:07:03 -07:00
|
|
|
|
|
|
|
ReleaseDC(nsnull, hdc);
|
|
|
|
|
2008-03-19 22:35:05 -07:00
|
|
|
// Look for font families without bold variations and add a FontEntry
|
|
|
|
// with synthetic bold (weight 600) for them.
|
|
|
|
nsRefPtr<FontEntry> darkestItalic;
|
|
|
|
nsRefPtr<FontEntry> darkestNonItalic;
|
|
|
|
PRUint8 highestItalic = 0, highestNonItalic = 0;
|
|
|
|
for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); i++) {
|
|
|
|
nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
|
|
|
|
if (fe->mItalic) {
|
|
|
|
if (!darkestItalic || fe->mWeight > darkestItalic->mWeight)
|
|
|
|
darkestItalic = fe;
|
|
|
|
} else {
|
|
|
|
if (!darkestNonItalic || fe->mWeight > darkestNonItalic->mWeight)
|
|
|
|
darkestNonItalic = fe;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (darkestItalic && darkestItalic->mWeight < 600) {
|
|
|
|
nsRefPtr<FontEntry> newEntry = new FontEntry(*darkestItalic.get());
|
|
|
|
newEntry->mWeight = 600;
|
|
|
|
aFontFamily->mVariations.AppendElement(newEntry);
|
|
|
|
}
|
|
|
|
if (darkestNonItalic && darkestNonItalic->mWeight < 600) {
|
|
|
|
nsRefPtr<FontEntry> newEntry = new FontEntry(*darkestNonItalic.get());
|
|
|
|
newEntry->mWeight = 600;
|
|
|
|
aFontFamily->mVariations.AppendElement(newEntry);
|
|
|
|
}
|
|
|
|
|
2007-05-29 17:07:03 -07:00
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
struct FontListData {
|
|
|
|
FontListData(const nsACString& aLangGroup, const nsACString& aGenericFamily, nsStringArray& aListOfFonts) :
|
|
|
|
mLangGroup(aLangGroup), mGenericFamily(aGenericFamily), mStringArray(aListOfFonts) {}
|
|
|
|
const nsACString& mLangGroup;
|
|
|
|
const nsACString& mGenericFamily;
|
|
|
|
nsStringArray& mStringArray;
|
|
|
|
};
|
|
|
|
|
|
|
|
PLDHashOperator PR_CALLBACK
|
|
|
|
gfxWindowsPlatform::HashEnumFunc(nsStringHashKey::KeyType aKey,
|
2008-03-18 17:06:55 -07:00
|
|
|
nsRefPtr<FontFamily>& aFontFamily,
|
2007-03-22 10:30:00 -07:00
|
|
|
void* userArg)
|
|
|
|
{
|
|
|
|
FontListData *data = (FontListData*)userArg;
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
// use the first variation for now. This data should be the same
|
|
|
|
// for all the variations and should probably be moved up to
|
|
|
|
// the Family
|
|
|
|
nsRefPtr<FontEntry> aFontEntry = aFontFamily->mVariations[0];
|
|
|
|
|
2007-06-25 14:51:15 -07:00
|
|
|
/* skip symbol fonts */
|
|
|
|
if (aFontEntry->mSymbolFont)
|
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (aFontEntry->SupportsLangGroup(data->mLangGroup) &&
|
|
|
|
aFontEntry->MatchesGenericFamily(data->mGenericFamily))
|
2008-03-18 17:06:55 -07:00
|
|
|
data->mStringArray.AppendString(aFontFamily->mName);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return PL_DHASH_NEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
gfxWindowsPlatform::GetFontList(const nsACString& aLangGroup,
|
|
|
|
const nsACString& aGenericFamily,
|
|
|
|
nsStringArray& aListOfFonts)
|
|
|
|
{
|
|
|
|
FontListData data(aLangGroup, aGenericFamily, aListOfFonts);
|
|
|
|
|
|
|
|
mFonts.Enumerate(gfxWindowsPlatform::HashEnumFunc, &data);
|
|
|
|
|
|
|
|
aListOfFonts.Sort();
|
|
|
|
aListOfFonts.Compact();
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
RemoveCharsetFromFontSubstitute(nsAString &aName)
|
|
|
|
{
|
|
|
|
PRInt32 comma = aName.FindChar(PRUnichar(','));
|
|
|
|
if (comma >= 0)
|
|
|
|
aName.Truncate(comma);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
BuildKeyNameFromFontName(nsAString &aName)
|
|
|
|
{
|
|
|
|
if (aName.Length() >= LF_FACESIZE)
|
|
|
|
aName.Truncate(LF_FACESIZE - 1);
|
|
|
|
ToLowerCase(aName);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
gfxWindowsPlatform::UpdateFontList()
|
|
|
|
{
|
2008-03-21 14:22:29 -07:00
|
|
|
gfxFontCache *fc = gfxFontCache::GetCache();
|
|
|
|
if (fc)
|
|
|
|
fc->AgeAllGenerations();
|
2007-03-22 10:30:00 -07:00
|
|
|
mFonts.Clear();
|
|
|
|
mFontAliases.Clear();
|
|
|
|
mNonExistingFonts.Clear();
|
|
|
|
mFontSubstitutes.Clear();
|
2007-08-24 12:41:16 -07:00
|
|
|
mPrefFonts.Clear();
|
2008-03-03 18:34:05 -08:00
|
|
|
mCodepointsWithNoFonts.reset();
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
LOGFONTW logFont;
|
|
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
logFont.lfFaceName[0] = 0;
|
|
|
|
logFont.lfPitchAndFamily = 0;
|
|
|
|
|
|
|
|
// Use the screen DC here.. should we use something else for printing?
|
|
|
|
HDC dc = ::GetDC(nsnull);
|
2008-03-18 17:06:55 -07:00
|
|
|
EnumFontFamiliesExW(dc, &logFont, (FONTENUMPROCW)gfxWindowsPlatform::FontEnumProc, (LPARAM)&mFonts, 0);
|
2007-03-22 10:30:00 -07:00
|
|
|
::ReleaseDC(nsnull, dc);
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
// Look for additional styles
|
|
|
|
mFonts.Enumerate(gfxWindowsPlatform::FontGetStylesProc, &mFonts);
|
2007-05-29 17:07:03 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Create the list of FontSubstitutes
|
2007-05-29 17:07:03 -07:00
|
|
|
nsCOMPtr<nsIWindowsRegKey> regKey = do_CreateInstance("@mozilla.org/windows-registry-key;1");
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!regKey)
|
|
|
|
return NS_ERROR_FAILURE;
|
2007-05-29 17:07:03 -07:00
|
|
|
NS_NAMED_LITERAL_STRING(kFontSubstitutesKey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\FontSubstitutes");
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-05-29 17:07:03 -07:00
|
|
|
nsresult rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_LOCAL_MACHINE,
|
|
|
|
kFontSubstitutesKey, nsIWindowsRegKey::ACCESS_READ);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
PRUint32 count;
|
|
|
|
rv = regKey->GetValueCount(&count);
|
|
|
|
if (NS_FAILED(rv) || count == 0)
|
|
|
|
return rv;
|
|
|
|
for (PRUint32 i = 0; i < count; i++) {
|
|
|
|
nsAutoString substituteName;
|
|
|
|
rv = regKey->GetValueName(i, substituteName);
|
|
|
|
if (NS_FAILED(rv) || substituteName.IsEmpty() ||
|
|
|
|
substituteName.CharAt(1) == PRUnichar('@'))
|
|
|
|
continue;
|
|
|
|
PRUint32 valueType;
|
|
|
|
rv = regKey->GetValueType(substituteName, &valueType);
|
|
|
|
if (NS_FAILED(rv) || valueType != nsIWindowsRegKey::TYPE_STRING)
|
|
|
|
continue;
|
|
|
|
nsAutoString actualFontName;
|
|
|
|
rv = regKey->ReadStringValue(substituteName, actualFontName);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
RemoveCharsetFromFontSubstitute(substituteName);
|
|
|
|
BuildKeyNameFromFontName(substituteName);
|
|
|
|
RemoveCharsetFromFontSubstitute(actualFontName);
|
|
|
|
BuildKeyNameFromFontName(actualFontName);
|
2008-03-18 17:06:55 -07:00
|
|
|
nsRefPtr<FontFamily> ff;
|
|
|
|
if (!actualFontName.IsEmpty() && mFonts.Get(actualFontName, &ff))
|
|
|
|
mFontSubstitutes.Put(substituteName, ff);
|
2007-03-22 10:30:00 -07:00
|
|
|
else
|
|
|
|
mNonExistingFonts.AppendString(substituteName);
|
|
|
|
}
|
|
|
|
|
2008-03-03 18:34:05 -08:00
|
|
|
// initialize ranges of characters for which system-wide font search should be skipped
|
|
|
|
mCodepointsWithNoFonts.SetRange(0,0x1f); // C0 controls
|
|
|
|
mCodepointsWithNoFonts.SetRange(0x7f,0x9f); // C1 controls
|
|
|
|
|
2008-03-12 19:36:58 -07:00
|
|
|
InitBadUnderlineList();
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-03-12 19:36:58 -07:00
|
|
|
static PRBool SimpleResolverCallback(const nsAString& aName, void* aClosure)
|
|
|
|
{
|
|
|
|
nsString* result = static_cast<nsString*>(aClosure);
|
|
|
|
result->Assign(aName);
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
gfxWindowsPlatform::InitBadUnderlineList()
|
|
|
|
{
|
|
|
|
nsAutoTArray<nsAutoString, 10> blacklist;
|
|
|
|
gfxFontUtils::GetPrefsFontList("font.blacklist.underline_offset", blacklist);
|
|
|
|
PRUint32 numFonts = blacklist.Length();
|
|
|
|
for (PRUint32 i = 0; i < numFonts; i++) {
|
|
|
|
PRBool aborted;
|
|
|
|
nsAutoString resolved;
|
|
|
|
ResolveFontName(blacklist[i], SimpleResolverCallback, &resolved, aborted);
|
|
|
|
if (resolved.IsEmpty())
|
|
|
|
continue;
|
2008-03-18 17:06:55 -07:00
|
|
|
FontFamily *ff = FindFontFamily(resolved);
|
|
|
|
if (!ff)
|
2008-03-12 19:36:58 -07:00
|
|
|
continue;
|
2008-03-18 17:06:55 -07:00
|
|
|
for (PRUint32 j = 0; j < ff->mVariations.Length(); ++j) {
|
|
|
|
nsRefPtr<FontEntry> fe = ff->mVariations[j];
|
|
|
|
fe->mIsBadUnderlineFont = 1;
|
|
|
|
}
|
2008-03-12 19:36:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-03-13 03:32:50 -07:00
|
|
|
nsresult
|
|
|
|
gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
|
|
|
|
{
|
|
|
|
aFamilyName.Truncate();
|
|
|
|
PRBool aborted;
|
|
|
|
return ResolveFontName(aFontName, SimpleResolverCallback, &aFamilyName, aborted);
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
struct ResolveData {
|
|
|
|
ResolveData(gfxPlatform::FontResolverCallback aCallback,
|
|
|
|
gfxWindowsPlatform *aCaller, const nsAString *aFontName,
|
|
|
|
void *aClosure) :
|
|
|
|
mFoundCount(0), mCallback(aCallback), mCaller(aCaller),
|
|
|
|
mFontName(aFontName), mClosure(aClosure) {}
|
|
|
|
PRUint32 mFoundCount;
|
|
|
|
gfxPlatform::FontResolverCallback mCallback;
|
|
|
|
gfxWindowsPlatform *mCaller;
|
|
|
|
const nsAString *mFontName;
|
|
|
|
void *mClosure;
|
|
|
|
};
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
gfxWindowsPlatform::ResolveFontName(const nsAString& aFontName,
|
|
|
|
FontResolverCallback aCallback,
|
|
|
|
void *aClosure,
|
|
|
|
PRBool& aAborted)
|
|
|
|
{
|
|
|
|
if (aFontName.IsEmpty())
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
nsAutoString keyName(aFontName);
|
|
|
|
BuildKeyNameFromFontName(keyName);
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
nsRefPtr<FontFamily> ff;
|
|
|
|
if (mFonts.Get(keyName, &ff) ||
|
|
|
|
mFontSubstitutes.Get(keyName, &ff) ||
|
|
|
|
mFontAliases.Get(keyName, &ff)) {
|
|
|
|
aAborted = !(*aCallback)(ff->mName, aClosure);
|
2007-03-22 10:30:00 -07:00
|
|
|
// XXX If the font has font link, we should add the linked font.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mNonExistingFonts.IndexOf(keyName) >= 0) {
|
|
|
|
aAborted = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
LOGFONTW logFont;
|
|
|
|
logFont.lfCharSet = DEFAULT_CHARSET;
|
|
|
|
logFont.lfPitchAndFamily = 0;
|
|
|
|
PRInt32 len = aFontName.Length();
|
|
|
|
if (len >= LF_FACESIZE)
|
|
|
|
len = LF_FACESIZE - 1;
|
|
|
|
memcpy(logFont.lfFaceName,
|
|
|
|
nsPromiseFlatString(aFontName).get(), len * sizeof(PRUnichar));
|
|
|
|
logFont.lfFaceName[len] = 0;
|
|
|
|
|
|
|
|
HDC dc = ::GetDC(nsnull);
|
|
|
|
ResolveData data(aCallback, this, &keyName, aClosure);
|
2008-03-18 17:06:55 -07:00
|
|
|
aAborted = !EnumFontFamiliesExW(dc, &logFont,
|
|
|
|
(FONTENUMPROCW)gfxWindowsPlatform::FontResolveProc,
|
|
|
|
(LPARAM)&data, 0);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (data.mFoundCount == 0)
|
|
|
|
mNonExistingFonts.AppendString(keyName);
|
|
|
|
::ReleaseDC(nsnull, dc);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int CALLBACK
|
|
|
|
gfxWindowsPlatform::FontResolveProc(const ENUMLOGFONTEXW *lpelfe,
|
|
|
|
const NEWTEXTMETRICEXW *nmetrics,
|
|
|
|
DWORD fontType, LPARAM data)
|
|
|
|
{
|
|
|
|
const LOGFONTW& logFont = lpelfe->elfLogFont;
|
|
|
|
// Ignore vertical fonts
|
|
|
|
if (logFont.lfFaceName[0] == L'@' || logFont.lfFaceName[0] == 0)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
ResolveData *rData = reinterpret_cast<ResolveData*>(data);
|
|
|
|
|
|
|
|
nsAutoString name(logFont.lfFaceName);
|
|
|
|
|
|
|
|
// Save the alias name to cache
|
2008-03-18 17:06:55 -07:00
|
|
|
nsRefPtr<FontFamily> ff;
|
2007-03-22 10:30:00 -07:00
|
|
|
nsAutoString keyName(name);
|
|
|
|
BuildKeyNameFromFontName(keyName);
|
2008-03-18 17:06:55 -07:00
|
|
|
if (!rData->mCaller->mFonts.Get(keyName, &ff)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// This case only occurs on failing to build
|
|
|
|
// the list of font substitue. In this case, the user should
|
|
|
|
// reboot the Windows. Probably, we don't have the good way for
|
|
|
|
// resolving in this time.
|
|
|
|
NS_WARNING("Cannot find actual font");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
rData->mFoundCount++;
|
2008-03-18 17:06:55 -07:00
|
|
|
rData->mCaller->mFontAliases.Put(*(rData->mFontName), ff);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return (rData->mCallback)(name, rData->mClosure);
|
|
|
|
|
|
|
|
// XXX If the font has font link, we should add the linked font.
|
|
|
|
}
|
|
|
|
|
|
|
|
struct FontSearch {
|
2008-03-03 18:34:05 -08:00
|
|
|
FontSearch(PRUint32 aCh, gfxWindowsFont *aFont) :
|
|
|
|
ch(aCh), fontToMatch(aFont), matchRank(0) {
|
2007-05-29 08:09:23 -07:00
|
|
|
}
|
2008-03-03 18:34:05 -08:00
|
|
|
PRUint32 ch;
|
2007-05-29 17:07:03 -07:00
|
|
|
nsRefPtr<gfxWindowsFont> fontToMatch;
|
|
|
|
PRInt32 matchRank;
|
|
|
|
nsRefPtr<FontEntry> bestMatch;
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
PLDHashOperator PR_CALLBACK
|
2008-03-03 18:34:05 -08:00
|
|
|
gfxWindowsPlatform::FindFontForCharProc(nsStringHashKey::KeyType aKey,
|
2008-03-18 17:06:55 -07:00
|
|
|
nsRefPtr<FontFamily>& aFontFamily,
|
|
|
|
void* userArg)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
FontSearch *data = (FontSearch*)userArg;
|
2007-05-29 08:09:23 -07:00
|
|
|
|
2008-03-19 17:41:19 -07:00
|
|
|
const PRUint32 ch = data->ch;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-03-19 17:41:19 -07:00
|
|
|
nsRefPtr<FontEntry> fe = GetPlatform()->FindFontEntry(aFontFamily, data->fontToMatch->GetStyle());
|
2007-05-29 08:09:23 -07:00
|
|
|
|
2008-03-19 17:41:19 -07:00
|
|
|
// skip over non-unicode and bitmap fonts and fonts that don't have
|
|
|
|
// the code point we're looking for
|
|
|
|
if (fe->IsCrappyFont() || !fe->mCharacterMap.test(ch))
|
|
|
|
return PL_DHASH_NEXT;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-03-19 17:41:19 -07:00
|
|
|
PRInt32 rank = 0;
|
|
|
|
// fonts that claim to support the range are more
|
|
|
|
// likely to be "better fonts" than ones that don't... (in theory)
|
|
|
|
if (fe->SupportsRange(gfxFontUtils::CharRangeBit(ch)))
|
|
|
|
rank += 1;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2008-03-19 17:41:19 -07:00
|
|
|
if (fe->SupportsLangGroup(data->fontToMatch->GetStyle()->langGroup))
|
|
|
|
rank += 2;
|
2008-03-18 17:06:55 -07:00
|
|
|
|
2008-03-19 17:41:19 -07:00
|
|
|
if (fe->mWindowsFamily == data->fontToMatch->GetFontEntry()->mWindowsFamily)
|
|
|
|
rank += 3;
|
|
|
|
if (fe->mWindowsPitch == data->fontToMatch->GetFontEntry()->mWindowsFamily)
|
|
|
|
rank += 3;
|
2008-03-18 17:06:55 -07:00
|
|
|
|
2008-03-19 17:41:19 -07:00
|
|
|
/* italic */
|
|
|
|
const PRBool italic = (data->fontToMatch->GetStyle()->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) ? PR_TRUE : PR_FALSE;
|
|
|
|
if (fe->mItalic != italic)
|
|
|
|
rank += 3;
|
|
|
|
|
|
|
|
/* weight */
|
|
|
|
PRInt8 baseWeight, weightDistance;
|
|
|
|
data->fontToMatch->GetStyle()->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
|
|
|
if (fe->mWeight == (baseWeight * 100) + (weightDistance * 100))
|
|
|
|
rank += 2;
|
|
|
|
else if (fe->mWeight == data->fontToMatch->GetFontEntry()->mWeight)
|
|
|
|
rank += 1;
|
|
|
|
|
|
|
|
if (rank > data->matchRank ||
|
|
|
|
(rank == data->matchRank && Compare(fe->GetName(), data->bestMatch->GetName()) > 0)) {
|
|
|
|
data->bestMatch = fe;
|
|
|
|
data->matchRank = rank;
|
2007-05-29 08:09:23 -07:00
|
|
|
}
|
2007-05-29 17:07:03 -07:00
|
|
|
|
|
|
|
return PL_DHASH_NEXT;
|
2007-05-29 08:09:23 -07:00
|
|
|
}
|
2007-05-29 03:24:15 -07:00
|
|
|
|
2007-05-29 17:07:03 -07:00
|
|
|
|
|
|
|
FontEntry *
|
2008-03-03 18:34:05 -08:00
|
|
|
gfxWindowsPlatform::FindFontForChar(PRUint32 aCh, gfxWindowsFont *aFont)
|
2007-05-29 08:09:23 -07:00
|
|
|
{
|
2008-03-03 18:34:05 -08:00
|
|
|
// is codepoint with no matching font? return null immediately
|
|
|
|
if (mCodepointsWithNoFonts.test(aCh)) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
FontSearch data(aCh, aFont);
|
2007-05-29 17:07:03 -07:00
|
|
|
|
|
|
|
// find fonts that support the character
|
2008-03-03 18:34:05 -08:00
|
|
|
mFonts.Enumerate(gfxWindowsPlatform::FindFontForCharProc, &data);
|
2007-05-29 17:07:03 -07:00
|
|
|
|
2008-03-03 18:34:05 -08:00
|
|
|
// no match? add to set of non-matching codepoints
|
|
|
|
if (!data.bestMatch) {
|
|
|
|
mCodepointsWithNoFonts.set(aCh);
|
|
|
|
}
|
|
|
|
|
2007-05-29 17:07:03 -07:00
|
|
|
return data.bestMatch;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-04-02 12:06:16 -07:00
|
|
|
|
|
|
|
gfxFontGroup *
|
|
|
|
gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies,
|
|
|
|
const gfxFontStyle *aStyle)
|
|
|
|
{
|
|
|
|
return new gfxWindowsFontGroup(aFamilies, aStyle);
|
|
|
|
}
|
2007-05-29 17:07:03 -07:00
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
FontFamily *
|
|
|
|
gfxWindowsPlatform::FindFontFamily(const nsAString& aName)
|
2007-05-29 17:07:03 -07:00
|
|
|
{
|
|
|
|
nsString name(aName);
|
|
|
|
ToLowerCase(name);
|
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
nsRefPtr<FontFamily> ff;
|
|
|
|
if (!mFonts.Get(name, &ff) &&
|
|
|
|
!mFontSubstitutes.Get(name, &ff) &&
|
|
|
|
!mFontAliases.Get(name, &ff)) {
|
2007-05-29 17:07:03 -07:00
|
|
|
return nsnull;
|
|
|
|
}
|
2008-03-18 17:06:55 -07:00
|
|
|
return ff.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
FontEntry *
|
|
|
|
gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle *aFontStyle)
|
|
|
|
{
|
|
|
|
nsRefPtr<FontFamily> ff = FindFontFamily(aName);
|
|
|
|
if (!ff)
|
|
|
|
return nsnull;
|
|
|
|
|
2008-03-19 17:41:19 -07:00
|
|
|
return FindFontEntry(ff, aFontStyle);
|
|
|
|
}
|
|
|
|
|
|
|
|
FontEntry *
|
|
|
|
gfxWindowsPlatform::FindFontEntry(FontFamily *aFontFamily, const gfxFontStyle *aFontStyle)
|
|
|
|
{
|
2008-03-18 17:06:55 -07:00
|
|
|
PRUint8 bestMatch = 0;
|
2008-03-20 15:09:45 -07:00
|
|
|
PRBool italic = (aFontStyle->style & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
|
2008-03-18 17:06:55 -07:00
|
|
|
|
|
|
|
nsAutoTArray<nsRefPtr<FontEntry>, 10> weightList;
|
|
|
|
weightList.AppendElements(10);
|
2008-03-20 15:09:45 -07:00
|
|
|
for (PRUint32 j = 0; j < 2; j++) {
|
|
|
|
PRBool matchesSomething = PR_FALSE;
|
|
|
|
// build up an array of weights that match the italicness we're looking for
|
2008-03-21 14:22:29 -07:00
|
|
|
for (PRUint32 i = 0; i < aFontFamily->mVariations.Length(); i++) {
|
2008-03-20 15:09:45 -07:00
|
|
|
nsRefPtr<FontEntry> fe = aFontFamily->mVariations[i];
|
|
|
|
const PRUint8 weight = (fe->mWeight / 100);
|
|
|
|
if (fe->mItalic == italic) {
|
|
|
|
weightList[weight] = fe;
|
|
|
|
matchesSomething = PR_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (matchesSomething)
|
|
|
|
break;
|
|
|
|
italic = !italic;
|
2008-03-18 17:06:55 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
PRInt8 baseWeight, weightDistance;
|
|
|
|
aFontStyle->ComputeWeightAndOffset(&baseWeight, &weightDistance);
|
|
|
|
|
2008-03-20 15:09:45 -07:00
|
|
|
// 500 isn't quite bold so we want to treat it as 400 if we don't
|
|
|
|
// have a 500 weight
|
|
|
|
if (baseWeight == 5 && weightDistance == 0) {
|
|
|
|
// If we have a 500 weight then use it
|
|
|
|
if (weightList[5])
|
|
|
|
return weightList[5];
|
2008-03-18 17:06:55 -07:00
|
|
|
|
2008-03-20 15:09:45 -07:00
|
|
|
// Otherwise treat as 400
|
|
|
|
baseWeight = 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PRInt8 matchBaseWeight = 0;
|
|
|
|
PRInt8 direction = (baseWeight > 5) ? 1 : -1;
|
|
|
|
for (PRInt8 i = baseWeight; ; i += direction) {
|
|
|
|
if (weightList[i]) {
|
|
|
|
matchBaseWeight = i;
|
2008-03-18 17:06:55 -07:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-03-20 15:09:45 -07:00
|
|
|
// if we've reached one side without finding a font,
|
|
|
|
// go the other direction until we find a match
|
|
|
|
if (i == 1 || i == 9)
|
|
|
|
direction = -direction;
|
2008-03-18 17:06:55 -07:00
|
|
|
}
|
|
|
|
|
2008-03-20 15:09:45 -07:00
|
|
|
nsRefPtr<FontEntry> matchFE;
|
|
|
|
const PRInt8 absDistance = abs(weightDistance);
|
|
|
|
direction = (weightDistance >= 0) ? 1 : -1;
|
|
|
|
for (PRInt8 i = matchBaseWeight, k = 0; i < 10 && i > 0; i += direction) {
|
|
|
|
if (weightList[i]) {
|
|
|
|
matchFE = weightList[i];
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
if (k > absDistance)
|
2008-03-18 17:06:55 -07:00
|
|
|
break;
|
|
|
|
}
|
2008-03-19 17:41:19 -07:00
|
|
|
|
2008-03-18 17:06:55 -07:00
|
|
|
if (!matchFE) {
|
2008-03-20 15:09:45 -07:00
|
|
|
/* if we still don't have a match, grab the closest thing in the other direction */
|
|
|
|
direction = -direction;
|
|
|
|
for (PRInt8 i = matchBaseWeight; i < 10 && i > 0; i += direction) {
|
|
|
|
if (weightList[i]) {
|
|
|
|
matchFE = weightList[i];
|
|
|
|
}
|
|
|
|
}
|
2008-03-18 17:06:55 -07:00
|
|
|
}
|
2008-03-20 15:09:45 -07:00
|
|
|
|
|
|
|
|
|
|
|
NS_ASSERTION(matchFE, "we should always be able to return something here");
|
2008-03-18 17:06:55 -07:00
|
|
|
return matchFE;
|
2007-05-29 17:07:03 -07:00
|
|
|
}
|
2007-07-23 15:02:17 -07:00
|
|
|
|
|
|
|
cmsHPROFILE
|
|
|
|
gfxWindowsPlatform::GetPlatformCMSOutputProfile()
|
|
|
|
{
|
|
|
|
WCHAR str[1024+1];
|
|
|
|
DWORD size = 1024;
|
|
|
|
|
|
|
|
HDC dc = GetDC(nsnull);
|
|
|
|
GetICMProfileW(dc, &size, (LPWSTR)&str);
|
|
|
|
ReleaseDC(nsnull, dc);
|
|
|
|
|
|
|
|
cmsHPROFILE profile =
|
|
|
|
cmsOpenProfileFromFile(NS_ConvertUTF16toUTF8(str).get(), "r");
|
|
|
|
#ifdef DEBUG_tor
|
|
|
|
if (profile)
|
|
|
|
fprintf(stderr,
|
|
|
|
"ICM profile read from %s successfully\n",
|
|
|
|
NS_ConvertUTF16toUTF8(str).get());
|
|
|
|
#endif
|
|
|
|
return profile;
|
|
|
|
}
|
2007-08-24 12:41:16 -07:00
|
|
|
|
|
|
|
PRBool
|
2008-03-18 17:06:55 -07:00
|
|
|
gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> > *array)
|
2007-08-24 12:41:16 -07:00
|
|
|
{
|
2008-03-18 17:06:55 -07:00
|
|
|
return mPrefFonts.Get(aKey, array);
|
2007-08-24 12:41:16 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2008-03-18 17:06:55 -07:00
|
|
|
gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<FontEntry> >& array)
|
2007-08-24 12:41:16 -07:00
|
|
|
{
|
2008-03-18 17:06:55 -07:00
|
|
|
mPrefFonts.Put(aKey, array);
|
2007-08-24 12:41:16 -07:00
|
|
|
}
|