adding color management capabilities -- preffed off. bug 16769. patch from tor....
[mozilla-central.git] / gfx / thebes / src / gfxPlatform.cpp
blob45c6c72fb90324daec7451dde9184df693423cb1
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 gCMSRGBATransform = nsnull;
77 gfxPlatform*
78 gfxPlatform::GetPlatform()
80 return gPlatform;
83 nsresult
84 gfxPlatform::Init()
86 NS_ASSERTION(!gPlatform, "Already started???");
87 #if defined(XP_WIN)
88 gPlatform = new gfxWindowsPlatform;
89 #elif defined(XP_MACOSX)
90 gPlatform = new gfxPlatformMac;
91 #elif defined(MOZ_WIDGET_GTK2)
92 gPlatform = new gfxPlatformGtk;
93 #elif defined(XP_BEOS)
94 gPlatform = new gfxBeOSPlatform;
95 #elif defined(XP_OS2)
96 gPlatform = new gfxOS2Platform;
97 #endif
98 if (!gPlatform)
99 return NS_ERROR_OUT_OF_MEMORY;
101 nsresult rv;
103 #if defined(XP_MACOSX)
104 rv = gfxQuartzFontCache::Init();
105 if (NS_FAILED(rv)) {
106 NS_ERROR("Could not initialize gfxQuartzFontCache");
107 Shutdown();
108 return rv;
110 #endif
112 rv = gfxFontCache::Init();
113 if (NS_FAILED(rv)) {
114 NS_ERROR("Could not initialize gfxFontCache");
115 Shutdown();
116 return rv;
119 rv = gfxTextRunWordCache::Init();
120 if (NS_FAILED(rv)) {
121 NS_ERROR("Could not initialize gfxTextRunWordCache");
122 Shutdown();
123 return rv;
126 rv = gfxTextRunCache::Init();
127 if (NS_FAILED(rv)) {
128 NS_ERROR("Could not initialize gfxTextRunCache");
129 Shutdown();
130 return rv;
133 return NS_OK;
136 void
137 gfxPlatform::Shutdown()
139 // These may be called before the corresponding subsystems have actually
140 // started up. That's OK, they can handle it.
141 gfxTextRunCache::Shutdown();
142 gfxTextRunWordCache::Shutdown();
143 gfxFontCache::Shutdown();
144 #if defined(XP_MACOSX)
145 gfxQuartzFontCache::Shutdown();
146 #endif
147 delete gPlatform;
148 gPlatform = nsnull;
151 gfxPlatform::~gfxPlatform()
153 // The cairo folks think we should only clean up in debug builds,
154 // but we're generally in the habit of trying to shut down as
155 // cleanly as possible even in production code, so call this
156 // cairo_debug_* function unconditionally.
157 cairo_debug_reset_static_data();
160 PRBool
161 gfxPlatform::UseGlitz()
163 #ifdef MOZ_ENABLE_GLITZ
164 if (gGlitzState == -1) {
165 if (getenv("MOZ_GLITZ"))
166 gGlitzState = 1;
167 else
168 gGlitzState = 0;
171 if (gGlitzState)
172 return PR_TRUE;
173 #endif
175 return PR_FALSE;
178 void
179 gfxPlatform::SetUseGlitz(PRBool use)
181 gGlitzState = (use ? 1 : 0);
184 PRBool
185 gfxPlatform::DoesARGBImageDataHaveAlpha(PRUint8* data,
186 PRUint32 width,
187 PRUint32 height,
188 PRUint32 stride)
190 PRUint32 *r;
192 for (PRUint32 j = 0; j < height; j++) {
193 r = (PRUint32*) (data + stride*j);
194 for (PRUint32 i = 0; i < width; i++) {
195 if ((*r++ & 0xff000000) != 0xff000000) {
196 return PR_TRUE;
201 return PR_FALSE;
204 already_AddRefed<gfxASurface>
205 gfxPlatform::OptimizeImage(gfxImageSurface *aSurface)
207 const gfxIntSize& surfaceSize = aSurface->GetSize();
209 gfxASurface::gfxImageFormat realFormat = aSurface->Format();
211 if (realFormat == gfxASurface::ImageFormatARGB32) {
212 // this might not really need alpha; figure that out
213 if (!DoesARGBImageDataHaveAlpha(aSurface->Data(),
214 surfaceSize.width,
215 surfaceSize.height,
216 aSurface->Stride()))
218 realFormat = gfxASurface::ImageFormatRGB24;
222 nsRefPtr<gfxASurface> optSurface = CreateOffscreenSurface(surfaceSize, realFormat);
224 if (!optSurface)
225 return nsnull;
227 nsRefPtr<gfxContext> tmpCtx(new gfxContext(optSurface));
228 tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
229 tmpCtx->SetSource(aSurface);
230 tmpCtx->Paint();
232 gfxASurface *ret = optSurface;
233 NS_ADDREF(ret);
234 return ret;
237 nsresult
238 gfxPlatform::GetFontList(const nsACString& aLangGroup,
239 const nsACString& aGenericFamily,
240 nsStringArray& aListOfFonts)
242 return NS_ERROR_NOT_IMPLEMENTED;
245 nsresult
246 gfxPlatform::UpdateFontList()
248 return NS_ERROR_NOT_IMPLEMENTED;
251 static void
252 AppendGenericFontFromPref(nsString& aFonts, const char *aLangGroup, const char *aGenericName)
254 nsresult rv;
256 nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID));
257 if (!prefs)
258 return;
260 nsCAutoString prefName;
261 nsXPIDLString value;
263 nsXPIDLString genericName;
264 if (aGenericName) {
265 genericName = NS_ConvertASCIItoUTF16(aGenericName);
266 } else {
267 prefName.AssignLiteral("font.default.");
268 prefName.Append(aLangGroup);
269 prefs->CopyUnicharPref(prefName.get(), getter_Copies(genericName));
272 nsCAutoString genericDotLang;
273 genericDotLang.Assign(NS_ConvertUTF16toUTF8(genericName));
274 genericDotLang.AppendLiteral(".");
275 genericDotLang.Append(aLangGroup);
277 prefName.AssignLiteral("font.name.");
278 prefName.Append(genericDotLang);
279 rv = prefs->CopyUnicharPref(prefName.get(), getter_Copies(value));
280 if (NS_SUCCEEDED(rv)) {
281 if (!aFonts.IsEmpty())
282 aFonts.AppendLiteral(", ");
283 aFonts.Append(value);
286 prefName.AssignLiteral("font.name-list.");
287 prefName.Append(genericDotLang);
288 rv = prefs->CopyUnicharPref(prefName.get(), getter_Copies(value));
289 if (NS_SUCCEEDED(rv)) {
290 if (!aFonts.IsEmpty())
291 aFonts.AppendLiteral(", ");
292 aFonts.Append(value);
296 void
297 gfxPlatform::GetPrefFonts(const char *aLangGroup, nsString& aFonts, PRBool aAppendUnicode)
299 aFonts.Truncate();
301 AppendGenericFontFromPref(aFonts, aLangGroup, nsnull);
302 if (aAppendUnicode)
303 AppendGenericFontFromPref(aFonts, "x-unicode", nsnull);
306 PRBool
307 gfxPlatform::IsCMSEnabled()
309 static PRBool sEnabled = -1;
310 if (sEnabled == -1) {
311 sEnabled = PR_TRUE;
312 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
313 if (prefs) {
314 PRBool enabled;
315 nsresult rv =
316 prefs->GetBoolPref("gfx.color_management.enabled", &enabled);
317 if (NS_SUCCEEDED(rv)) {
318 sEnabled = enabled;
322 return sEnabled;
325 cmsHPROFILE
326 gfxPlatform::GetPlatformCMSOutputProfile()
328 return nsnull;
331 cmsHPROFILE
332 gfxPlatform::GetCMSOutputProfile()
334 if (!gCMSOutputProfile) {
335 /* Default lcms error action is to abort on error - change */
336 #ifdef DEBUG_tor
337 cmsErrorAction(LCMS_ERROR_SHOW);
338 #else
339 cmsErrorAction(LCMS_ERROR_IGNORE);
340 #endif
342 nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
343 if (prefs) {
344 nsXPIDLCString fname;
345 nsresult rv =
346 prefs->GetCharPref("gfx.color_management.display_profile",
347 getter_Copies(fname));
348 if (NS_SUCCEEDED(rv) && !fname.IsEmpty()) {
349 gCMSOutputProfile = cmsOpenProfileFromFile(fname, "r");
350 #ifdef DEBUG_tor
351 if (gCMSOutputProfile)
352 fprintf(stderr,
353 "ICM profile read from %s successfully\n",
354 fname.get());
355 #endif
359 if (!gCMSOutputProfile) {
360 gCMSOutputProfile =
361 gfxPlatform::GetPlatform()->GetPlatformCMSOutputProfile();
364 if (!gCMSOutputProfile) {
365 gCMSOutputProfile = cmsCreate_sRGBProfile();
369 return gCMSOutputProfile;
372 cmsHTRANSFORM
373 gfxPlatform::GetCMSRGBTransform()
375 if (!gCMSRGBTransform) {
376 cmsHPROFILE inProfile, outProfile;
377 outProfile = GetCMSOutputProfile();
378 inProfile = cmsCreate_sRGBProfile();
380 if (!inProfile || !outProfile)
381 return nsnull;
383 gCMSRGBTransform = cmsCreateTransform(inProfile, TYPE_RGB_8,
384 outProfile, TYPE_RGB_8,
385 INTENT_PERCEPTUAL, 0);
388 return gCMSRGBTransform;
391 cmsHTRANSFORM
392 gfxPlatform::GetCMSRGBATransform()
394 if (!gCMSRGBATransform) {
395 cmsHPROFILE inProfile, outProfile;
396 outProfile = GetCMSOutputProfile();
397 inProfile = cmsCreate_sRGBProfile();
399 if (!inProfile || !outProfile)
400 return nsnull;
402 gCMSRGBATransform = cmsCreateTransform(inProfile, TYPE_RGBA_8,
403 outProfile, TYPE_RGBA_8,
404 INTENT_PERCEPTUAL, 0);
407 return gCMSRGBATransform;