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
4 : *
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/
9 : *
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.
14 : *
15 : * The Original Code is Mozilla Foundation code.
16 : *
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.
20 : *
21 : * Contributor(s):
22 : * Vladimir Vukicevic <vladimir@pobox.com>
23 : * Masayuki Nakano <masayuki@d-toybox.com>
24 : * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
25 : *
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.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #ifdef MOZ_PANGO
41 : #define PANGO_ENABLE_BACKEND
42 : #define PANGO_ENABLE_ENGINE
43 : #endif
44 :
45 : #include "gfxPlatformGtk.h"
46 :
47 : #include "nsUnicharUtils.h"
48 : #include "nsUnicodeProperties.h"
49 : #include "gfxFontconfigUtils.h"
50 : #ifdef MOZ_PANGO
51 : #include "gfxPangoFonts.h"
52 : #include "gfxContext.h"
53 : #include "gfxUserFontSet.h"
54 : #else
55 : #include <ft2build.h>
56 : #include FT_FREETYPE_H
57 : #include "gfxFT2Fonts.h"
58 : #endif
59 :
60 : #include "mozilla/gfx/2D.h"
61 :
62 : #include "cairo.h"
63 : #include <gtk/gtk.h>
64 :
65 : #include "gfxImageSurface.h"
66 : #ifdef MOZ_X11
67 : #include <gdk/gdkx.h>
68 : #include "gfxXlibSurface.h"
69 : #include "cairo-xlib.h"
70 :
71 : /* Undefine the Status from Xlib since it will conflict with system headers on OSX */
72 : #if defined(__APPLE__) && defined(Status)
73 : #undef Status
74 : #endif
75 :
76 : #endif /* MOZ_X11 */
77 :
78 : #include <fontconfig/fontconfig.h>
79 :
80 : #include "nsMathUtils.h"
81 :
82 : #define GDK_PIXMAP_SIZE_MAX 32767
83 :
84 : using namespace mozilla;
85 : using namespace mozilla::gfx;
86 : using namespace mozilla::unicode;
87 :
88 : gfxFontconfigUtils *gfxPlatformGtk::sFontconfigUtils = nsnull;
89 :
90 : #ifndef MOZ_PANGO
91 : typedef nsDataHashtable<nsStringHashKey, nsRefPtr<FontFamily> > FontTable;
92 : typedef nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > PrefFontTable;
93 : static FontTable *gPlatformFonts = NULL;
94 : static FontTable *gPlatformFontAliases = NULL;
95 : static PrefFontTable *gPrefFonts = NULL;
96 : static gfxSparseBitSet *gCodepointsWithNoFonts = NULL;
97 : static FT_Library gPlatformFTLibrary = NULL;
98 : #endif
99 :
100 : static cairo_user_data_key_t cairo_gdk_drawable_key;
101 0 : static void do_gdk_drawable_unref (void *data)
102 : {
103 0 : GdkDrawable *d = (GdkDrawable*) data;
104 0 : g_object_unref (d);
105 0 : }
106 :
107 3 : gfxPlatformGtk::gfxPlatformGtk()
108 : {
109 3 : if (!sFontconfigUtils)
110 3 : sFontconfigUtils = gfxFontconfigUtils::GetFontconfigUtils();
111 :
112 : #ifndef MOZ_PANGO
113 : FT_Init_FreeType(&gPlatformFTLibrary);
114 :
115 : gPlatformFonts = new FontTable();
116 : gPlatformFonts->Init(100);
117 : gPlatformFontAliases = new FontTable();
118 : gPlatformFontAliases->Init(100);
119 : gPrefFonts = new PrefFontTable();
120 : gPrefFonts->Init(100);
121 : gCodepointsWithNoFonts = new gfxSparseBitSet();
122 : UpdateFontList();
123 : #endif
124 3 : }
125 :
126 9 : gfxPlatformGtk::~gfxPlatformGtk()
127 : {
128 3 : gfxFontconfigUtils::Shutdown();
129 3 : sFontconfigUtils = nsnull;
130 :
131 : #ifdef MOZ_PANGO
132 3 : gfxPangoFontGroup::Shutdown();
133 : #else
134 : delete gPlatformFonts;
135 : gPlatformFonts = NULL;
136 : delete gPlatformFontAliases;
137 : gPlatformFontAliases = NULL;
138 : delete gPrefFonts;
139 : gPrefFonts = NULL;
140 : delete gCodepointsWithNoFonts;
141 : gCodepointsWithNoFonts = NULL;
142 :
143 : #ifdef NS_FREE_PERMANENT_DATA
144 : // do cairo cleanup *before* closing down the FTLibrary,
145 : // otherwise we'll crash when the gfxPlatform destructor
146 : // calls it (bug 605009)
147 : cairo_debug_reset_static_data();
148 :
149 : FT_Done_FreeType(gPlatformFTLibrary);
150 : gPlatformFTLibrary = NULL;
151 : #endif
152 : #endif
153 :
154 : #if 0
155 : // It would be nice to do this (although it might need to be after
156 : // the cairo shutdown that happens in ~gfxPlatform). It even looks
157 : // idempotent. But it has fatal assertions that fire if stuff is
158 : // leaked, and we hit them.
159 : FcFini();
160 : #endif
161 12 : }
162 :
163 : already_AddRefed<gfxASurface>
164 17 : gfxPlatformGtk::CreateOffscreenSurface(const gfxIntSize& size,
165 : gfxASurface::gfxContentType contentType)
166 : {
167 34 : nsRefPtr<gfxASurface> newSurface;
168 17 : bool needsClear = true;
169 17 : gfxASurface::gfxImageFormat imageFormat = gfxASurface::FormatFromContent(contentType);
170 : #ifdef MOZ_X11
171 : // XXX we really need a different interface here, something that passes
172 : // in more context, including the display and/or target surface type that
173 : // we should try to match
174 17 : GdkScreen *gdkScreen = gdk_screen_get_default();
175 17 : if (gdkScreen) {
176 : // try to optimize it for 16bpp default screen
177 0 : if (gfxASurface::CONTENT_COLOR == contentType) {
178 0 : imageFormat = GetOffscreenFormat();
179 : }
180 :
181 0 : if (UseClientSideRendering()) {
182 : // We're not going to use XRender, so we don't need to
183 : // search for a render format
184 0 : newSurface = new gfxImageSurface(size, imageFormat);
185 : // The gfxImageSurface ctor zeroes this for us, no need to
186 : // waste time clearing again
187 0 : needsClear = false;
188 : } else {
189 0 : Screen *screen = gdk_x11_screen_get_xscreen(gdkScreen);
190 : XRenderPictFormat* xrenderFormat =
191 : gfxXlibSurface::FindRenderFormat(DisplayOfScreen(screen),
192 0 : imageFormat);
193 :
194 0 : if (xrenderFormat) {
195 0 : newSurface = gfxXlibSurface::Create(screen, xrenderFormat, size);
196 : }
197 : }
198 : }
199 : #endif
200 :
201 17 : if (!newSurface) {
202 : // We couldn't create a native surface for whatever reason;
203 : // e.g., no display, no RENDER, bad size, etc.
204 : // Fall back to image surface for the data.
205 17 : newSurface = new gfxImageSurface(size, imageFormat);
206 : }
207 :
208 17 : if (newSurface->CairoStatus()) {
209 0 : newSurface = nsnull; // surface isn't valid for some reason
210 : }
211 :
212 17 : if (newSurface && needsClear) {
213 34 : gfxContext tmpCtx(newSurface);
214 17 : tmpCtx.SetOperator(gfxContext::OPERATOR_CLEAR);
215 17 : tmpCtx.Paint();
216 : }
217 :
218 17 : return newSurface.forget();
219 : }
220 :
221 : #ifdef MOZ_PANGO
222 :
223 : nsresult
224 0 : gfxPlatformGtk::GetFontList(nsIAtom *aLangGroup,
225 : const nsACString& aGenericFamily,
226 : nsTArray<nsString>& aListOfFonts)
227 : {
228 : return sFontconfigUtils->GetFontList(aLangGroup, aGenericFamily,
229 0 : aListOfFonts);
230 : }
231 :
232 : nsresult
233 0 : gfxPlatformGtk::UpdateFontList()
234 : {
235 0 : return sFontconfigUtils->UpdateFontList();
236 : }
237 :
238 : nsresult
239 0 : gfxPlatformGtk::ResolveFontName(const nsAString& aFontName,
240 : FontResolverCallback aCallback,
241 : void *aClosure,
242 : bool& aAborted)
243 : {
244 : return sFontconfigUtils->ResolveFontName(aFontName, aCallback,
245 0 : aClosure, aAborted);
246 : }
247 :
248 : nsresult
249 0 : gfxPlatformGtk::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
250 : {
251 0 : return sFontconfigUtils->GetStandardFamilyName(aFontName, aFamilyName);
252 : }
253 :
254 : gfxFontGroup *
255 0 : gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies,
256 : const gfxFontStyle *aStyle,
257 : gfxUserFontSet *aUserFontSet)
258 : {
259 0 : return new gfxPangoFontGroup(aFamilies, aStyle, aUserFontSet);
260 : }
261 :
262 : gfxFontEntry*
263 0 : gfxPlatformGtk::LookupLocalFont(const gfxProxyFontEntry *aProxyEntry,
264 : const nsAString& aFontName)
265 : {
266 0 : return gfxPangoFontGroup::NewFontEntry(*aProxyEntry, aFontName);
267 : }
268 :
269 : gfxFontEntry*
270 0 : gfxPlatformGtk::MakePlatformFont(const gfxProxyFontEntry *aProxyEntry,
271 : const PRUint8 *aFontData, PRUint32 aLength)
272 : {
273 : // passing ownership of the font data to the new font entry
274 : return gfxPangoFontGroup::NewFontEntry(*aProxyEntry,
275 0 : aFontData, aLength);
276 : }
277 :
278 : bool
279 0 : gfxPlatformGtk::IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags)
280 : {
281 : // check for strange format flags
282 0 : NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
283 : "strange font format hint set");
284 :
285 : // accept supported formats
286 : // Pango doesn't apply features from AAT TrueType extensions.
287 : // Assume that if this is the only SFNT format specified,
288 : // then AAT extensions are required for complex script support.
289 0 : if (aFormatFlags & (gfxUserFontSet::FLAG_FORMAT_WOFF |
290 : gfxUserFontSet::FLAG_FORMAT_OPENTYPE |
291 : gfxUserFontSet::FLAG_FORMAT_TRUETYPE)) {
292 0 : return true;
293 : }
294 :
295 : // reject all other formats, known and unknown
296 0 : if (aFormatFlags != 0) {
297 0 : return false;
298 : }
299 :
300 : // no format hint set, need to look at data
301 0 : return true;
302 : }
303 :
304 : #else
305 :
306 : nsresult
307 : gfxPlatformGtk::GetFontList(nsIAtom *aLangGroup,
308 : const nsACString& aGenericFamily,
309 : nsTArray<nsString>& aListOfFonts)
310 : {
311 : return sFontconfigUtils->GetFontList(aLangGroup, aGenericFamily,
312 : aListOfFonts);
313 : }
314 :
315 : nsresult
316 : gfxPlatformGtk::UpdateFontList()
317 : {
318 : FcPattern *pat = NULL;
319 : FcObjectSet *os = NULL;
320 : FcFontSet *fs = NULL;
321 : PRInt32 result = -1;
322 :
323 : pat = FcPatternCreate();
324 : os = FcObjectSetBuild(FC_FAMILY, FC_FILE, FC_INDEX, FC_WEIGHT, FC_SLANT, FC_WIDTH, NULL);
325 :
326 : fs = FcFontList(NULL, pat, os);
327 :
328 :
329 : for (int i = 0; i < fs->nfont; i++) {
330 : char *str;
331 :
332 : if (FcPatternGetString(fs->fonts[i], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
333 : continue;
334 :
335 : //printf("Family: %s\n", str);
336 :
337 : nsAutoString name(NS_ConvertUTF8toUTF16(nsDependentCString(str)).get());
338 : nsAutoString key(name);
339 : ToLowerCase(key);
340 : nsRefPtr<FontFamily> ff;
341 : if (!gPlatformFonts->Get(key, &ff)) {
342 : ff = new FontFamily(name);
343 : gPlatformFonts->Put(key, ff);
344 : }
345 :
346 : FontEntry *fe = new FontEntry(ff->Name());
347 : ff->AddFontEntry(fe);
348 :
349 : if (FcPatternGetString(fs->fonts[i], FC_FILE, 0, (FcChar8 **) &str) == FcResultMatch) {
350 : fe->mFilename = nsDependentCString(str);
351 : //printf(" - file: %s\n", str);
352 : }
353 :
354 : int x;
355 : if (FcPatternGetInteger(fs->fonts[i], FC_INDEX, 0, &x) == FcResultMatch) {
356 : //printf(" - index: %d\n", x);
357 : fe->mFTFontIndex = x;
358 : } else {
359 : fe->mFTFontIndex = 0;
360 : }
361 :
362 : fe->mWeight = gfxFontconfigUtils::GetThebesWeight(fs->fonts[i]);
363 : //printf(" - weight: %d\n", fe->mWeight);
364 :
365 : fe->mItalic = false;
366 : if (FcPatternGetInteger(fs->fonts[i], FC_SLANT, 0, &x) == FcResultMatch) {
367 : switch (x) {
368 : case FC_SLANT_ITALIC:
369 : case FC_SLANT_OBLIQUE:
370 : fe->mItalic = true;
371 : }
372 : //printf(" - slant: %d\n", x);
373 : }
374 :
375 : //if (FcPatternGetInteger(fs->fonts[i], FC_WIDTH, 0, &x) == FcResultMatch)
376 : //printf(" - width: %d\n", x);
377 : // XXX deal with font-stretch stuff later
378 : }
379 :
380 : if (pat)
381 : FcPatternDestroy(pat);
382 : if (os)
383 : FcObjectSetDestroy(os);
384 : if (fs)
385 : FcFontSetDestroy(fs);
386 :
387 : return sFontconfigUtils->UpdateFontList();
388 : }
389 :
390 : nsresult
391 : gfxPlatformGtk::ResolveFontName(const nsAString& aFontName,
392 : FontResolverCallback aCallback,
393 : void *aClosure,
394 : bool& aAborted)
395 : {
396 :
397 : nsAutoString name(aFontName);
398 : ToLowerCase(name);
399 :
400 : nsRefPtr<FontFamily> ff;
401 : if (gPlatformFonts->Get(name, &ff) ||
402 : gPlatformFontAliases->Get(name, &ff)) {
403 : aAborted = !(*aCallback)(ff->Name(), aClosure);
404 : return NS_OK;
405 : }
406 :
407 : nsCAutoString utf8Name = NS_ConvertUTF16toUTF8(aFontName);
408 :
409 : FcPattern *npat = FcPatternCreate();
410 : FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get());
411 : FcObjectSet *nos = FcObjectSetBuild(FC_FAMILY, NULL);
412 : FcFontSet *nfs = FcFontList(NULL, npat, nos);
413 :
414 : for (int k = 0; k < nfs->nfont; k++) {
415 : FcChar8 *str;
416 : if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
417 : continue;
418 : nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
419 : ToLowerCase(altName);
420 : if (gPlatformFonts->Get(altName, &ff)) {
421 : //printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
422 : gPlatformFontAliases->Put(name, ff);
423 : aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str))), aClosure);
424 : goto DONE;
425 : }
426 : }
427 :
428 : FcPatternDestroy(npat);
429 : FcObjectSetDestroy(nos);
430 : FcFontSetDestroy(nfs);
431 :
432 : {
433 : npat = FcPatternCreate();
434 : FcPatternAddString(npat, FC_FAMILY, (FcChar8*)utf8Name.get());
435 : FcPatternDel(npat, FC_LANG);
436 : FcConfigSubstitute(NULL, npat, FcMatchPattern);
437 : FcDefaultSubstitute(npat);
438 :
439 : nos = FcObjectSetBuild(FC_FAMILY, NULL);
440 : nfs = FcFontList(NULL, npat, nos);
441 :
442 : FcResult fresult;
443 :
444 : FcPattern *match = FcFontMatch(NULL, npat, &fresult);
445 : if (match)
446 : FcFontSetAdd(nfs, match);
447 :
448 : for (int k = 0; k < nfs->nfont; k++) {
449 : FcChar8 *str;
450 : if (FcPatternGetString(nfs->fonts[k], FC_FAMILY, 0, (FcChar8 **) &str) != FcResultMatch)
451 : continue;
452 : nsAutoString altName = NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str)));
453 : ToLowerCase(altName);
454 : if (gPlatformFonts->Get(altName, &ff)) {
455 : //printf("Adding alias: %s -> %s\n", utf8Name.get(), str);
456 : gPlatformFontAliases->Put(name, ff);
457 : aAborted = !(*aCallback)(NS_ConvertUTF8toUTF16(nsDependentCString(reinterpret_cast<char*>(str))), aClosure);
458 : goto DONE;
459 : }
460 : }
461 : }
462 : DONE:
463 : FcPatternDestroy(npat);
464 : FcObjectSetDestroy(nos);
465 : FcFontSetDestroy(nfs);
466 :
467 : return NS_OK;
468 : }
469 :
470 : nsresult
471 : gfxPlatformGtk::GetStandardFamilyName(const nsAString& aFontName, nsAString& aFamilyName)
472 : {
473 : return sFontconfigUtils->GetStandardFamilyName(aFontName, aFamilyName);
474 : }
475 :
476 : gfxFontGroup *
477 : gfxPlatformGtk::CreateFontGroup(const nsAString &aFamilies,
478 : const gfxFontStyle *aStyle,
479 : gfxUserFontSet *aUserFontSet)
480 : {
481 : return new gfxFT2FontGroup(aFamilies, aStyle, aUserFontSet);
482 : }
483 :
484 : #endif
485 :
486 : static PRInt32 sDPI = 0;
487 :
488 : PRInt32
489 0 : gfxPlatformGtk::GetDPI()
490 : {
491 0 : if (!sDPI) {
492 : // Make sure init is run so we have a resolution
493 0 : GdkScreen *screen = gdk_screen_get_default();
494 0 : gtk_settings_get_for_screen(screen);
495 0 : sDPI = PRInt32(round(gdk_screen_get_resolution(screen)));
496 0 : if (sDPI <= 0) {
497 : // Fall back to something sane
498 0 : sDPI = 96;
499 : }
500 : }
501 0 : return sDPI;
502 : }
503 :
504 : gfxImageFormat
505 0 : gfxPlatformGtk::GetOffscreenFormat()
506 : {
507 0 : if (gdk_visual_get_system()->depth == 16) {
508 0 : return gfxASurface::ImageFormatRGB16_565;
509 : }
510 :
511 0 : return gfxASurface::ImageFormatRGB24;
512 : }
513 :
514 : qcms_profile *
515 0 : gfxPlatformGtk::GetPlatformCMSOutputProfile()
516 : {
517 : #ifdef MOZ_X11
518 0 : const char EDID1_ATOM_NAME[] = "XFree86_DDC_EDID1_RAWDATA";
519 0 : const char ICC_PROFILE_ATOM_NAME[] = "_ICC_PROFILE";
520 :
521 : Atom edidAtom, iccAtom;
522 0 : Display *dpy = GDK_DISPLAY();
523 0 : Window root = gdk_x11_get_default_root_xwindow();
524 :
525 : Atom retAtom;
526 : int retFormat;
527 : unsigned long retLength, retAfter;
528 : unsigned char *retProperty ;
529 :
530 0 : iccAtom = XInternAtom(dpy, ICC_PROFILE_ATOM_NAME, TRUE);
531 0 : if (iccAtom) {
532 : // read once to get size, once for the data
533 0 : if (Success == XGetWindowProperty(dpy, root, iccAtom,
534 : 0, 0 /* length */,
535 : False, AnyPropertyType,
536 : &retAtom, &retFormat, &retLength,
537 0 : &retAfter, &retProperty)) {
538 : XGetWindowProperty(dpy, root, iccAtom,
539 : 0, retLength,
540 : False, AnyPropertyType,
541 : &retAtom, &retFormat, &retLength,
542 0 : &retAfter, &retProperty);
543 :
544 0 : qcms_profile* profile = NULL;
545 :
546 0 : if (retLength > 0)
547 0 : profile = qcms_profile_from_memory(retProperty, retLength);
548 :
549 0 : XFree(retProperty);
550 :
551 0 : if (profile) {
552 : #ifdef DEBUG_tor
553 : fprintf(stderr,
554 : "ICM profile read from %s successfully\n",
555 : ICC_PROFILE_ATOM_NAME);
556 : #endif
557 0 : return profile;
558 : }
559 : }
560 : }
561 :
562 0 : edidAtom = XInternAtom(dpy, EDID1_ATOM_NAME, TRUE);
563 0 : if (edidAtom) {
564 0 : if (Success == XGetWindowProperty(dpy, root, edidAtom, 0, 32,
565 : False, AnyPropertyType,
566 : &retAtom, &retFormat, &retLength,
567 0 : &retAfter, &retProperty)) {
568 : double gamma;
569 : qcms_CIE_xyY whitePoint;
570 : qcms_CIE_xyYTRIPLE primaries;
571 :
572 0 : if (retLength != 128) {
573 : #ifdef DEBUG_tor
574 : fprintf(stderr, "Short EDID data\n");
575 : #endif
576 0 : return nsnull;
577 : }
578 :
579 : // Format documented in "VESA E-EDID Implementation Guide"
580 :
581 0 : gamma = (100 + retProperty[0x17]) / 100.0;
582 0 : whitePoint.x = ((retProperty[0x21] << 2) |
583 0 : (retProperty[0x1a] >> 2 & 3)) / 1024.0;
584 0 : whitePoint.y = ((retProperty[0x22] << 2) |
585 0 : (retProperty[0x1a] >> 0 & 3)) / 1024.0;
586 0 : whitePoint.Y = 1.0;
587 :
588 0 : primaries.red.x = ((retProperty[0x1b] << 2) |
589 0 : (retProperty[0x19] >> 6 & 3)) / 1024.0;
590 0 : primaries.red.y = ((retProperty[0x1c] << 2) |
591 0 : (retProperty[0x19] >> 4 & 3)) / 1024.0;
592 0 : primaries.red.Y = 1.0;
593 :
594 0 : primaries.green.x = ((retProperty[0x1d] << 2) |
595 0 : (retProperty[0x19] >> 2 & 3)) / 1024.0;
596 0 : primaries.green.y = ((retProperty[0x1e] << 2) |
597 0 : (retProperty[0x19] >> 0 & 3)) / 1024.0;
598 0 : primaries.green.Y = 1.0;
599 :
600 0 : primaries.blue.x = ((retProperty[0x1f] << 2) |
601 0 : (retProperty[0x1a] >> 6 & 3)) / 1024.0;
602 0 : primaries.blue.y = ((retProperty[0x20] << 2) |
603 0 : (retProperty[0x1a] >> 4 & 3)) / 1024.0;
604 0 : primaries.blue.Y = 1.0;
605 :
606 0 : XFree(retProperty);
607 :
608 : #ifdef DEBUG_tor
609 : fprintf(stderr, "EDID gamma: %f\n", gamma);
610 : fprintf(stderr, "EDID whitepoint: %f %f %f\n",
611 : whitePoint.x, whitePoint.y, whitePoint.Y);
612 : fprintf(stderr, "EDID primaries: [%f %f %f] [%f %f %f] [%f %f %f]\n",
613 : primaries.Red.x, primaries.Red.y, primaries.Red.Y,
614 : primaries.Green.x, primaries.Green.y, primaries.Green.Y,
615 : primaries.Blue.x, primaries.Blue.y, primaries.Blue.Y);
616 : #endif
617 :
618 : qcms_profile* profile =
619 0 : qcms_profile_create_rgb_with_gamma(whitePoint, primaries, gamma);
620 :
621 : #ifdef DEBUG_tor
622 : if (profile) {
623 : fprintf(stderr,
624 : "ICM profile read from %s successfully\n",
625 : EDID1_ATOM_NAME);
626 : }
627 : #endif
628 :
629 0 : return profile;
630 : }
631 : }
632 : #endif
633 :
634 0 : return nsnull;
635 : }
636 :
637 :
638 : #ifndef MOZ_PANGO
639 : FT_Library
640 : gfxPlatformGtk::GetFTLibrary()
641 : {
642 : return gPlatformFTLibrary;
643 : }
644 :
645 : FontFamily *
646 : gfxPlatformGtk::FindFontFamily(const nsAString& aName)
647 : {
648 : nsAutoString name(aName);
649 : ToLowerCase(name);
650 :
651 : nsRefPtr<FontFamily> ff;
652 : if (!gPlatformFonts->Get(name, &ff)) {
653 : return nsnull;
654 : }
655 : return ff.get();
656 : }
657 :
658 : FontEntry *
659 : gfxPlatformGtk::FindFontEntry(const nsAString& aName, const gfxFontStyle& aFontStyle)
660 : {
661 : nsRefPtr<FontFamily> ff = FindFontFamily(aName);
662 : if (!ff)
663 : return nsnull;
664 :
665 : return ff->FindFontEntry(aFontStyle);
666 : }
667 :
668 : static PLDHashOperator
669 : FindFontForCharProc(nsStringHashKey::KeyType aKey,
670 : nsRefPtr<FontFamily>& aFontFamily,
671 : void* aUserArg)
672 : {
673 : GlobalFontMatch *data = (GlobalFontMatch*)aUserArg;
674 : aFontFamily->FindFontForChar(data);
675 : return PL_DHASH_NEXT;
676 : }
677 :
678 : already_AddRefed<gfxFont>
679 : gfxPlatformGtk::FindFontForChar(PRUint32 aCh, gfxFont *aFont)
680 : {
681 : if (!gPlatformFonts || !gCodepointsWithNoFonts)
682 : return nsnull;
683 :
684 : // is codepoint with no matching font? return null immediately
685 : if (gCodepointsWithNoFonts->test(aCh)) {
686 : return nsnull;
687 : }
688 :
689 : GlobalFontMatch data(aCh, GetScriptCode(aCh),
690 : (aFont ? aFont->GetStyle() : nsnull));
691 :
692 : // find fonts that support the character
693 : gPlatformFonts->Enumerate(FindFontForCharProc, &data);
694 :
695 : if (data.mBestMatch) {
696 : nsRefPtr<gfxFT2Font> font =
697 : gfxFT2Font::GetOrMakeFont(static_cast<FontEntry*>(data.mBestMatch.get()),
698 : aFont->GetStyle());
699 : gfxFont* ret = font.forget().get();
700 : return already_AddRefed<gfxFont>(ret);
701 : }
702 :
703 : // no match? add to set of non-matching codepoints
704 : gCodepointsWithNoFonts->set(aCh);
705 :
706 : return nsnull;
707 : }
708 :
709 : bool
710 : gfxPlatformGtk::GetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> > *aFontEntryList)
711 : {
712 : return gPrefFonts->Get(aKey, aFontEntryList);
713 : }
714 :
715 : void
716 : gfxPlatformGtk::SetPrefFontEntries(const nsCString& aKey, nsTArray<nsRefPtr<gfxFontEntry> >& aFontEntryList)
717 : {
718 : gPrefFonts->Put(aKey, aFontEntryList);
719 : }
720 : #endif
721 :
722 :
723 : void
724 0 : gfxPlatformGtk::SetGdkDrawable(gfxASurface *target,
725 : GdkDrawable *drawable)
726 : {
727 0 : if (target->CairoStatus())
728 0 : return;
729 :
730 0 : g_object_ref(drawable);
731 :
732 : cairo_surface_set_user_data (target->CairoSurface(),
733 : &cairo_gdk_drawable_key,
734 : drawable,
735 0 : do_gdk_drawable_unref);
736 : }
737 :
738 : GdkDrawable *
739 0 : gfxPlatformGtk::GetGdkDrawable(gfxASurface *target)
740 : {
741 0 : if (target->CairoStatus())
742 0 : return NULL;
743 :
744 : GdkDrawable *result;
745 :
746 : result = (GdkDrawable*) cairo_surface_get_user_data (target->CairoSurface(),
747 0 : &cairo_gdk_drawable_key);
748 0 : if (result)
749 0 : return result;
750 :
751 : #ifdef MOZ_X11
752 0 : if (target->GetType() != gfxASurface::SurfaceTypeXlib)
753 0 : return NULL;
754 :
755 0 : gfxXlibSurface *xs = static_cast<gfxXlibSurface*>(target);
756 :
757 : // try looking it up in gdk's table
758 0 : result = (GdkDrawable*) gdk_xid_table_lookup(xs->XDrawable());
759 0 : if (result) {
760 0 : SetGdkDrawable(target, result);
761 0 : return result;
762 : }
763 : #endif
764 :
765 0 : return NULL;
766 : }
767 :
768 : RefPtr<ScaledFont>
769 0 : gfxPlatformGtk::GetScaledFontForFont(gfxFont *aFont)
770 : {
771 : NativeFont nativeFont;
772 0 : nativeFont.mType = NATIVE_FONT_SKIA_FONT_FACE;
773 0 : nativeFont.mFont = aFont;
774 : RefPtr<ScaledFont> scaledFont =
775 0 : Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
776 :
777 : return scaledFont;
778 : }
779 :
780 : bool
781 0 : gfxPlatformGtk::SupportsAzure(BackendType& aBackend)
782 : {
783 0 : aBackend = BACKEND_SKIA;
784 0 : return true;
785 : }
786 :
|