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
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.
22 * Vladimir Vukicevic <vladimir@pobox.com>
23 * Masayuki Nakano <masayuki@d-toybox.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #define PANGO_ENABLE_BACKEND
40 #define PANGO_ENABLE_ENGINE
42 #include "gfxPlatformGtk.h"
44 #include "gfxFontconfigUtils.h"
45 #include "gfxPangoFonts.h"
51 #include "gfxImageSurface.h"
52 #include "gfxXlibSurface.h"
54 #include "gfxPangoFonts.h"
56 #include <pango/pangocairo.h>
58 #ifdef MOZ_ENABLE_GLITZ
59 #include "gfxGlitzSurface.h"
60 #include "glitz-glx.h"
63 #include <fontconfig/fontconfig.h>
65 #include "nsMathUtils.h"
69 PRInt32
gfxPlatformGtk::sDPI
= -1;
70 gfxFontconfigUtils
*gfxPlatformGtk::sFontconfigUtils
= nsnull
;
72 static cairo_user_data_key_t cairo_gdk_pixmap_key
;
73 static void do_gdk_pixmap_unref (void *data
)
75 GdkPixmap
*pmap
= (GdkPixmap
*)data
;
76 gdk_pixmap_unref (pmap
);
79 gfxPlatformGtk::gfxPlatformGtk()
81 #ifdef MOZ_ENABLE_GLITZ
85 if (!sFontconfigUtils
)
86 sFontconfigUtils
= gfxFontconfigUtils::GetFontconfigUtils();
91 gfxPlatformGtk::~gfxPlatformGtk()
93 gfxFontconfigUtils::Shutdown();
94 sFontconfigUtils
= nsnull
;
96 gfxPangoFont::Shutdown();
99 // It would be nice to do this (although it might need to be after
100 // the cairo shutdown that happens in ~gfxPlatform). It even looks
101 // idempotent. But it has fatal assertions that fire if stuff is
102 // leaked, and we hit them.
107 already_AddRefed
<gfxASurface
>
108 gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize
& size
,
109 gfxASurface::gfxImageFormat imageFormat
)
111 nsRefPtr
<gfxASurface
> newSurface
= nsnull
;
115 switch (imageFormat
) {
116 case gfxASurface::ImageFormatARGB32
:
117 glitzf
= 0; // GLITZ_STANDARD_ARGB32;
118 xrenderFormatID
= PictStandardARGB32
;
120 case gfxASurface::ImageFormatRGB24
:
121 glitzf
= 1; // GLITZ_STANDARD_RGB24;
122 xrenderFormatID
= PictStandardRGB24
;
124 case gfxASurface::ImageFormatA8
:
125 glitzf
= 2; // GLITZ_STANDARD_A8;
126 xrenderFormatID
= PictStandardA8
;
128 case gfxASurface::ImageFormatA1
:
129 glitzf
= 3; // GLITZ_STANDARD_A1;
130 xrenderFormatID
= PictStandardA1
;
136 // XXX we really need a different interface here, something that passes
137 // in more context, including the display and/or target surface type that
138 // we should try to match
139 Display
* display
= GDK_DISPLAY();
144 GdkPixmap
* pixmap
= nsnull
;
145 XRenderPictFormat
* xrenderFormat
=
146 XRenderFindStandardFormat(display
, xrenderFormatID
);
149 pixmap
= gdk_pixmap_new(nsnull
, size
.width
, size
.height
,
150 xrenderFormat
->depth
);
153 gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap
), nsnull
);
154 newSurface
= new gfxXlibSurface(display
,
155 GDK_PIXMAP_XID(GDK_DRAWABLE(pixmap
)),
160 if (newSurface
&& newSurface
->CairoStatus() == 0) {
161 // set up the surface to auto-unref the gdk pixmap when
162 // the surface is released
163 newSurface
->SetData(&cairo_gdk_pixmap_key
,
165 do_gdk_pixmap_unref
);
167 // something went wrong with the surface creation.
168 // Ignore and let's fall back to image surfaces.
170 gdk_pixmap_unref(pixmap
);
176 // We don't have Render or we couldn't create an xlib surface for
177 // whatever reason; fall back to image surface for the data.
178 newSurface
= new gfxImageSurface(gfxIntSize(size
.width
, size
.height
), imageFormat
);
182 #ifdef MOZ_ENABLE_GLITZ
183 glitz_drawable_format_t
*gdformat
= glitz_glx_find_pbuffer_format
185 gdk_x11_get_default_screen(),
188 glitz_drawable_t
*gdraw
=
189 glitz_glx_create_pbuffer_drawable(display
,
190 DefaultScreen(display
),
194 glitz_format_t
*gformat
=
195 glitz_find_standard_format(gdraw
, (glitz_format_name_t
)glitzf
);
197 glitz_surface_t
*gsurf
=
198 glitz_surface_create(gdraw
,
205 glitz_surface_attach(gsurf
, gdraw
, GLITZ_DRAWABLE_BUFFER_FRONT_COLOR
);
206 newSurface
= new gfxGlitzSurface(gdraw
, gsurf
, PR_TRUE
);
210 return newSurface
.forget();
214 gfxPlatformGtk::GetFontList(const nsACString
& aLangGroup
,
215 const nsACString
& aGenericFamily
,
216 nsStringArray
& aListOfFonts
)
218 return sFontconfigUtils
->GetFontList(aLangGroup
, aGenericFamily
,
223 gfxPlatformGtk::UpdateFontList()
225 return sFontconfigUtils
->UpdateFontList();
229 gfxPlatformGtk::ResolveFontName(const nsAString
& aFontName
,
230 FontResolverCallback aCallback
,
234 return sFontconfigUtils
->ResolveFontName(aFontName
, aCallback
,
239 gfxPlatformGtk::GetStandardFamilyName(const nsAString
& aFontName
, nsAString
& aFamilyName
)
241 return sFontconfigUtils
->GetStandardFamilyName(aFontName
, aFamilyName
);
245 gfxPlatformGtk::CreateFontGroup(const nsAString
&aFamilies
,
246 const gfxFontStyle
*aStyle
)
248 return new gfxPangoFontGroup(aFamilies
, aStyle
);
253 gfxPlatformGtk::InitDPI()
255 PangoContext
*context
= gdk_pango_context_get ();
256 sDPI
= pango_cairo_context_get_resolution (context
);
257 g_object_unref (context
);
260 // Fall back to something sane
266 gfxPlatformGtk::GetPlatformCMSOutputProfile()
268 const char EDID1_ATOM_NAME
[] = "XFree86_DDC_EDID1_RAWDATA";
269 const char ICC_PROFILE_ATOM_NAME
[] = "_ICC_PROFILE";
271 Atom edidAtom
, iccAtom
;
272 Display
*dpy
= GDK_DISPLAY();
273 Window root
= gdk_x11_get_default_root_xwindow();
277 unsigned long retLength
, retAfter
;
278 unsigned char *retProperty
;
280 iccAtom
= XInternAtom(dpy
, ICC_PROFILE_ATOM_NAME
, TRUE
);
282 // read once to get size, once for the data
283 if (Success
== XGetWindowProperty(dpy
, root
, iccAtom
,
285 False
, AnyPropertyType
,
286 &retAtom
, &retFormat
, &retLength
,
287 &retAfter
, &retProperty
)) {
288 XGetWindowProperty(dpy
, root
, iccAtom
,
290 False
, AnyPropertyType
,
291 &retAtom
, &retFormat
, &retLength
,
292 &retAfter
, &retProperty
);
294 cmsHPROFILE profile
=
295 cmsOpenProfileFromMem(retProperty
, retLength
);
302 "ICM profile read from %s successfully\n",
303 ICC_PROFILE_ATOM_NAME
);
310 edidAtom
= XInternAtom(dpy
, EDID1_ATOM_NAME
, TRUE
);
312 if (Success
== XGetWindowProperty(dpy
, root
, edidAtom
, 0, 32,
313 False
, AnyPropertyType
,
314 &retAtom
, &retFormat
, &retLength
,
315 &retAfter
, &retProperty
)) {
317 cmsCIExyY whitePoint
;
318 cmsCIExyYTRIPLE primaries
;
320 if (retLength
!= 128) {
322 fprintf(stderr
, "Short EDID data\n");
327 // Format documented in "VESA E-EDID Implementation Guide"
329 gamma
= (100 + retProperty
[0x17]) / 100.0;
330 whitePoint
.x
= ((retProperty
[0x21] << 2) |
331 (retProperty
[0x1a] >> 2 & 3)) / 1024.0;
332 whitePoint
.y
= ((retProperty
[0x22] << 2) |
333 (retProperty
[0x1a] >> 0 & 3)) / 1024.0;
336 primaries
.Red
.x
= ((retProperty
[0x1b] << 2) |
337 (retProperty
[0x19] >> 6 & 3)) / 1024.0;
338 primaries
.Red
.y
= ((retProperty
[0x1c] << 2) |
339 (retProperty
[0x19] >> 4 & 3)) / 1024.0;
340 primaries
.Red
.Y
= 1.0;
342 primaries
.Green
.x
= ((retProperty
[0x1d] << 2) |
343 (retProperty
[0x19] >> 2 & 3)) / 1024.0;
344 primaries
.Green
.y
= ((retProperty
[0x1e] << 2) |
345 (retProperty
[0x19] >> 0 & 3)) / 1024.0;
346 primaries
.Green
.Y
= 1.0;
348 primaries
.Blue
.x
= ((retProperty
[0x1f] << 2) |
349 (retProperty
[0x1a] >> 6 & 3)) / 1024.0;
350 primaries
.Blue
.y
= ((retProperty
[0x20] << 2) |
351 (retProperty
[0x1a] >> 4 & 3)) / 1024.0;
352 primaries
.Blue
.Y
= 1.0;
357 fprintf(stderr
, "EDID gamma: %f\n", gamma
);
358 fprintf(stderr
, "EDID whitepoint: %f %f %f\n",
359 whitePoint
.x
, whitePoint
.y
, whitePoint
.Y
);
360 fprintf(stderr
, "EDID primaries: [%f %f %f] [%f %f %f] [%f %f %f]\n",
361 primaries
.Red
.x
, primaries
.Red
.y
, primaries
.Red
.Y
,
362 primaries
.Green
.x
, primaries
.Green
.y
, primaries
.Green
.Y
,
363 primaries
.Blue
.x
, primaries
.Blue
.y
, primaries
.Blue
.Y
);
366 LPGAMMATABLE gammaTable
[3];
367 gammaTable
[0] = gammaTable
[1] = gammaTable
[2] =
368 cmsBuildGamma(256, gamma
);
373 cmsHPROFILE profile
=
374 cmsCreateRGBProfile(&whitePoint
, &primaries
, gammaTable
);
376 cmsFreeGamma(gammaTable
[0]);
381 "ICM profile read from %s successfully\n",