/* -*- 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 * Vladimir Vukicevic * Masayuki Nakano * Masatoshi Kimura * * 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 "nsIPrefService.h" #include "nsIPrefBranch2.h" #include "nsServiceManagerUtils.h" #include "nsTArray.h" #include "nsIWindowsRegKey.h" #include "nsILocalFile.h" #include "plbase64.h" #ifdef MOZ_FT2_FONTS #include "ft2build.h" #include FT_FREETYPE_H #include "gfxFT2Fonts.h" #include "cairo-ft.h" #include "nsAppDirectoryServiceDefs.h" #include "gfxFT2FontList.h" #else #include "gfxWindowsFonts.h" #include "gfxGDIFontList.h" #endif /*XXX to get CAIRO_HAS_DDRAW_SURFACE */ #include "cairo.h" #ifdef WINCE #include #ifdef CAIRO_HAS_DDRAW_SURFACE #include "gfxDDrawSurface.h" #endif #endif #include "gfxUserFontSet.h" #include #ifdef MOZ_FT2_FONTS static FT_Library gPlatformFTLibrary = NULL; #endif static __inline void BuildKeyNameFromFontName(nsAString &aName) { if (aName.Length() >= LF_FACESIZE) aName.Truncate(LF_FACESIZE - 1); ToLowerCase(aName); } gfxWindowsPlatform::gfxWindowsPlatform() { mPrefFonts.Init(50); #ifdef MOZ_FT2_FONTS FT_Init_FreeType(&gPlatformFTLibrary); #endif /* Pick the default render mode differently between * desktop, Windows Mobile, and Windows CE. */ #if defined(WINCE_WINDOWS_MOBILE) mRenderMode = RENDER_IMAGE_DDRAW16; #elif defined(WINCE) mRenderMode = RENDER_DDRAW_GL; #else mRenderMode = RENDER_GDI; #endif nsCOMPtr pref = do_GetService(NS_PREFSERVICE_CONTRACTID); PRInt32 rmode; if (NS_SUCCEEDED(pref->GetIntPref("mozilla.widget.render-mode", &rmode))) { if (rmode >= 0 || rmode < RENDER_MODE_MAX) { #ifndef CAIRO_HAS_DDRAW_SURFACE if (rmode == RENDER_DDRAW || rmode == RENDER_DDRAW_GL) rmode = RENDER_IMAGE_STRETCH24; #endif mRenderMode = (RenderMode) rmode; } } } gfxWindowsPlatform::~gfxWindowsPlatform() { // not calling FT_Done_FreeType because cairo may still hold references to // these FT_Faces. See bug 458169. } gfxPlatformFontList* gfxWindowsPlatform::CreatePlatformFontList() { #ifdef MOZ_FT2_FONTS return new gfxFT2FontList(); #else return new gfxGDIFontList(); #endif } already_AddRefed gfxWindowsPlatform::CreateOffscreenSurface(const gfxIntSize& size, gfxASurface::gfxImageFormat imageFormat) { gfxASurface *surf = nsnull; #ifdef CAIRO_HAS_DDRAW_SURFACE if (mRenderMode == RENDER_DDRAW || mRenderMode == RENDER_DDRAW_GL) surf = new gfxDDrawSurface(NULL, size, imageFormat); #endif #ifdef CAIRO_HAS_WIN32_SURFACE if (mRenderMode == RENDER_GDI) surf = new gfxWindowsSurface(size, imageFormat); #endif if (surf == nsnull) surf = new gfxImageSurface(size, imageFormat); NS_IF_ADDREF(surf); return surf; } nsresult gfxWindowsPlatform::GetFontList(const nsACString& aLangGroup, const nsACString& aGenericFamily, nsTArray& aListOfFonts) { gfxPlatformFontList::PlatformFontList()->GetFontList(aLangGroup, aGenericFamily, aListOfFonts); return NS_OK; } static void RemoveCharsetFromFontSubstitute(nsAString &aName) { PRInt32 comma = aName.FindChar(PRUnichar(',')); if (comma >= 0) aName.Truncate(comma); } nsresult gfxWindowsPlatform::UpdateFontList() { gfxPlatformFontList::PlatformFontList()->UpdateFontList(); return NS_OK; } 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) { nsAutoString resolvedName; if (!gfxPlatformFontList::PlatformFontList()-> ResolveFontName(aFontName, resolvedName)) { aAborted = PR_FALSE; return NS_OK; } aAborted = !(*aCallback)(resolvedName, aClosure); return NS_OK; } nsresult gfxWindowsPlatform::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName) { gfxPlatformFontList::PlatformFontList()->GetStandardFamilyName(aFontName, aFamilyName); return NS_OK; } gfxFontGroup * gfxWindowsPlatform::CreateFontGroup(const nsAString &aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet) { #ifdef MOZ_FT2_FONTS return new gfxFT2FontGroup(aFamilies, aStyle); #else return new gfxWindowsFontGroup(aFamilies, aStyle, aUserFontSet); #endif } gfxFontEntry* gfxWindowsPlatform::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry, const nsAString& aFontName) { return gfxPlatformFontList::PlatformFontList()->LookupLocalFont(aProxyEntry, aFontName); } gfxFontEntry* gfxWindowsPlatform::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry, const PRUint8 *aFontData, PRUint32 aLength) { return gfxPlatformFontList::PlatformFontList()->MakePlatformFont(aProxyEntry, aFontData, aLength); } PRBool gfxWindowsPlatform::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags) { // check for strange format flags NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED), "strange font format hint set"); // accept supported formats if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_WOFF | gfxUserFontSet::FLAG_FORMAT_OPENTYPE | gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) { return PR_TRUE; } // reject all other formats, known and unknown if (aFormatFlags != 0) { return PR_FALSE; } // no format hint set, need to look at data return PR_TRUE; } gfxFontFamily * gfxWindowsPlatform::FindFontFamily(const nsAString& aName) { return gfxPlatformFontList::PlatformFontList()->FindFamily(aName); } gfxFontEntry * gfxWindowsPlatform::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle) { nsRefPtr ff = FindFontFamily(aName); if (!ff) return nsnull; PRBool aNeedsBold; return ff->FindFontForStyle(aFontStyle, aNeedsBold); } qcms_profile* gfxWindowsPlatform::GetPlatformCMSOutputProfile() { #ifndef MOZ_FT2_FONTS WCHAR str[1024+1]; DWORD size = 1024; HDC dc = GetDC(nsnull); if (!dc) return nsnull; __try { GetICMProfileW(dc, &size, (LPWSTR)&str); } __except(GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION) { str[0] = 0; } ReleaseDC(nsnull, dc); qcms_profile* profile = qcms_profile_from_path(NS_ConvertUTF16toUTF8(str).get()); #ifdef DEBUG_tor if (profile) fprintf(stderr, "ICM profile read from %s successfully\n", NS_ConvertUTF16toUTF8(str).get()); #endif return profile; #else return nsnull; #endif } PRBool gfxWindowsPlatform::GetPrefFontEntries(const nsCString& aKey, nsTArray > *array) { return mPrefFonts.Get(aKey, array); } void gfxWindowsPlatform::SetPrefFontEntries(const nsCString& aKey, nsTArray >& array) { mPrefFonts.Put(aKey, array); } #ifdef MOZ_FT2_FONTS FT_Library gfxWindowsPlatform::GetFTLibrary() { return gPlatformFTLibrary; } #endif #ifndef MOZ_FT2_FONTS void gfxWindowsPlatform::SetupClusterBoundaries(gfxTextRun *aTextRun, const PRUnichar *aString) { NS_ABORT_IF_FALSE(sizeof(WCHAR) == sizeof(PRUnichar), "WCHAR/PRUnichar not compatible"); PRUint32 length = aTextRun->GetLength(); nsAutoTArray items; PRUint32 maxItems = 4; int numItems; HRESULT result; PRUint32 i, j; do { items.SetLength(maxItems); result = ::ScriptItemize(aString, length, maxItems - 1, NULL, NULL, items.Elements(), &numItems); maxItems <<= 1; if (maxItems > INT_MAX) break; } while (result == E_OUTOFMEMORY); if (result != 0) { return; } nsTArray attrs; for (i = 0; i < PRUint32(numItems); ++i) { PRUint32 offset = items[i].iCharPos; length = items[i + 1].iCharPos - offset; if (attrs.Length() < length) { attrs.SetLength(length); } result = ::ScriptBreak(aString + offset, length, &items[i].a, attrs.Elements()); if (result != 0) { break; } for (j = 1; j < length; ++j) { if (!attrs[j].fCharStop) { gfxTextRun::CompressedGlyph g; // Remember that this character is not the start of a cluster // by setting its glyph data to "not a cluster start", // "is a ligature start", with no glyphs. aTextRun->SetGlyphs(offset + j, g.SetComplex(PR_FALSE, PR_TRUE, 0), nsnull); } } } } #endif void gfxWindowsPlatform::InitDisplayCaps() { HDC dc = GetDC((HWND)nsnull); gfxPlatform::sDPI = GetDeviceCaps(dc, LOGPIXELSY); ReleaseDC((HWND)nsnull, dc); }