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>
24 * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
41 #define PANGO_ENABLE_BACKEND
42 #define PANGO_ENABLE_ENGINE
45 #include "gfxPlatformGtk.h"
47 #include "gfxFontconfigUtils.h"
49 #include "gfxPangoFonts.h"
50 #include "gfxContext.h"
51 #include "gfxUserFontSet.h"
54 #include FT_FREETYPE_H
55 #include "gfxFT2Fonts.h"
61 #include "gfxImageSurface.h"
64 #include "gfxXlibSurface.h"
65 #include "cairo-xlib.h"
69 #include "gfxDirectFBSurface.h"
73 #include "gfxDirectFBSurface.h"
76 #include <fontconfig/fontconfig.h>
78 #include "nsMathUtils.h"
82 #define GDK_PIXMAP_SIZE_MAX 32767
86 #include FT_FREETYPE_H
89 double gfxPlatformGtk::sDPI
= -1.0;
90 gfxFontconfigUtils
*gfxPlatformGtk::sFontconfigUtils
= nsnull
;
93 typedef nsDataHashtable
<nsStringHashKey
, nsRefPtr
<FontFamily
> > FontTable
;
94 static FontTable
*gPlatformFonts
= NULL
;
95 static FontTable
*gPlatformFontAliases
= NULL
;
96 static FT_Library gPlatformFTLibrary
= NULL
;
99 static cairo_user_data_key_t cairo_gdk_drawable_key
;
100 static void do_gdk_drawable_unref (void *data
)
102 GdkDrawable
*d
= (GdkDrawable
*) data
;
106 gfxPlatformGtk::gfxPlatformGtk()
108 if (!sFontconfigUtils
)
109 sFontconfigUtils
= gfxFontconfigUtils::GetFontconfigUtils();
112 FT_Init_FreeType(&gPlatformFTLibrary
);
114 gPlatformFonts
= new FontTable();
115 gPlatformFonts
->Init(100);
116 gPlatformFontAliases
= new FontTable();
117 gPlatformFontAliases
->Init(100);
124 gfxPlatformGtk::~gfxPlatformGtk()
126 gfxFontconfigUtils::Shutdown();
127 sFontconfigUtils
= nsnull
;
130 gfxPangoFontGroup::Shutdown();
132 delete gPlatformFonts
;
133 gPlatformFonts
= NULL
;
134 delete gPlatformFontAliases
;
135 gPlatformFontAliases
= NULL
;
137 FT_Done_FreeType(gPlatformFTLibrary
);
138 gPlatformFTLibrary
= NULL
;
142 // It would be nice to do this (although it might need to be after
143 // the cairo shutdown that happens in ~gfxPlatform). It even looks
144 // idempotent. But it has fatal assertions that fire if stuff is
145 // leaked, and we hit them.
150 already_AddRefed
<gfxASurface
>
151 gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize
& size
,
152 gfxASurface::gfxImageFormat imageFormat
)
154 nsRefPtr
<gfxASurface
> newSurface
= nsnull
;
155 PRBool sizeOk
= PR_TRUE
;
157 if (size
.width
>= GDK_PIXMAP_SIZE_MAX
||
158 size
.height
>= GDK_PIXMAP_SIZE_MAX
)
164 switch (imageFormat
) {
165 case gfxASurface::ImageFormatARGB32
:
166 glitzf
= 0; // GLITZ_STANDARD_ARGB32;
167 xrenderFormatID
= PictStandardARGB32
;
169 case gfxASurface::ImageFormatRGB24
:
170 glitzf
= 1; // GLITZ_STANDARD_RGB24;
171 xrenderFormatID
= PictStandardRGB24
;
173 case gfxASurface::ImageFormatA8
:
174 glitzf
= 2; // GLITZ_STANDARD_A8;
175 xrenderFormatID
= PictStandardA8
;
177 case gfxASurface::ImageFormatA1
:
178 glitzf
= 3; // GLITZ_STANDARD_A1;
179 xrenderFormatID
= PictStandardA1
;
185 // XXX we really need a different interface here, something that passes
186 // in more context, including the display and/or target surface type that
187 // we should try to match
188 Display
* display
= GDK_DISPLAY();
192 GdkPixmap
* pixmap
= nsnull
;
193 XRenderPictFormat
* xrenderFormat
=
194 XRenderFindStandardFormat(display
, xrenderFormatID
);
196 if (xrenderFormat
&& sizeOk
) {
197 pixmap
= gdk_pixmap_new(nsnull
, size
.width
, size
.height
,
198 xrenderFormat
->depth
);
201 gdk_drawable_set_colormap(GDK_DRAWABLE(pixmap
), nsnull
);
202 newSurface
= new gfxXlibSurface(display
,
203 GDK_PIXMAP_XID(GDK_DRAWABLE(pixmap
)),
208 if (newSurface
&& newSurface
->CairoStatus() == 0) {
209 // set up the surface to auto-unref the gdk pixmap when
210 // the surface is released
211 SetGdkDrawable(newSurface
, GDK_DRAWABLE(pixmap
));
213 // something went wrong with the surface creation.
214 // Ignore and let's fall back to image surfaces.
218 // always unref; SetGdkDrawable takes its own ref
220 g_object_unref(pixmap
);
226 newSurface
= new gfxDirectFBSurface(size
, imageFormat
);
231 // We couldn't create a native surface for whatever reason;
232 // e.g., no RENDER, bad size, etc.
233 // Fall back to image surface for the data.
234 newSurface
= new gfxImageSurface(gfxIntSize(size
.width
, size
.height
), imageFormat
);
238 gfxContext
tmpCtx(newSurface
);
239 tmpCtx
.SetOperator(gfxContext::OPERATOR_CLEAR
);
243 return newSurface
.forget();
249 gfxPlatformGtk::GetFontList(const nsACString
& aLangGroup
,
250 const nsACString
& aGenericFamily
,
251 nsStringArray
& aListOfFonts
)
253 return sFontconfigUtils
->GetFontList(aLangGroup
, aGenericFamily
,
258 gfxPlatformGtk::UpdateFontList()
260 return sFontconfigUtils
->UpdateFontList();
264 gfxPlatformGtk::ResolveFontName(const nsAString
& aFontName
,
265 FontResolverCallback aCallback
,
269 return sFontconfigUtils
->ResolveFontName(aFontName
, aCallback
,
274 gfxPlatformGtk::GetStandardFamilyName(const nsAString
& aFontName
, nsAString
& aFamilyName
)
276 return sFontconfigUtils
->GetStandardFamilyName(aFontName
, aFamilyName
);
280 gfxPlatformGtk::CreateFontGroup(const nsAString
&aFamilies
,
281 const gfxFontStyle
*aStyle
,
282 gfxUserFontSet
*aUserFontSet
)
284 return new gfxPangoFontGroup(aFamilies
, aStyle
, aUserFontSet
);
288 gfxPlatformGtk::MakePlatformFont(const gfxProxyFontEntry
*aProxyEntry
,
289 nsISupports
*aLoader
,
290 const PRUint8
*aFontData
, PRUint32 aLength
)
292 // Just being consistent with other platforms.
293 // This will mean that only fonts in SFNT formats will be accepted.
294 if (!gfxFontUtils::ValidateSFNTHeaders(aFontData
, aLength
))
297 return gfxPangoFontGroup::NewFontEntry(*aProxyEntry
, aLoader
,
302 gfxPlatformGtk::IsFontFormatSupported(nsIURI
*aFontURI
, PRUint32 aFormatFlags
)
304 // reject based on format flags
305 if (aFormatFlags
& (gfxUserFontSet::FLAG_FORMAT_EOT
| gfxUserFontSet::FLAG_FORMAT_SVG
)) {
309 // Pango doesn't apply features from AAT TrueType extensions.
310 // Assume that if this is the only SFNT format specified,
311 // then AAT extensions are required for complex script support.
312 if ((aFormatFlags
& gfxUserFontSet::FLAG_FORMAT_TRUETYPE_AAT
)
313 && !(aFormatFlags
& (gfxUserFontSet::FLAG_FORMAT_OPENTYPE
| gfxUserFontSet::FLAG_FORMAT_TRUETYPE
))) {
317 // otherwise, return true
324 gfxPlatformGtk::GetFontList(const nsACString
& aLangGroup
,
325 const nsACString
& aGenericFamily
,
326 nsStringArray
& aListOfFonts
)
328 return sFontconfigUtils
->GetFontList(aLangGroup
, aGenericFamily
,
333 gfxPlatformGtk::UpdateFontList()
335 FcPattern
*pat
= NULL
;
336 FcObjectSet
*os
= NULL
;
337 FcFontSet
*fs
= NULL
;
340 pat
= FcPatternCreate();
341 os
= FcObjectSetBuild(FC_FAMILY
, FC_FILE
, FC_INDEX
, FC_WEIGHT
, FC_SLANT
, FC_WIDTH
, NULL
);
343 fs
= FcFontList(NULL
, pat
, os
);
346 for (int i
= 0; i
< fs
->nfont
; i
++) {
349 if (FcPatternGetString(fs
->fonts
[i
], FC_FAMILY
, 0, (FcChar8
**) &str
) != FcResultMatch
)
352 //printf("Family: %s\n", str);
354 nsAutoString
name(NS_ConvertUTF8toUTF16(nsDependentCString(str
)).get());
355 nsAutoString
key(name
);
358 nsRefPtr
<FontFamily
> ff
;
359 if (!gPlatformFonts
->Get(key
, &ff
)) {
360 ff
= new FontFamily(name
);
361 gPlatformFonts
->Put(key
, ff
);
364 nsRefPtr
<FontEntry
> fe
= new FontEntry(ff
->mName
);
365 ff
->mFaces
.AppendElement(fe
);
367 if (FcPatternGetString(fs
->fonts
[i
], FC_FILE
, 0, (FcChar8
**) &str
) == FcResultMatch
) {
368 fe
->mFilename
= nsDependentCString(str
);
369 //printf(" - file: %s\n", str);
373 if (FcPatternGetInteger(fs
->fonts
[i
], FC_INDEX
, 0, &x
) == FcResultMatch
) {
374 //printf(" - index: %d\n", x);
375 fe
->mFTFontIndex
= x
;
377 fe
->mFTFontIndex
= 0;
380 fe
->mWeight
= gfxFontconfigUtils::GetThebesWeight(fs
->fonts
[i
]);
381 //printf(" - weight: %d\n", fe->mWeight);
383 fe
->mItalic
= PR_FALSE
;
384 if (FcPatternGetInteger(fs
->fonts
[i
], FC_SLANT
, 0, &x
) == FcResultMatch
) {
386 case FC_SLANT_ITALIC
:
387 case FC_SLANT_OBLIQUE
:
388 fe
->mItalic
= PR_TRUE
;
390 //printf(" - slant: %d\n", x);
393 //if (FcPatternGetInteger(fs->fonts[i], FC_WIDTH, 0, &x) == FcResultMatch)
394 //printf(" - width: %d\n", x);
395 // XXX deal with font-stretch stuff later
399 FcPatternDestroy(pat
);
401 FcObjectSetDestroy(os
);
403 FcFontSetDestroy(fs
);
405 return sFontconfigUtils
->UpdateFontList();
409 gfxPlatformGtk::ResolveFontName(const nsAString
& aFontName
,
410 FontResolverCallback aCallback
,
415 nsAutoString
name(aFontName
);
419 nsRefPtr
<FontFamily
> ff
;
420 if (gPlatformFonts
->Get(name
, &ff
) ||
421 gPlatformFontAliases
->Get(name
, &ff
)) {
422 aAborted
= !(*aCallback
)(ff
->mName
, aClosure
);
426 nsCAutoString utf8Name
= NS_ConvertUTF16toUTF8(aFontName
);
428 FcPattern
*npat
= FcPatternCreate();
429 FcPatternAddString(npat
, FC_FAMILY
, (FcChar8
*)utf8Name
.get());
430 FcObjectSet
*nos
= FcObjectSetBuild(FC_FAMILY
, NULL
);
431 FcFontSet
*nfs
= FcFontList(NULL
, npat
, nos
);
433 for (int k
= 0; k
< nfs
->nfont
; k
++) {
435 if (FcPatternGetString(nfs
->fonts
[k
], FC_FAMILY
, 0, (FcChar8
**) &str
) != FcResultMatch
)
437 nsAutoString altName
= NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str
)));
439 //ToLowerCase(altName);
440 if (gPlatformFonts
->Get(altName
, &ff
)) {
441 //printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
442 gPlatformFontAliases
->Put(name
, ff
);
443 aAborted
= !(*aCallback
)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str
))), aClosure
);
448 FcPatternDestroy(npat
);
449 FcObjectSetDestroy(nos
);
450 FcFontSetDestroy(nfs
);
453 npat
= FcPatternCreate();
454 FcPatternAddString(npat
, FC_FAMILY
, (FcChar8
*)utf8Name
.get());
455 FcPatternDel(npat
, FC_LANG
);
456 FcConfigSubstitute(NULL
, npat
, FcMatchPattern
);
457 FcDefaultSubstitute(npat
);
459 nos
= FcObjectSetBuild(FC_FAMILY
, NULL
);
460 nfs
= FcFontList(NULL
, npat
, nos
);
464 FcPattern
*match
= FcFontMatch(NULL
, npat
, &fresult
);
466 FcFontSetAdd(nfs
, match
);
468 for (int k
= 0; k
< nfs
->nfont
; k
++) {
470 if (FcPatternGetString(nfs
->fonts
[k
], FC_FAMILY
, 0, (FcChar8
**) &str
) != FcResultMatch
)
472 nsAutoString altName
= NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str
)));
474 //ToLowerCase(altName);
475 if (gPlatformFonts
->Get(altName
, &ff
)) {
476 //printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
477 gPlatformFontAliases
->Put(name
, ff
);
478 aAborted
= !(*aCallback
)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str
))), aClosure
);
484 FcPatternDestroy(npat
);
485 FcObjectSetDestroy(nos
);
486 FcFontSetDestroy(nfs
);
492 gfxPlatformGtk::GetStandardFamilyName(const nsAString
& aFontName
, nsAString
& aFamilyName
)
494 return sFontconfigUtils
->GetStandardFamilyName(aFontName
, aFamilyName
);
498 gfxPlatformGtk::CreateFontGroup(const nsAString
&aFamilies
,
499 const gfxFontStyle
*aStyle
)
501 return new gfxFT2FontGroup(aFamilies
, aStyle
);
509 gfxPlatformGtk::InitDPI()
511 sDPI
= gdk_screen_get_resolution(gdk_screen_get_default());
514 // Fall back to something sane
520 gfxPlatformGtk::GetPlatformCMSOutputProfile()
523 const char EDID1_ATOM_NAME
[] = "XFree86_DDC_EDID1_RAWDATA";
524 const char ICC_PROFILE_ATOM_NAME
[] = "_ICC_PROFILE";
526 Atom edidAtom
, iccAtom
;
527 Display
*dpy
= GDK_DISPLAY();
528 Window root
= gdk_x11_get_default_root_xwindow();
532 unsigned long retLength
, retAfter
;
533 unsigned char *retProperty
;
535 iccAtom
= XInternAtom(dpy
, ICC_PROFILE_ATOM_NAME
, TRUE
);
537 // read once to get size, once for the data
538 if (Success
== XGetWindowProperty(dpy
, root
, iccAtom
,
540 False
, AnyPropertyType
,
541 &retAtom
, &retFormat
, &retLength
,
542 &retAfter
, &retProperty
)) {
543 XGetWindowProperty(dpy
, root
, iccAtom
,
545 False
, AnyPropertyType
,
546 &retAtom
, &retFormat
, &retLength
,
547 &retAfter
, &retProperty
);
549 cmsHPROFILE profile
=
550 cmsOpenProfileFromMem(retProperty
, retLength
);
557 "ICM profile read from %s successfully\n",
558 ICC_PROFILE_ATOM_NAME
);
565 edidAtom
= XInternAtom(dpy
, EDID1_ATOM_NAME
, TRUE
);
567 if (Success
== XGetWindowProperty(dpy
, root
, edidAtom
, 0, 32,
568 False
, AnyPropertyType
,
569 &retAtom
, &retFormat
, &retLength
,
570 &retAfter
, &retProperty
)) {
572 cmsCIExyY whitePoint
;
573 cmsCIExyYTRIPLE primaries
;
575 if (retLength
!= 128) {
577 fprintf(stderr
, "Short EDID data\n");
582 // Format documented in "VESA E-EDID Implementation Guide"
584 gamma
= (100 + retProperty
[0x17]) / 100.0;
585 whitePoint
.x
= ((retProperty
[0x21] << 2) |
586 (retProperty
[0x1a] >> 2 & 3)) / 1024.0;
587 whitePoint
.y
= ((retProperty
[0x22] << 2) |
588 (retProperty
[0x1a] >> 0 & 3)) / 1024.0;
591 primaries
.Red
.x
= ((retProperty
[0x1b] << 2) |
592 (retProperty
[0x19] >> 6 & 3)) / 1024.0;
593 primaries
.Red
.y
= ((retProperty
[0x1c] << 2) |
594 (retProperty
[0x19] >> 4 & 3)) / 1024.0;
595 primaries
.Red
.Y
= 1.0;
597 primaries
.Green
.x
= ((retProperty
[0x1d] << 2) |
598 (retProperty
[0x19] >> 2 & 3)) / 1024.0;
599 primaries
.Green
.y
= ((retProperty
[0x1e] << 2) |
600 (retProperty
[0x19] >> 0 & 3)) / 1024.0;
601 primaries
.Green
.Y
= 1.0;
603 primaries
.Blue
.x
= ((retProperty
[0x1f] << 2) |
604 (retProperty
[0x1a] >> 6 & 3)) / 1024.0;
605 primaries
.Blue
.y
= ((retProperty
[0x20] << 2) |
606 (retProperty
[0x1a] >> 4 & 3)) / 1024.0;
607 primaries
.Blue
.Y
= 1.0;
612 fprintf(stderr
, "EDID gamma: %f\n", gamma
);
613 fprintf(stderr
, "EDID whitepoint: %f %f %f\n",
614 whitePoint
.x
, whitePoint
.y
, whitePoint
.Y
);
615 fprintf(stderr
, "EDID primaries: [%f %f %f] [%f %f %f] [%f %f %f]\n",
616 primaries
.Red
.x
, primaries
.Red
.y
, primaries
.Red
.Y
,
617 primaries
.Green
.x
, primaries
.Green
.y
, primaries
.Green
.Y
,
618 primaries
.Blue
.x
, primaries
.Blue
.y
, primaries
.Blue
.Y
);
621 LPGAMMATABLE gammaTable
[3];
622 gammaTable
[0] = gammaTable
[1] = gammaTable
[2] =
623 cmsBuildGamma(256, gamma
);
628 cmsHPROFILE profile
=
629 cmsCreateRGBProfile(&whitePoint
, &primaries
, gammaTable
);
631 cmsFreeGamma(gammaTable
[0]);
636 "ICM profile read from %s successfully\n",
652 gfxPlatformGtk::GetFTLibrary()
654 return gPlatformFTLibrary
;
658 gfxPlatformGtk::FindFontFamily(const nsAString
& aName
)
660 nsAutoString
name(aName
);
664 nsRefPtr
<FontFamily
> ff
;
665 if (!gPlatformFonts
->Get(name
, &ff
)) {
672 gfxPlatformGtk::FindFontEntry(const nsAString
& aName
, const gfxFontStyle
& aFontStyle
)
674 nsRefPtr
<FontFamily
> ff
= FindFontFamily(aName
);
678 return ff
->FindFontEntry(aFontStyle
);
684 gfxPlatformGtk::SetGdkDrawable(gfxASurface
*target
,
685 GdkDrawable
*drawable
)
687 if (target
->CairoStatus())
690 gdk_drawable_ref(drawable
);
692 cairo_surface_set_user_data (target
->CairoSurface(),
693 &cairo_gdk_drawable_key
,
695 do_gdk_drawable_unref
);
699 // Look for an existing Colormap that is known to be associated with visual.
701 LookupGdkColormapForVisual(const Screen
* screen
, const Visual
* visual
)
703 Display
* dpy
= DisplayOfScreen(screen
);
704 GdkDisplay
* gdkDpy
= gdk_x11_lookup_xdisplay(dpy
);
708 // I wish there were a gdk_x11_display_lookup_screen.
710 for (int s
= 0; s
< ScreenCount(dpy
); ++s
) {
711 if (ScreenOfDisplay(dpy
, s
) == screen
) {
716 GdkScreen
* gdkScreen
= gdk_display_get_screen(gdkDpy
, screen_num
);
718 // Common case: the display's default colormap
720 GDK_VISUAL_XVISUAL(gdk_screen_get_system_visual(gdkScreen
)))
721 return gdk_screen_get_system_colormap(gdkScreen
);
723 // widget/src/gtk2/mozcontainer.c uses gdk_rgb_get_colormap()
724 // which is inherited by child widgets, so this is the visual
725 // expected when drawing directly to widget surfaces or surfaces
726 // created using cairo_surface_create_similar with
727 // CAIRO_CONTENT_COLOR.
728 // gdk_screen_get_rgb_colormap is the generalization of
729 // gdk_rgb_get_colormap for any screen.
731 GDK_VISUAL_XVISUAL(gdk_screen_get_rgb_visual(gdkScreen
)))
732 return gdk_screen_get_rgb_colormap(gdkScreen
);
734 // This is the visual expected on displays with the Composite
735 // extension enabled when the surface has been created using
736 // cairo_surface_create_similar with CAIRO_CONTENT_COLOR_ALPHA,
737 // as happens with non-unit opacity.
739 GDK_VISUAL_XVISUAL(gdk_screen_get_rgba_visual(gdkScreen
)))
740 return gdk_screen_get_rgba_colormap(gdkScreen
);
747 gfxPlatformGtk::GetGdkDrawable(gfxASurface
*target
)
749 if (target
->CairoStatus())
754 result
= (GdkDrawable
*) cairo_surface_get_user_data (target
->CairoSurface(),
755 &cairo_gdk_drawable_key
);
760 if (target
->GetType() == gfxASurface::SurfaceTypeXlib
) {
761 gfxXlibSurface
*xs
= (gfxXlibSurface
*) target
;
763 // try looking it up in gdk's table
764 result
= (GdkDrawable
*) gdk_xid_table_lookup(xs
->XDrawable());
766 SetGdkDrawable(target
, result
);
770 // If all else fails, try doing a foreign_new
771 // but don't bother if we can't get a colormap.
772 // Without a colormap GDK won't know how to draw.
773 Screen
*screen
= cairo_xlib_surface_get_screen(xs
->CairoSurface());
774 Visual
*visual
= cairo_xlib_surface_get_visual(xs
->CairoSurface());
775 GdkColormap
*cmap
= LookupGdkColormapForVisual(screen
, visual
);
779 result
= (GdkDrawable
*) gdk_pixmap_foreign_new_for_display
780 (gdk_display_get_default(), xs
->XDrawable());
782 gdk_drawable_set_colormap(result
, cmap
);
784 SetGdkDrawable(target
, result
);
785 // Release our ref. The object is held by target. Caller will
786 // only need to ref if it wants to keep the drawable longer than
788 g_object_unref(result
);