Bug 396137. Use Windows cmap font matching in place of ATSUI font matching. r+sr...
[wine-gecko.git] / gfx / thebes / src / gfxPlatform.cpp
blob4ed2b76bd025c5831c719d4730b6939bed7663f6
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is Mozilla Foundation code.
17 * The Initial Developer of the Original Code is Mozilla Foundation.
18 * Portions created by the Initial Developer are Copyright (C) 2005
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Vladimir Vukicevic <vladimir@pobox.com>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
38 #include "gfxPlatform.h"
40 #if defined(XP_WIN)
41 #include "gfxWindowsPlatform.h"
42 #elif defined(XP_MACOSX)
43 #include "gfxPlatformMac.h"
44 #include "gfxQuartzFontCache.h"
45 #elif defined(MOZ_WIDGET_GTK2)
46 #include "gfxPlatformGtk.h"
47 #elif defined(XP_BEOS)
48 #include "gfxBeOSPlatform.h"
49 #elif defined(XP_OS2)
50 #include "gfxOS2Platform.h"
51 #endif
53 #include "gfxContext.h"
54 #include "gfxImageSurface.h"
55 #include "gfxTextRunCache.h"
56 #include "gfxTextRunWordCache.h"
58 #include "nsIPref.h"
59 #include "nsServiceManagerUtils.h"
61 #ifdef MOZ_ENABLE_GLITZ
62 #include <stdlib.h>
63 #endif
65 #include "cairo.h"
66 #include "lcms.h"
68 #include "nsIPrefService.h"
69 #include "nsIPrefBranch.h"
71 gfxPlatform *gPlatform = nsnull;
72 int gGlitzState = -1;
73 static cmsHPROFILE gCMSOutputProfile = nsnull;
74 static cmsHTRANSFORM gCMSRGBTransform = nsnull;
75 static cmsHTRANSFORM gCMSInverseRGBTransform = nsnull;
76 static cmsHTRANSFORM gCMSRGBATransform = nsnull;
78 gfxPlatform*
79 gfxPlatform::GetPlatform()
81 return gPlatform;
84 nsresult
85 gfxPlatform::Init()
87 NS_ASSERTION(!gPlatform, "Already started???");
88 #if defined(XP_WIN)
89 gPlatform = new gfxWindowsPlatform;
90 #elif defined(XP_MACOSX)
91 gPlatform = new gfxPlatformMac;
92 #elif defined(MOZ_WIDGET_GTK2)
93 gPlatform = new gfxPlatformGtk;
94 #elif defined(XP_BEOS)
95 gPlatform = new gfxBeOSPlatform;
96 #elif defined(XP_OS2)
97 gPlatform = new gfxOS2Platform;
98 #endif
99 if (!gPlatform)
100 return NS_ERROR_OUT_OF_MEMORY;
102 nsresult rv;
104 #if defined(XP_MACOSX)
105 rv = gfxQuartzFontCache::Init();
106 if (NS_FAILED(rv)) {
107 NS_ERROR("Could not initialize gfxQuartzFontCache");
108 Shutdown();
109 return rv;
111 #endif
113 rv = gfxFontCache::Init();
114 if (NS_FAILED(rv)) {
115 NS_ERROR("Could not initialize gfxFontCache");
116 Shutdown();
117 return rv;
120 rv = gfxTextRunWordCache::Init();
121 if (NS_FAILED(rv)) {
122 NS_ERROR("Could not initialize gfxTextRunWordCache");
123 Shutdown();
124 return rv;
127 rv = gfxTextRunCache::Init();
128 if (NS_FAILED(rv)) {
129 NS_ERROR("Could not initialize gfxTextRunCache");
130 Shutdown();
131 return rv;
134 return NS_OK;
137 void
138 gfxPlatform::Shutdown()
140 // These may be called before the corresponding subsystems have actually
141 // started up. That's OK, they can handle it.
142 gfxTextRunCache::Shutdown();
143 gfxTextRunWordCache::Shutdown();
144 gfxFontCache::Shutdown();
145 #if defined(XP_MACOSX)
146 gfxQuartzFontCache::Shutdown();
147 #endif
148 delete gPlatform;
149 gPlatform = nsnull;
152 gfxPlatform::~gfxPlatform()
154 // The cairo folks think we should only clean up in debug builds,
155 // but we're generally in the habit of trying to shut down as
156 // cleanly as possible even in production code, so call this
157 // cairo_debug_* function unconditionally.
159 // because cairo can assert and thus crash on shutdown, don't do this in release builds
160 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) || defined(NS_TRACE_MALLOC)
161 cairo_debug_reset_static_data();
162 #endif
164 #if 0
165 // It would be nice to do this (although it might need to be after
166 // the cairo shutdown that happens in ~gfxPlatform). It even looks
167 // idempotent. But it has fatal assertions that fire if stuff is
168 // leaked, and we hit them.
169 FcFini();
170 #endif
173 PRBool
174 gfxPlatform::UseGlitz()
176 #ifdef MOZ_ENABLE_GLITZ
177 if (gGlitzState == -1) {
178 if (getenv("MOZ_GLITZ"))
179 gGlitzState = 1;
180 else
181 gGlitzState = 0;
184 if (gGlitzState)
185 return PR_TRUE;
186 #endif
188 return PR_FALSE;
191 void
192 gfxPlatform::SetUseGlitz(PRBool use)
194 gGlitzState = (use ? 1 : 0);
197 already_AddRefed<gfxASurface>
198 gfxPlatform::OptimizeImage(gfxImageSurface *aSurface,
199 gfxASurface::gfxImageFormat format)
201 const gfxIntSize& surfaceSize = aSurface->GetSize();
203 nsRefPtr<gfxASurface> optSurface = CreateOffscreenSurface(surfaceSize, format);
204 if (!optSurface || optSurface->CairoStatus() != 0)
205 return nsnull;
207 nsRefPtr<gfxContext> tmpCtx(new gfxContext(optSurface));
208 tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
209 tmpCtx->SetSource(aSurface);
210 tmpCtx->Paint();
212 gfxASurface *ret = optSurface;
213 NS_ADDREF(ret);
214 return ret;
217 nsresult
218 gfxPlatform::GetFontList(const nsACString& aLangGroup,
219 const nsACString& aGenericFamily,
220 nsStringArray& aListOfFonts)
222 return NS_ERROR_NOT_IMPLEMENTED;
225 nsresult
226 gfxPlatform::UpdateFontList()
228 return NS_ERROR_NOT_IMPLEMENTED;
231 static void
232 AppendGenericFontFromPref(nsString& aFonts, const char *aLangGroup, const char *aGenericName)
234 nsresult rv;
236 nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
237 if (!prefs)
238 return;
240 nsCAutoString prefName;
241 nsXPIDLString nameValue, nameListValue;
243 nsXPIDLString genericName;
244 if (aGenericName) {
245 genericName = NS_ConvertASCIItoUTF16(aGenericName);
246 } else {
247 prefName.AssignLiteral("font.default.");
248 prefName.Append(aLangGroup);
249 prefs->CopyUnicharPref(prefName.get(), getter_Copies(genericName));
252 nsCAutoString genericDotLang;
253 genericDotLang.Assign(NS_ConvertUTF16toUTF8(genericName));
254 genericDotLang.AppendLiteral(".");
255 genericDotLang.Append(aLangGroup);
257 // fetch font.name.xxx value
258 prefName.AssignLiteral("font.name.");
259 prefName.Append(genericDotLang);
260 rv = prefs->CopyUnicharPref(prefName.get(), getter_Copies(nameValue));
261 if (NS_SUCCEEDED(rv)) {
262 if (!aFonts.IsEmpty())
263 aFonts.AppendLiteral(", ");
264 aFonts.Append(nameValue);
267 // fetch font.name-list.xxx value
268 prefName.AssignLiteral("font.name-list.");
269 prefName.Append(genericDotLang);
270 rv = prefs->CopyUnicharPref(prefName.get(), getter_Copies(nameListValue));
271 if (NS_SUCCEEDED(rv) && !nameListValue.Equals(nameValue)) {
272 if (!aFonts.IsEmpty())
273 aFonts.AppendLiteral(", ");
274 aFonts.Append(nameListValue);
278 void
279 gfxPlatform::GetPrefFonts(const char *aLangGroup, nsString& aFonts, PRBool aAppendUnicode)
281 aFonts.Truncate();
283 AppendGenericFontFromPref(aFonts, aLangGroup, nsnull);
284 if (aAppendUnicode)
285 AppendGenericFontFromPref(aFonts, "x-unicode", nsnull);
288 PRBool
289 gfxPlatform::IsCMSEnabled()
291 static PRBool sEnabled = -1;
292 if (sEnabled == -1) {
293 sEnabled = PR_TRUE;
294 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
295 if (prefs) {
296 PRBool enabled;
297 nsresult rv =
298 prefs->GetBoolPref("gfx.color_management.enabled", &enabled);
299 if (NS_SUCCEEDED(rv)) {
300 sEnabled = enabled;
304 return sEnabled;
307 cmsHPROFILE
308 gfxPlatform::GetPlatformCMSOutputProfile()
310 return nsnull;
313 cmsHPROFILE
314 gfxPlatform::GetCMSOutputProfile()
316 if (!gCMSOutputProfile) {
317 /* Default lcms error action is to abort on error - change */
318 #ifdef DEBUG_tor
319 cmsErrorAction(LCMS_ERROR_SHOW);
320 #else
321 cmsErrorAction(LCMS_ERROR_IGNORE);
322 #endif
324 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
325 if (prefs) {
326 nsXPIDLCString fname;
327 nsresult rv =
328 prefs->GetCharPref("gfx.color_management.display_profile",
329 getter_Copies(fname));
330 if (NS_SUCCEEDED(rv) && !fname.IsEmpty()) {
331 gCMSOutputProfile = cmsOpenProfileFromFile(fname, "r");
332 #ifdef DEBUG_tor
333 if (gCMSOutputProfile)
334 fprintf(stderr,
335 "ICM profile read from %s successfully\n",
336 fname.get());
337 #endif
341 if (!gCMSOutputProfile) {
342 gCMSOutputProfile =
343 gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile();
346 if (!gCMSOutputProfile) {
347 gCMSOutputProfile = cmsCreate_sRGBProfile();
351 return gCMSOutputProfile;
354 cmsHTRANSFORM
355 gfxPlatform::GetCMSRGBTransform()
357 if (!gCMSRGBTransform) {
358 cmsHPROFILE inProfile, outProfile;
359 outProfile = GetCMSOutputProfile();
360 inProfile = cmsCreate_sRGBProfile();
362 if (!inProfile || !outProfile)
363 return nsnull;
365 gCMSRGBTransform = cmsCreateTransform(inProfile, TYPE_RGB_8,
366 outProfile, TYPE_RGB_8,
367 INTENT_PERCEPTUAL, 0);
370 return gCMSRGBTransform;
373 cmsHTRANSFORM
374 gfxPlatform::GetCMSInverseRGBTransform()
376 if (!gCMSInverseRGBTransform) {
377 cmsHPROFILE inProfile, outProfile;
378 inProfile = GetCMSOutputProfile();
379 outProfile = cmsCreate_sRGBProfile();
381 if (!inProfile || !outProfile)
382 return nsnull;
384 gCMSInverseRGBTransform = cmsCreateTransform(inProfile, TYPE_RGB_8,
385 outProfile, TYPE_RGB_8,
386 INTENT_PERCEPTUAL, 0);
389 return gCMSInverseRGBTransform;
392 cmsHTRANSFORM
393 gfxPlatform::GetCMSRGBATransform()
395 if (!gCMSRGBATransform) {
396 cmsHPROFILE inProfile, outProfile;
397 outProfile = GetCMSOutputProfile();
398 inProfile = cmsCreate_sRGBProfile();
400 if (!inProfile || !outProfile)
401 return nsnull;
403 gCMSRGBATransform = cmsCreateTransform(inProfile, TYPE_RGBA_8,
404 outProfile, TYPE_RGBA_8,
405 INTENT_PERCEPTUAL, 0);
408 return gCMSRGBATransform;