~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/gfx/src/gtk/nsDeviceContextGTK.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
2
// vim:cindent:ts=2:et:sw=2:
 
3
/* ***** BEGIN LICENSE BLOCK *****
 
4
 * Version: NPL 1.1/GPL 2.0/LGPL 2.1
 
5
 *
 
6
 * The contents of this file are subject to the Netscape Public License
 
7
 * Version 1.1 (the "License"); you may not use this file except in
 
8
 * compliance with the License. You may obtain a copy of the License at
 
9
 * http://www.mozilla.org/NPL/
 
10
 *
 
11
 * Software distributed under the License is distributed on an "AS IS" basis,
 
12
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
13
 * for the specific language governing rights and limitations under the
 
14
 * License.
 
15
 *
 
16
 * The Original Code is mozilla.org code.
 
17
 *
 
18
 * The Initial Developer of the Original Code is 
 
19
 * Netscape Communications Corporation.
 
20
 * Portions created by the Initial Developer are Copyright (C) 1998
 
21
 * the Initial Developer. All Rights Reserved.
 
22
 *
 
23
 * Contributor(s):
 
24
 *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de> 
 
25
 *
 
26
 *
 
27
 * Alternatively, the contents of this file may be used under the terms of
 
28
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
29
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
30
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
31
 * of those above. If you wish to allow use of your version of this file only
 
32
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
33
 * use your version of this file under the terms of the NPL, indicate your
 
34
 * decision by deleting the provisions above and replace them with the notice
 
35
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
36
 * the provisions above, a recipient may use your version of this file under
 
37
 * the terms of any one of the NPL, the GPL or the LGPL.
 
38
 *
 
39
 * ***** END LICENSE BLOCK ***** */
 
40
 
 
41
#include <math.h>
 
42
 
 
43
#include "nspr.h"
 
44
#include "nsIPref.h"
 
45
#include "nsIServiceManager.h"
 
46
#include "nsCRT.h"
 
47
 
 
48
#include "nsDeviceContextGTK.h"
 
49
#include "nsGfxCIID.h"
 
50
 
 
51
#ifdef USE_POSTSCRIPT
 
52
#include "nsGfxPSCID.h"
 
53
#include "nsIDeviceContextPS.h"
 
54
#endif /* USE_POSTSCRIPT */
 
55
#ifdef USE_XPRINT
 
56
#include "nsGfxXPrintCID.h"
 
57
#include "nsIDeviceContextXPrint.h"
 
58
#endif /* USE_XPRINT */
 
59
 
 
60
#include "nsFontMetricsUtils.h"
 
61
 
 
62
#include <gdk/gdk.h>
 
63
#include <gdk/gdkx.h>
 
64
 
 
65
#ifdef MOZ_WIDGET_GTK
 
66
#include "gdksuperwin.h"
 
67
#endif /* MOZ_WIDGET_GTK */
 
68
 
 
69
#ifdef MOZ_WIDGET_GTK2
 
70
#include <pango/pango.h>
 
71
#include <pango/pangox.h>
 
72
#include <pango/pango-fontmap.h>
 
73
#endif
 
74
 
 
75
#ifdef MOZ_ENABLE_XFT
 
76
#include "nsFontMetricsUtils.h"
 
77
#include <X11/Xlib.h>
 
78
#include <X11/Xft/Xft.h>
 
79
 
 
80
static PRInt32 GetXftDPI(void);
 
81
#endif
 
82
 
 
83
#include <X11/Xatom.h>
 
84
 
 
85
#include "nsDeviceContextSpecG.h"
 
86
 
 
87
static PRInt32 GetOSDPI(void);
 
88
 
 
89
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
 
90
 
 
91
#define GDK_DEFAULT_FONT1 "-*-helvetica-medium-r-*--*-120-*-*-*-*-iso8859-1"
 
92
#define GDK_DEFAULT_FONT2 "-*-fixed-medium-r-*-*-*-120-*-*-*-*-*-*"
 
93
 
 
94
#ifdef MOZ_WIDGET_GTK
 
95
// this is specific to gtk 1.2
 
96
extern GdkFont *default_font;
 
97
#endif /* MOZ_WIDGET_GTK */
 
98
 
 
99
/**
 
100
 * A singleton instance of nsSystemFontsGTK is created by the first
 
101
 * device context and destroyed by the module destructor.
 
102
 */
 
103
class nsSystemFontsGTK {
 
104
 
 
105
  public:
 
106
    nsSystemFontsGTK(float aPixelsToTwips);
 
107
 
 
108
    const nsFont& GetDefaultFont() { return mDefaultFont; }
 
109
    const nsFont& GetMenuFont() { return mMenuFont; }
 
110
    const nsFont& GetFieldFont() { return mFieldFont; }
 
111
    const nsFont& GetButtonFont() { return mButtonFont; }
 
112
 
 
113
  private:
 
114
    nsresult GetSystemFontInfo(GtkWidget *aWidget, nsFont* aFont,
 
115
                               float aPixelsToTwips) const;
 
116
 
 
117
    /*
 
118
     * The following system font constants exist:
 
119
     *
 
120
     * css2: http://www.w3.org/TR/REC-CSS2/fonts.html#x27
 
121
     * eSystemFont_Caption, eSystemFont_Icon, eSystemFont_Menu,
 
122
     * eSystemFont_MessageBox, eSystemFont_SmallCaption,
 
123
     * eSystemFont_StatusBar,
 
124
     * // css3
 
125
     * eSystemFont_Window, eSystemFont_Document,
 
126
     * eSystemFont_Workspace, eSystemFont_Desktop,
 
127
     * eSystemFont_Info, eSystemFont_Dialog,
 
128
     * eSystemFont_Button, eSystemFont_PullDownMenu,
 
129
     * eSystemFont_List, eSystemFont_Field,
 
130
     * // moz
 
131
     * eSystemFont_Tooltips, eSystemFont_Widget
 
132
     */
 
133
    nsFont mDefaultFont;
 
134
    nsFont mButtonFont;
 
135
    nsFont mFieldFont;
 
136
    nsFont mMenuFont;
 
137
};
 
138
 
 
139
 
 
140
nscoord nsDeviceContextGTK::mDpi = 96;
 
141
static nsSystemFontsGTK *gSystemFonts = nsnull;
 
142
 
 
143
nsDeviceContextGTK::nsDeviceContextGTK()
 
144
  : DeviceContextImpl()
 
145
{
 
146
  mTwipsToPixels = 1.0;
 
147
  mPixelsToTwips = 1.0;
 
148
  mDepth = 0 ;
 
149
  mNumCells = 0;
 
150
 
 
151
  mWidthFloat = 0.0f;
 
152
  mHeightFloat = 0.0f;
 
153
  mWidth = -1;
 
154
  mHeight = -1;
 
155
  mDeviceWindow = nsnull;
 
156
}
 
157
 
 
158
nsDeviceContextGTK::~nsDeviceContextGTK()
 
159
{
 
160
  nsresult rv;
 
161
  nsCOMPtr<nsIPref> prefs = do_GetService(kPrefCID, &rv);
 
162
  if (NS_SUCCEEDED(rv)) {
 
163
    prefs->UnregisterCallback("browser.display.screen_resolution",
 
164
                              prefChanged, (void *)this);
 
165
  }
 
166
}
 
167
 
 
168
/* static */ void nsDeviceContextGTK::Shutdown()
 
169
{
 
170
  if (gSystemFonts) {
 
171
    delete gSystemFonts;
 
172
    gSystemFonts = nsnull;
 
173
  }
 
174
}
 
175
 
 
176
NS_IMETHODIMP nsDeviceContextGTK::Init(nsNativeWidget aNativeWidget)
 
177
{
 
178
  GtkRequisition req;
 
179
  GtkWidget *sb;
 
180
  
 
181
  // get the screen object and its width/height
 
182
  // XXXRight now this will only get the primary monitor.
 
183
 
 
184
  if (!mScreenManager)
 
185
    mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
 
186
  if (!mScreenManager) {
 
187
    return NS_ERROR_FAILURE;
 
188
  }
 
189
 
 
190
#ifdef MOZ_WIDGET_GTK
 
191
 
 
192
  if (aNativeWidget) {
 
193
    // superwin?
 
194
    if (GDK_IS_SUPERWIN(aNativeWidget)) {
 
195
      mDeviceWindow = GDK_SUPERWIN(aNativeWidget)->shell_window;
 
196
    }
 
197
    // gtk widget?
 
198
    else if (GTK_IS_WIDGET(aNativeWidget)) {
 
199
      mDeviceWindow = GTK_WIDGET(aNativeWidget)->window;
 
200
    }
 
201
    // must be a bin_window
 
202
    else {
 
203
      mDeviceWindow = NS_STATIC_CAST(GdkWindow *, aNativeWidget);
 
204
    }
 
205
  }
 
206
 
 
207
#endif /* MOZ_WIDGET_GTK */
 
208
 
 
209
#ifdef MOZ_WIDGET_GTK2
 
210
 
 
211
  if (aNativeWidget) {
 
212
    // can only be a gdk window
 
213
    if (GDK_IS_WINDOW(aNativeWidget))
 
214
      mDeviceWindow = GDK_WINDOW(aNativeWidget);
 
215
    else 
 
216
      NS_WARNING("unsupported native widget type!");
 
217
  }
 
218
 
 
219
#endif
 
220
 
 
221
  nsCOMPtr<nsIScreen> screen;
 
222
  mScreenManager->GetPrimaryScreen ( getter_AddRefs(screen) );
 
223
  if ( screen ) {
 
224
    PRInt32 x, y, width, height, depth;
 
225
    screen->GetRect ( &x, &y, &width, &height );
 
226
    screen->GetPixelDepth ( &depth );
 
227
    mWidthFloat = float(width);
 
228
    mHeightFloat = float(height);
 
229
    mDepth = NS_STATIC_CAST ( PRUint32, depth );
 
230
  }
 
231
    
 
232
  static int initialized = 0;
 
233
  PRInt32 prefVal = -1;
 
234
  if (!initialized) {
 
235
    initialized = 1;
 
236
 
 
237
    // Set prefVal the value of the preference
 
238
    // "browser.display.screen_resolution"
 
239
    // or -1 if we can't get it.
 
240
    // If it's negative, we pretend it's not set.
 
241
    // If it's 0, it means force use of the operating system's logical
 
242
    // resolution.
 
243
    // If it's positive, we use it as the logical resolution
 
244
    nsresult res;
 
245
 
 
246
    nsCOMPtr<nsIPref> prefs(do_GetService(kPrefCID, &res));
 
247
    if (NS_SUCCEEDED(res) && prefs) {
 
248
      res = prefs->GetIntPref("browser.display.screen_resolution", &prefVal);
 
249
      if (NS_FAILED(res)) {
 
250
        prefVal = -1;
 
251
      }
 
252
      prefs->RegisterCallback("browser.display.screen_resolution", prefChanged,
 
253
                              (void *)this);
 
254
    }
 
255
 
 
256
    SetDPI(prefVal);
 
257
  } else {
 
258
    SetDPI(mDpi); // to setup p2t and t2p
 
259
  }
 
260
 
 
261
  sb = gtk_vscrollbar_new(NULL);
 
262
  gtk_widget_ref(sb);
 
263
  gtk_object_sink(GTK_OBJECT(sb));
 
264
#ifdef MOZ_WIDGET_GTK2
 
265
  gtk_widget_ensure_style(sb);
 
266
  gtk_widget_queue_resize(sb);
 
267
#endif /* MOZ_WIDGET_GTK2 */
 
268
  gtk_widget_size_request(sb,&req);
 
269
  mScrollbarWidth = req.width;
 
270
  gtk_widget_destroy(sb);
 
271
  gtk_widget_unref(sb);
 
272
  
 
273
  sb = gtk_hscrollbar_new(NULL);
 
274
  gtk_widget_ref(sb);
 
275
  gtk_object_sink(GTK_OBJECT(sb));
 
276
#ifdef MOZ_WIDGET_GTK2
 
277
  gtk_widget_ensure_style(sb);
 
278
  gtk_widget_queue_resize(sb);
 
279
#endif /* MOZ_WIDGET_GTK2 */
 
280
  gtk_widget_size_request(sb,&req);
 
281
  mScrollbarHeight = req.height;
 
282
  gtk_widget_destroy(sb);
 
283
  gtk_widget_unref(sb);
 
284
 
 
285
#ifdef DEBUG
 
286
  static PRBool once = PR_TRUE;
 
287
  if (once) {
 
288
    printf("GFX: dpi=%d t2p=%g p2t=%g depth=%d\n", mDpi, mTwipsToPixels, mPixelsToTwips,mDepth);
 
289
    once = PR_FALSE;
 
290
  }
 
291
#endif
 
292
 
 
293
  DeviceContextImpl::CommonInit();
 
294
 
 
295
  return NS_OK;
 
296
}
 
297
 
 
298
NS_IMETHODIMP nsDeviceContextGTK::CreateRenderingContext(nsIRenderingContext *&aContext)
 
299
{
 
300
#ifdef NS_PRINT_PREVIEW
 
301
  // Defer to Alt when there is one
 
302
  if (mAltDC && ((mUseAltDC & kUseAltDCFor_CREATERC_PAINT) || (mUseAltDC & kUseAltDCFor_CREATERC_REFLOW))) {
 
303
    return mAltDC->CreateRenderingContext(aContext);
 
304
  }
 
305
#endif
 
306
 
 
307
  nsIRenderingContext *pContext;
 
308
  nsresult             rv;
 
309
  nsDrawingSurfaceGTK  *surf;
 
310
  GtkWidget *w;
 
311
 
 
312
  w = (GtkWidget*)mWidget;
 
313
 
 
314
  // to call init for this, we need to have a valid nsDrawingSurfaceGTK created
 
315
  pContext = new nsRenderingContextGTK();
 
316
 
 
317
  if (nsnull != pContext)
 
318
  {
 
319
    NS_ADDREF(pContext);
 
320
 
 
321
    // create the nsDrawingSurfaceGTK
 
322
    surf = new nsDrawingSurfaceGTK();
 
323
 
 
324
    if (surf && w)
 
325
      {
 
326
        GdkDrawable *gwin = nsnull;
 
327
        GdkDrawable *win = nsnull;
 
328
        // FIXME
 
329
        if (GTK_IS_LAYOUT(w))
 
330
          gwin = (GdkDrawable*)GTK_LAYOUT(w)->bin_window;
 
331
        else
 
332
          gwin = (GdkDrawable*)(w)->window;
 
333
 
 
334
        // window might not be realized... ugh
 
335
        if (gwin)
 
336
          gdk_window_ref(gwin);
 
337
        else {
 
338
          win = gdk_pixmap_new(nsnull,
 
339
                               w->allocation.width,
 
340
                               w->allocation.height,
 
341
                               gdk_rgb_get_visual()->depth);
 
342
#ifdef MOZ_WIDGET_GTK2
 
343
          gdk_drawable_set_colormap(win, gdk_rgb_get_colormap());
 
344
#endif
 
345
        }
 
346
 
 
347
        GdkGC *gc = gdk_gc_new(win);
 
348
 
 
349
        // init the nsDrawingSurfaceGTK
 
350
        rv = surf->Init(win,gc);
 
351
 
 
352
        if (NS_OK == rv)
 
353
          // Init the nsRenderingContextGTK
 
354
          rv = pContext->Init(this, surf);
 
355
      }
 
356
    else
 
357
      rv = NS_ERROR_OUT_OF_MEMORY;
 
358
  }
 
359
  else
 
360
    rv = NS_ERROR_OUT_OF_MEMORY;
 
361
 
 
362
  if (NS_OK != rv)
 
363
  {
 
364
    NS_IF_RELEASE(pContext);
 
365
  }
 
366
 
 
367
  aContext = pContext;
 
368
 
 
369
  return rv;
 
370
}
 
371
 
 
372
NS_IMETHODIMP nsDeviceContextGTK::CreateRenderingContextInstance(nsIRenderingContext *&aContext)
 
373
{
 
374
  nsCOMPtr<nsIRenderingContext> renderingContext = new nsRenderingContextGTK();
 
375
  if (!renderingContext)
 
376
    return NS_ERROR_OUT_OF_MEMORY;
 
377
         
 
378
  aContext = renderingContext;
 
379
  NS_ADDREF(aContext);
 
380
  
 
381
  return NS_OK;
 
382
}
 
383
 
 
384
NS_IMETHODIMP nsDeviceContextGTK::SupportsNativeWidgets(PRBool &aSupportsWidgets)
 
385
{
 
386
  //XXX it is very critical that this not lie!! MMP
 
387
  // read the comments in the mac code for this
 
388
  aSupportsWidgets = PR_TRUE;
 
389
 
 
390
  return NS_OK;
 
391
}
 
392
 
 
393
NS_IMETHODIMP nsDeviceContextGTK::GetScrollBarDimensions(float &aWidth, float &aHeight) const
 
394
{
 
395
  float scale;
 
396
  GetCanonicalPixelScale(scale);
 
397
  aWidth = mScrollbarWidth * mPixelsToTwips * scale;
 
398
  aHeight = mScrollbarHeight * mPixelsToTwips * scale;
 
399
 
 
400
  return NS_OK;
 
401
}
 
402
 
 
403
NS_IMETHODIMP nsDeviceContextGTK::GetSystemFont(nsSystemFontID aID, nsFont *aFont) const
 
404
{
 
405
  nsresult status = NS_OK;
 
406
 
 
407
  if (!gSystemFonts) {
 
408
    gSystemFonts = new nsSystemFontsGTK(mPixelsToTwips);
 
409
  }
 
410
 
 
411
  switch (aID) {
 
412
    case eSystemFont_Menu:         // css2
 
413
    case eSystemFont_PullDownMenu: // css3
 
414
        *aFont = gSystemFonts->GetMenuFont();
 
415
        break;
 
416
 
 
417
    case eSystemFont_Field:        // css3
 
418
    case eSystemFont_List:         // css3
 
419
        *aFont = gSystemFonts->GetFieldFont();
 
420
        break;
 
421
 
 
422
    case eSystemFont_Button:       // css3
 
423
        *aFont = gSystemFonts->GetButtonFont();
 
424
        break;
 
425
 
 
426
    case eSystemFont_Caption:      // css2
 
427
    case eSystemFont_Icon:         // css2
 
428
    case eSystemFont_MessageBox:   // css2
 
429
    case eSystemFont_SmallCaption: // css2
 
430
    case eSystemFont_StatusBar:    // css2
 
431
    case eSystemFont_Window:       // css3
 
432
    case eSystemFont_Document:     // css3
 
433
    case eSystemFont_Workspace:    // css3
 
434
    case eSystemFont_Desktop:      // css3
 
435
    case eSystemFont_Info:         // css3
 
436
    case eSystemFont_Dialog:       // css3
 
437
    case eSystemFont_Tooltips:     // moz
 
438
    case eSystemFont_Widget:       // moz
 
439
        *aFont = gSystemFonts->GetDefaultFont();
 
440
        break;
 
441
  }
 
442
 
 
443
  return status;
 
444
}
 
445
 
 
446
NS_IMETHODIMP nsDeviceContextGTK::CheckFontExistence(const nsString& aFontName)
 
447
{
 
448
  return NS_FontMetricsFamilyExists(this, aFontName);
 
449
}
 
450
 
 
451
NS_IMETHODIMP nsDeviceContextGTK::GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight)
 
452
{
 
453
#ifdef NS_PRINT_PREVIEW
 
454
  // Defer to Alt when there is one
 
455
  if (mAltDC && (mUseAltDC & kUseAltDCFor_SURFACE_DIM)) {
 
456
    return mAltDC->GetDeviceSurfaceDimensions(aWidth, aHeight);
 
457
  }
 
458
#endif
 
459
 
 
460
  if (mWidth == -1)
 
461
    mWidth = NSToIntRound(mWidthFloat * mDevUnitsToAppUnits);
 
462
 
 
463
  if (mHeight == -1)
 
464
    mHeight = NSToIntRound(mHeightFloat * mDevUnitsToAppUnits);
 
465
 
 
466
  aWidth = mWidth;
 
467
  aHeight = mHeight;
 
468
 
 
469
  return NS_OK;
 
470
}
 
471
 
 
472
 
 
473
 
 
474
NS_IMETHODIMP nsDeviceContextGTK::GetRect(nsRect &aRect)
 
475
{
 
476
  // if we have an initialized widget for this device context, use it
 
477
  // to try and get real screen coordinates.
 
478
  if (mDeviceWindow) {
 
479
    gint x, y, width, height, depth;
 
480
    x = y = width = height = 0;
 
481
 
 
482
    gdk_window_get_geometry(mDeviceWindow, &x, &y, &width, &height,
 
483
                            &depth);
 
484
    gdk_window_get_origin(mDeviceWindow, &x, &y);
 
485
 
 
486
    nsCOMPtr<nsIScreen> screen;
 
487
    mScreenManager->ScreenForRect(x, y, width, height, getter_AddRefs(screen));
 
488
    screen->GetRect(&aRect.x, &aRect.y, &aRect.width, &aRect.height);
 
489
    aRect.x = NSToIntRound(mDevUnitsToAppUnits * aRect.x);
 
490
    aRect.y = NSToIntRound(mDevUnitsToAppUnits * aRect.y);
 
491
    aRect.width = NSToIntRound(mDevUnitsToAppUnits * aRect.width);
 
492
    aRect.height = NSToIntRound(mDevUnitsToAppUnits * aRect.height);
 
493
  }
 
494
  else {
 
495
    PRInt32 width, height;
 
496
    GetDeviceSurfaceDimensions(width, height);
 
497
    aRect.x = 0;
 
498
    aRect.y = 0;
 
499
    aRect.width = width;
 
500
    aRect.height = height;
 
501
  }
 
502
  return NS_OK;
 
503
}
 
504
 
 
505
 
 
506
NS_IMETHODIMP nsDeviceContextGTK::GetClientRect(nsRect &aRect)
 
507
{
 
508
  // if we have an initialized widget for this device context, use it
 
509
  // to try and get real screen coordinates.
 
510
  if (mDeviceWindow) {
 
511
    gint x, y, width, height, depth;
 
512
    x = y = width = height = 0;
 
513
 
 
514
    gdk_window_get_geometry(mDeviceWindow, &x, &y, &width, &height,
 
515
                            &depth);
 
516
    gdk_window_get_origin(mDeviceWindow, &x, &y);
 
517
 
 
518
    nsCOMPtr<nsIScreen> screen;
 
519
    mScreenManager->ScreenForRect(x, y, width, height, getter_AddRefs(screen));
 
520
    screen->GetAvailRect(&aRect.x, &aRect.y, &aRect.width, &aRect.height);
 
521
    aRect.x = NSToIntRound(mDevUnitsToAppUnits * aRect.x);
 
522
    aRect.y = NSToIntRound(mDevUnitsToAppUnits * aRect.y);
 
523
    aRect.width = NSToIntRound(mDevUnitsToAppUnits * aRect.width);
 
524
    aRect.height = NSToIntRound(mDevUnitsToAppUnits * aRect.height);
 
525
  }
 
526
  else {
 
527
    PRInt32 width, height;
 
528
    GetDeviceSurfaceDimensions(width, height);
 
529
    aRect.x = 0;
 
530
    aRect.y = 0;
 
531
    aRect.width = width;
 
532
    aRect.height = height;
 
533
  }
 
534
 
 
535
  return NS_OK;
 
536
}
 
537
 
 
538
NS_IMETHODIMP nsDeviceContextGTK::GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
 
539
                                                       nsIDeviceContext *&aContext)
 
540
{
 
541
  nsresult                 rv;
 
542
  PrintMethod              method;
 
543
  nsDeviceContextSpecGTK  *spec = NS_STATIC_CAST(nsDeviceContextSpecGTK *, aDevice);
 
544
  
 
545
  rv = spec->GetPrintMethod(method);
 
546
  if (NS_FAILED(rv)) 
 
547
    return rv;
 
548
 
 
549
#ifdef USE_XPRINT
 
550
  if (method == pmXprint) { // XPRINT
 
551
    static NS_DEFINE_CID(kCDeviceContextXp, NS_DEVICECONTEXTXP_CID);
 
552
    nsCOMPtr<nsIDeviceContextXp> dcxp(do_CreateInstance(kCDeviceContextXp, &rv));
 
553
    NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create Xp Device context.");    
 
554
    if (NS_FAILED(rv)) 
 
555
      return NS_ERROR_GFX_COULD_NOT_LOAD_PRINT_MODULE;
 
556
    
 
557
    rv = dcxp->SetSpec(aDevice);
 
558
    if (NS_FAILED(rv)) 
 
559
      return rv;
 
560
    
 
561
    rv = dcxp->InitDeviceContextXP((nsIDeviceContext*)aContext,
 
562
                                   (nsIDeviceContext*)this);
 
563
    if (NS_FAILED(rv)) 
 
564
      return rv;
 
565
      
 
566
    rv = dcxp->QueryInterface(NS_GET_IID(nsIDeviceContext),
 
567
                              (void **)&aContext);
 
568
    return rv;
 
569
  }
 
570
  else
 
571
#endif /* USE_XPRINT */
 
572
#ifdef USE_POSTSCRIPT
 
573
  if (method == pmPostScript) { // PostScript
 
574
    // default/PS
 
575
    static NS_DEFINE_CID(kCDeviceContextPS, NS_DEVICECONTEXTPS_CID);
 
576
  
 
577
    // Create a Postscript device context 
 
578
    nsCOMPtr<nsIDeviceContextPS> dcps(do_CreateInstance(kCDeviceContextPS, &rv));
 
579
    NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create PS Device context.");
 
580
    if (NS_FAILED(rv)) 
 
581
      return NS_ERROR_GFX_COULD_NOT_LOAD_PRINT_MODULE;
 
582
  
 
583
    rv = dcps->SetSpec(aDevice);
 
584
    if (NS_FAILED(rv)) 
 
585
      return rv;
 
586
      
 
587
    rv = dcps->InitDeviceContextPS((nsIDeviceContext*)aContext,
 
588
                                   (nsIDeviceContext*)this);
 
589
    if (NS_FAILED(rv)) 
 
590
      return rv;
 
591
 
 
592
    rv = dcps->QueryInterface(NS_GET_IID(nsIDeviceContext),
 
593
                              (void **)&aContext);
 
594
    return rv;
 
595
  }
 
596
#endif /* USE_POSTSCRIPT */
 
597
  
 
598
  NS_WARNING("no print module created.");
 
599
  return NS_ERROR_UNEXPECTED;
 
600
}
 
601
 
 
602
NS_IMETHODIMP nsDeviceContextGTK::BeginDocument(PRUnichar * aTitle, PRUnichar* aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage)
 
603
{
 
604
  return NS_OK;
 
605
}
 
606
 
 
607
NS_IMETHODIMP nsDeviceContextGTK::EndDocument(void)
 
608
{
 
609
  return NS_OK;
 
610
}
 
611
 
 
612
NS_IMETHODIMP nsDeviceContextGTK::AbortDocument(void)
 
613
{
 
614
  return NS_OK;
 
615
}
 
616
 
 
617
NS_IMETHODIMP nsDeviceContextGTK::BeginPage(void)
 
618
{
 
619
  return NS_OK;
 
620
}
 
621
 
 
622
NS_IMETHODIMP nsDeviceContextGTK::EndPage(void)
 
623
{
 
624
  return NS_OK;
 
625
}
 
626
 
 
627
NS_IMETHODIMP nsDeviceContextGTK::GetDepth(PRUint32& aDepth)
 
628
{
 
629
  aDepth = mDepth;
 
630
  return NS_OK;
 
631
}
 
632
 
 
633
nsresult
 
634
nsDeviceContextGTK::SetDPI(PRInt32 aPrefDPI)
 
635
{
 
636
  PRInt32 OSVal = GetOSDPI();
 
637
 
 
638
  if (aPrefDPI > 0) {
 
639
    // If there's a valid pref value for the logical resolution,
 
640
    // use it.
 
641
    mDpi = aPrefDPI;
 
642
  } else if ((aPrefDPI == 0) || (OSVal > 96)) {
 
643
    // Either if the pref is 0 (force use of OS value) or the OS
 
644
    // value is bigger than 96, use the OS value.
 
645
    mDpi = OSVal;
 
646
  } else {
 
647
    // if we couldn't get the pref or it's negative, and the OS
 
648
    // value is under 96ppi, then use 96.
 
649
    mDpi = 96;
 
650
  }
 
651
  
 
652
  int pt2t = 72;
 
653
 
 
654
  // make p2t a nice round number - this prevents rounding problems
 
655
  mPixelsToTwips = float(NSToIntRound(float(NSIntPointsToTwips(pt2t)) / float(mDpi)));
 
656
  mTwipsToPixels = 1.0f / mPixelsToTwips;
 
657
 
 
658
  // XXX need to reflow all documents
 
659
  return NS_OK;
 
660
}
 
661
 
 
662
int nsDeviceContextGTK::prefChanged(const char *aPref, void *aClosure)
 
663
{
 
664
  nsDeviceContextGTK *context = (nsDeviceContextGTK*)aClosure;
 
665
  nsresult rv;
 
666
  
 
667
  if (nsCRT::strcmp(aPref, "browser.display.screen_resolution")==0) {
 
668
    PRInt32 dpi;
 
669
    nsCOMPtr<nsIPref> prefs(do_GetService(kPrefCID, &rv));
 
670
    rv = prefs->GetIntPref(aPref, &dpi);
 
671
    if (NS_SUCCEEDED(rv))
 
672
      context->SetDPI(dpi);
 
673
 
 
674
    // If this pref changes, we have to clear our cache of stored system
 
675
    // fonts.
 
676
    if (gSystemFonts) {
 
677
      delete gSystemFonts;
 
678
      gSystemFonts = nsnull;
 
679
    }
 
680
  }
 
681
  
 
682
  return 0;
 
683
}
 
684
 
 
685
#define DEFAULT_TWIP_FONT_SIZE 240
 
686
 
 
687
nsSystemFontsGTK::nsSystemFontsGTK(float aPixelsToTwips)
 
688
  : mDefaultFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
 
689
                 NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE,
 
690
                 DEFAULT_TWIP_FONT_SIZE),
 
691
    mButtonFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
 
692
                NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE,
 
693
                DEFAULT_TWIP_FONT_SIZE),
 
694
    mFieldFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
 
695
               NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE,
 
696
               DEFAULT_TWIP_FONT_SIZE),
 
697
    mMenuFont("sans-serif", NS_FONT_STYLE_NORMAL, NS_FONT_VARIANT_NORMAL,
 
698
               NS_FONT_WEIGHT_NORMAL, NS_FONT_DECORATION_NONE,
 
699
               DEFAULT_TWIP_FONT_SIZE)
 
700
{
 
701
  /*
 
702
   * Much of the widget creation code here is similar to the code in
 
703
   * nsLookAndFeel::InitColors().
 
704
   */
 
705
 
 
706
  // mDefaultFont
 
707
  GtkWidget *label = gtk_label_new("M");
 
708
  GtkWidget *parent = gtk_fixed_new();
 
709
  GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
 
710
 
 
711
  gtk_container_add(GTK_CONTAINER(parent), label);
 
712
  gtk_container_add(GTK_CONTAINER(window), parent);
 
713
 
 
714
  gtk_widget_ensure_style(label);
 
715
 
 
716
  GetSystemFontInfo(label, &mDefaultFont, aPixelsToTwips);
 
717
 
 
718
  gtk_widget_destroy(window);  // no unref, windows are different
 
719
 
 
720
  // mFieldFont
 
721
  GtkWidget *entry = gtk_entry_new();
 
722
  parent = gtk_fixed_new();
 
723
  window = gtk_window_new(GTK_WINDOW_POPUP);
 
724
 
 
725
  gtk_container_add(GTK_CONTAINER(parent), entry);
 
726
  gtk_container_add(GTK_CONTAINER(window), parent);
 
727
  gtk_widget_ensure_style(entry);
 
728
 
 
729
  GetSystemFontInfo(entry, &mFieldFont, aPixelsToTwips);
 
730
 
 
731
  gtk_widget_destroy(window);  // no unref, windows are different
 
732
 
 
733
  // mMenuFont
 
734
  GtkWidget *accel_label = gtk_accel_label_new("M");
 
735
  GtkWidget *menuitem = gtk_menu_item_new();
 
736
  GtkWidget *menu = gtk_menu_new();
 
737
  gtk_object_ref(GTK_OBJECT(menu));
 
738
  gtk_object_sink(GTK_OBJECT(menu));
 
739
 
 
740
  gtk_container_add(GTK_CONTAINER(menuitem), accel_label);
 
741
  gtk_menu_append(GTK_MENU(menu), menuitem);
 
742
 
 
743
  gtk_widget_ensure_style(accel_label);
 
744
 
 
745
  GetSystemFontInfo(accel_label, &mMenuFont, aPixelsToTwips);
 
746
 
 
747
  gtk_widget_unref(menu);
 
748
 
 
749
  // mButtonFont
 
750
  parent = gtk_fixed_new();
 
751
  GtkWidget *button = gtk_button_new();
 
752
  label = gtk_label_new("M");
 
753
  window = gtk_window_new(GTK_WINDOW_POPUP);
 
754
          
 
755
  gtk_container_add(GTK_CONTAINER(button), label);
 
756
  gtk_container_add(GTK_CONTAINER(parent), button);
 
757
  gtk_container_add(GTK_CONTAINER(window), parent);
 
758
 
 
759
  gtk_widget_ensure_style(label);
 
760
 
 
761
  GetSystemFontInfo(label, &mButtonFont, aPixelsToTwips);
 
762
 
 
763
  gtk_widget_destroy(window);  // no unref, windows are different
 
764
 
 
765
}
 
766
 
 
767
#if 0 // debugging code to list the font properties
 
768
static void
 
769
ListFontProps(XFontStruct *aFont, Display *aDisplay)
 
770
{
 
771
  printf("\n\n");
 
772
  for (int i = 0, n = aFont->n_properties; i < n; ++i) {
 
773
    XFontProp *prop = aFont->properties + i;
 
774
    char *atomName = ::XGetAtomName(aDisplay, prop->name);
 
775
    // 500 is just a guess
 
776
    char *cardName = (prop->card32 > 0 && prop->card32 < 500)
 
777
                       ? ::XGetAtomName(aDisplay, prop->card32)
 
778
                       : 0;
 
779
    printf("%s : %ld (%s)\n", atomName, prop->card32, cardName?cardName:"");
 
780
    ::XFree(atomName);
 
781
    if (cardName)
 
782
      ::XFree(cardName);
 
783
  }
 
784
  printf("\n\n");
 
785
}
 
786
#endif
 
787
 
 
788
#if defined(MOZ_ENABLE_COREXFONTS) || defined(MOZ_WIDGET_GTK)
 
789
 
 
790
#define LOCATE_MINUS(pos, str)  { \
 
791
   pos = str.FindChar('-'); \
 
792
   if (pos < 0) \
 
793
     return ; \
 
794
  }
 
795
#define NEXT_MINUS(pos, str) { \
 
796
   pos = str.FindChar('-', pos+1); \
 
797
   if (pos < 0) \
 
798
     return ; \
 
799
  }  
 
800
 
 
801
static void
 
802
AppendFontFFREName(nsString& aString, const char* aXLFDName)
 
803
{
 
804
  // convert fontname from XFLD to FFRE and append, ie. from
 
805
  // -adobe-courier-medium-o-normal--14-140-75-75-m-90-iso8859-15
 
806
  // to
 
807
  // adobe-courier-iso8859-15
 
808
  nsCAutoString nameStr(aXLFDName);
 
809
  PRInt32 pos1, pos2;
 
810
  // remove first '-' and everything before it. 
 
811
  LOCATE_MINUS(pos1, nameStr);
 
812
  nameStr.Cut(0, pos1+1);
 
813
 
 
814
  // skip foundry and family name
 
815
  LOCATE_MINUS(pos1, nameStr);
 
816
  NEXT_MINUS(pos1, nameStr);
 
817
  pos2 = pos1;
 
818
 
 
819
  // find '-' just before charset registry
 
820
  for (PRInt32 i=0; i < 10; i++) {
 
821
    NEXT_MINUS(pos2, nameStr);
 
822
  }
 
823
 
 
824
  // remove everything in between
 
825
  nameStr.Cut(pos1, pos2-pos1);
 
826
 
 
827
  aString.AppendWithConversion(nameStr.get());
 
828
}
 
829
#endif /* MOZ_ENABLE_COREXFONTS || MOZ_WIDGET_GTK*/
 
830
 
 
831
#ifdef MOZ_WIDGET_GTK
 
832
static void
 
833
AppendFontName(XFontStruct* aFontStruct, nsString& aString, Display *aDisplay)
 
834
{
 
835
  unsigned long pr = 0;
 
836
  // we first append the FFRE name to reconstruct font more faithfully
 
837
  unsigned long font_atom = gdk_atom_intern("FONT", FALSE);
 
838
  if (::XGetFontProperty(aFontStruct, font_atom, &pr) && pr) {
 
839
    char* xlfdName = ::XGetAtomName(aDisplay, pr);
 
840
    AppendFontFFREName(aString, xlfdName);
 
841
    ::XFree(xlfdName);
 
842
  }
 
843
 
 
844
  aString.Append(PRUnichar(','));
 
845
 
 
846
  // next, we need to append family name to cover more encodings.
 
847
  if ((::XGetFontProperty(aFontStruct, XA_FAMILY_NAME, &pr) ||
 
848
       ::XGetFontProperty(aFontStruct, XA_FULL_NAME, &pr)) &&
 
849
      pr) {
 
850
    char *fontName = ::XGetAtomName(aDisplay, pr);
 
851
    aString.AppendWithConversion(fontName);
 
852
    ::XFree(fontName);
 
853
  }
 
854
}
 
855
 
 
856
static PRUint16
 
857
GetFontWeight(XFontStruct* aFontStruct, Display *aDisplay)
 
858
{
 
859
  PRUint16 weight = NS_FONT_WEIGHT_NORMAL;
 
860
 
 
861
  // WEIGHT_NAME seems more reliable than WEIGHT, where 10 can mean
 
862
  // anything.  Check both, and make it bold if either says so.
 
863
  unsigned long pr = 0;
 
864
  Atom weightName = ::XInternAtom(aDisplay, "WEIGHT_NAME", True);
 
865
  if (weightName != None) {
 
866
    if (::XGetFontProperty(aFontStruct, weightName, &pr) && pr) {
 
867
      char *weightString = ::XGetAtomName(aDisplay, pr);
 
868
      if (nsCRT::strcasecmp(weightString, "bold") == 0)
 
869
        weight = NS_FONT_WEIGHT_BOLD;
 
870
      ::XFree(weightString);
 
871
    }
 
872
  }
 
873
 
 
874
  pr = 0;
 
875
  if (::XGetFontProperty(aFontStruct, XA_WEIGHT, &pr) && pr > 10 )
 
876
    weight = NS_FONT_WEIGHT_BOLD;
 
877
 
 
878
  return weight;
 
879
}
 
880
 
 
881
static nscoord
 
882
GetFontSize(XFontStruct *aFontStruct, float aPixelsToTwips)
 
883
{
 
884
  unsigned long pr = 0;
 
885
  Atom pixelSizeAtom = ::XInternAtom(GDK_DISPLAY(), "PIXEL_SIZE", 0);
 
886
  if (!::XGetFontProperty(aFontStruct, pixelSizeAtom, &pr) || !pr)
 
887
    return DEFAULT_TWIP_FONT_SIZE;
 
888
  return NSIntPixelsToTwips(pr, aPixelsToTwips);
 
889
}
 
890
 
 
891
nsresult
 
892
nsSystemFontsGTK::GetSystemFontInfo(GtkWidget *aWidget, nsFont* aFont,
 
893
                                    float aPixelsToTwips) const
 
894
{
 
895
  GtkStyle *style = gtk_widget_get_style(aWidget);
 
896
 
 
897
  GdkFont *theFont = style->font;
 
898
 
 
899
  aFont->style       = NS_FONT_STYLE_NORMAL;
 
900
  aFont->weight      = NS_FONT_WEIGHT_NORMAL;
 
901
  aFont->decorations = NS_FONT_DECORATION_NONE;
 
902
  
 
903
  // do we have the default_font defined by GTK/GDK then
 
904
  // we use it, if not then we load helvetica, if not then
 
905
  // we load fixed font else we error out.
 
906
  if (!theFont)
 
907
    theFont = default_font; // GTK default font
 
908
 
 
909
  if (!theFont)
 
910
    theFont = ::gdk_font_load( GDK_DEFAULT_FONT1 );
 
911
  
 
912
  if (!theFont)
 
913
    theFont = ::gdk_font_load( GDK_DEFAULT_FONT2 );
 
914
  
 
915
  if (!theFont)
 
916
    return NS_ERROR_FAILURE;
 
917
 
 
918
  Display *fontDisplay = GDK_FONT_XDISPLAY(theFont);
 
919
  if (theFont->type == GDK_FONT_FONT) {
 
920
    XFontStruct *fontStruct =
 
921
        NS_STATIC_CAST(XFontStruct*, GDK_FONT_XFONT(theFont));
 
922
 
 
923
    aFont->name.Truncate();
 
924
    AppendFontName(fontStruct, aFont->name, fontDisplay);
 
925
    aFont->weight = GetFontWeight(fontStruct, fontDisplay);
 
926
    aFont->size = GetFontSize(fontStruct, aPixelsToTwips);
 
927
  } else {
 
928
    NS_ASSERTION(theFont->type == GDK_FONT_FONTSET,
 
929
                 "theFont->type can only have two values");
 
930
 
 
931
    XFontSet fontSet = NS_REINTERPRET_CAST(XFontSet, GDK_FONT_XFONT(theFont));
 
932
    XFontStruct **fontStructs;
 
933
    char **fontNames;
 
934
    int numFonts = ::XFontsOfFontSet(fontSet, &fontStructs, &fontNames);
 
935
    if (numFonts == 0)
 
936
      return NS_ERROR_FAILURE;
 
937
 
 
938
    // Use the weight and size from the first font, but append all
 
939
    // the names.
 
940
    aFont->weight = GetFontWeight(*fontStructs, fontDisplay);
 
941
    aFont->size = GetFontSize(*fontStructs, aPixelsToTwips);
 
942
    nsString& fontName = aFont->name;
 
943
    fontName.Truncate();
 
944
    for (;;) {
 
945
      // we need to append FFRE name instead of family name in this case
 
946
      AppendFontFFREName(fontName, *fontNames);
 
947
      ++fontNames;
 
948
      --numFonts;
 
949
      if (numFonts == 0)
 
950
        break;
 
951
      fontName.Append(PRUnichar(','));
 
952
    }
 
953
  }
 
954
  return NS_OK;
 
955
}
 
956
#endif /* MOZ_WIDGET_GTK */
 
957
 
 
958
#ifdef MOZ_WIDGET_GTK2
 
959
 
 
960
#ifdef MOZ_ENABLE_COREXFONTS
 
961
static void xlfd_from_pango_font_description(GtkWidget *aWidget,
 
962
                                             const PangoFontDescription *aFontDesc,
 
963
                                             nsString& aFontName);
 
964
#endif /* MOZ_ENABLE_COREXFONTS */
 
965
 
 
966
nsresult
 
967
nsSystemFontsGTK::GetSystemFontInfo(GtkWidget *aWidget, nsFont* aFont,
 
968
                                    float aPixelsToTwips) const
 
969
{
 
970
  GtkSettings *settings = gtk_widget_get_settings(aWidget);
 
971
 
 
972
  aFont->style       = NS_FONT_STYLE_NORMAL;
 
973
  aFont->decorations = NS_FONT_DECORATION_NONE;
 
974
 
 
975
  gchar *fontname;
 
976
  g_object_get(settings, "gtk-font-name", &fontname, NULL);
 
977
 
 
978
  PangoFontDescription *desc;
 
979
  desc = pango_font_description_from_string(fontname);
 
980
 
 
981
  aFont->systemFont = PR_TRUE;
 
982
 
 
983
  g_free(fontname);
 
984
 
 
985
  aFont->name.Truncate();
 
986
#ifdef MOZ_ENABLE_XFT
 
987
  if (NS_IsXftEnabled()) {
 
988
    aFont->name.Assign(PRUnichar('"'));
 
989
    aFont->name.AppendWithConversion(pango_font_description_get_family(desc));
 
990
    aFont->name.Append(PRUnichar('"'));
 
991
  }
 
992
#endif /* MOZ_ENABLE_XFT */
 
993
 
 
994
#ifdef MOZ_ENABLE_COREXFONTS
 
995
  // if name already set by Xft, do nothing
 
996
  if (!aFont->name.Length()) {
 
997
    xlfd_from_pango_font_description(aWidget, desc, aFont->name);
 
998
  }
 
999
#endif /* MOZ_ENABLE_COREXFONTS */
 
1000
  aFont->weight = pango_font_description_get_weight(desc);
 
1001
 
 
1002
  float size = float(pango_font_description_get_size(desc) / PANGO_SCALE);
 
1003
#ifdef MOZ_ENABLE_XFT
 
1004
  if (NS_IsXftEnabled()) {
 
1005
    PRInt32 dpi = GetXftDPI();
 
1006
    if (dpi != 0) {
 
1007
      // pixels/inch * twips/pixel * inches/twip == 1, except it isn't, since
 
1008
      // our idea of dpi may be different from Xft's.
 
1009
      size *= float(dpi) * aPixelsToTwips * (1.0f/1440.0f);
 
1010
    }
 
1011
  }
 
1012
#endif /* MOZ_ENABLE_XFT */
 
1013
  aFont->size = NSFloatPointsToTwips(size);
 
1014
  
 
1015
  pango_font_description_free(desc);
 
1016
 
 
1017
  return NS_OK;
 
1018
}
 
1019
#endif /* MOZ_WIDGET_GTK2 */
 
1020
 
 
1021
#ifdef MOZ_WIDGET_GTK
 
1022
/* static */
 
1023
PRInt32
 
1024
GetOSDPI(void)
 
1025
{
 
1026
 
 
1027
#ifdef MOZ_ENABLE_XFT
 
1028
  // try to get it from xft
 
1029
  if (NS_IsXftEnabled()) {
 
1030
    PRInt32 xftdpi = GetXftDPI();
 
1031
    if (xftdpi)
 
1032
      return xftdpi;
 
1033
  }
 
1034
#endif /* MOZ_ENABLE_XFT */
 
1035
 
 
1036
  // Set OSVal to what the operating system thinks the logical resolution is.
 
1037
  float screenWidthIn = float(::gdk_screen_width_mm()) / 25.4f;
 
1038
  return NSToCoordRound(float(::gdk_screen_width()) / screenWidthIn);
 
1039
}
 
1040
#endif /* MOZ_WIDGET_GTK */
 
1041
 
 
1042
#ifdef MOZ_WIDGET_GTK2
 
1043
/* static */
 
1044
PRInt32
 
1045
GetOSDPI(void)
 
1046
{
 
1047
  GtkSettings *settings = gtk_settings_get_default();
 
1048
 
 
1049
  // first try to get the gtk2 dpi
 
1050
  gint dpi = 0;
 
1051
 
 
1052
  // See if there's a gtk-xft-dpi object on the settings object - note
 
1053
  // that we don't have to free the spec since it isn't addrefed
 
1054
  // before being returned.  It's just part of an internal object.
 
1055
  // The gtk-xft-dpi setting is included in rh8 and might be included
 
1056
  // in later versions of gtk, so we conditionally check for it.
 
1057
  GParamSpec *spec;
 
1058
  spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(settings)),
 
1059
                                      "gtk-xft-dpi");
 
1060
  if (spec) {
 
1061
    g_object_get(G_OBJECT(settings),
 
1062
                 "gtk-xft-dpi", &dpi,
 
1063
                 NULL);
 
1064
  }
 
1065
 
 
1066
  if (dpi > 0)
 
1067
    return NSToCoordRound(dpi / 1024.0);
 
1068
 
 
1069
#ifdef MOZ_ENABLE_XFT
 
1070
  // try to get it from xft
 
1071
  PRInt32 xftdpi = GetXftDPI();
 
1072
 
 
1073
  if (xftdpi)
 
1074
    return xftdpi;
 
1075
#endif /* MOZ_ENABLE_XFT */
 
1076
  
 
1077
  // fall back to the physical resolution
 
1078
  float screenWidthIn = float(::gdk_screen_width_mm()) / 25.4f;
 
1079
  return NSToCoordRound(float(::gdk_screen_width()) / screenWidthIn);
 
1080
}
 
1081
#endif /* MOZ_WIDGET_GTK2 */
 
1082
 
 
1083
#ifdef MOZ_ENABLE_XFT
 
1084
/* static */
 
1085
PRInt32
 
1086
GetXftDPI(void)
 
1087
{
 
1088
  char *val = XGetDefault(GDK_DISPLAY(), "Xft", "dpi");
 
1089
  if (val) {
 
1090
    char *e;
 
1091
    double d = strtod(val, &e);
 
1092
 
 
1093
    if (e != val)
 
1094
      return NSToCoordRound(d);
 
1095
  }
 
1096
 
 
1097
  return 0;
 
1098
}
 
1099
#endif /* MOZ_ENABLE_XFT */
 
1100
 
 
1101
#if defined(MOZ_WIDGET_GTK2) && defined(MOZ_ENABLE_COREXFONTS)
 
1102
// xlfd_from_pango_font_description copied from vte, which was
 
1103
// written by nalin@redhat.com, and added some codes.
 
1104
static void
 
1105
xlfd_from_pango_font_description(GtkWidget *aWidget,
 
1106
         const PangoFontDescription *aFontDesc,
 
1107
                                 nsString& aFontName)
 
1108
{
 
1109
  char *spec;
 
1110
  PangoContext *context;
 
1111
  PangoFont *font;
 
1112
  PangoXSubfont *subfont_ids;
 
1113
  PangoFontMap *fontmap;
 
1114
  int *subfont_charsets, i, count = 0;
 
1115
  char *tmp, *subfont;
 
1116
  char *encodings[] = {
 
1117
    "ascii-0",
 
1118
    "big5-0",
 
1119
    "dos-437",
 
1120
    "dos-737",
 
1121
    "gb18030.2000-0",
 
1122
    "gb18030.2000-1",
 
1123
    "gb2312.1980-0",
 
1124
    "iso8859-1",
 
1125
    "iso8859-2",
 
1126
    "iso8859-3",
 
1127
    "iso8859-4",
 
1128
    "iso8859-5",
 
1129
    "iso8859-7",
 
1130
    "iso8859-8",
 
1131
    "iso8859-9",
 
1132
    "iso8859-10",
 
1133
    "iso8859-15",
 
1134
    "iso10646-0",
 
1135
    "iso10646-1",
 
1136
    "jisx0201.1976-0",
 
1137
    "jisx0208.1983-0",
 
1138
    "jisx0208.1990-0",
 
1139
    "jisx0208.1997-0",
 
1140
    "jisx0212.1990-0",
 
1141
    "jisx0213.2000-1",
 
1142
    "jisx0213.2000-2",
 
1143
    "koi8-r",
 
1144
    "koi8-u",
 
1145
    "koi8-ub",
 
1146
    "ksc5601.1987-0",
 
1147
    "ksc5601.1992-3",
 
1148
    "tis620-0",
 
1149
    "iso8859-13",
 
1150
    "microsoft-cp1251"
 
1151
    "misc-fontspecific",
 
1152
  };
 
1153
#if XlibSpecificationRelease >= 6
 
1154
  XOM xom;
 
1155
#endif
 
1156
  if (!aFontDesc) {
 
1157
    return;
 
1158
  }
 
1159
 
 
1160
  context = gtk_widget_get_pango_context(GTK_WIDGET(aWidget));
 
1161
 
 
1162
  pango_context_set_language (context, gtk_get_default_language ());
 
1163
  fontmap = pango_x_font_map_for_display(GDK_DISPLAY());
 
1164
 
 
1165
  if (!fontmap) {
 
1166
    return;
 
1167
  }
 
1168
 
 
1169
  font = pango_font_map_load_font(fontmap, context, aFontDesc);
 
1170
  if (!font) {
 
1171
    return;
 
1172
  }
 
1173
 
 
1174
#if XlibSpecificationRelease >= 6
 
1175
  xom = XOpenOM (GDK_DISPLAY(), NULL, NULL, NULL);
 
1176
  if (xom) {
 
1177
    XOMCharSetList cslist;
 
1178
    int n_encodings = 0;
 
1179
    cslist.charset_count = 0;
 
1180
    XGetOMValues (xom,
 
1181
      XNRequiredCharSet, &cslist,
 
1182
      NULL);
 
1183
    n_encodings = cslist.charset_count;
 
1184
    if (n_encodings) {
 
1185
      char **xom_encodings = (char**) g_malloc (sizeof(char*) * n_encodings);
 
1186
 
 
1187
      for (i = 0; i < n_encodings; i++) {
 
1188
        xom_encodings[i] = g_ascii_strdown (cslist.charset_list[i], -1);
 
1189
      }
 
1190
      count = pango_x_list_subfonts(font, xom_encodings, n_encodings,
 
1191
            &subfont_ids, &subfont_charsets);
 
1192
 
 
1193
      for(i = 0; i < n_encodings; i++) {
 
1194
        g_free (xom_encodings[i]);
 
1195
      }
 
1196
      g_free (xom_encodings);
 
1197
    }
 
1198
    XCloseOM (xom);
 
1199
  }
 
1200
#endif
 
1201
  if (count == 0) {
 
1202
    count = pango_x_list_subfonts(font, encodings, G_N_ELEMENTS(encodings),
 
1203
          &subfont_ids, &subfont_charsets);
 
1204
  }
 
1205
 
 
1206
  for (i = 0; i < count; i++) {
 
1207
    subfont = pango_x_font_subfont_xlfd(font, subfont_ids[i]);
 
1208
    AppendFontFFREName(aFontName, subfont);
 
1209
    g_free(subfont);
 
1210
    aFontName.Append(PRUnichar(','));
 
1211
  }
 
1212
 
 
1213
  spec = pango_font_description_to_string(aFontDesc);
 
1214
 
 
1215
  if (subfont_ids != NULL) {
 
1216
    g_free(subfont_ids);
 
1217
  }
 
1218
  if (subfont_charsets != NULL) {
 
1219
    g_free(subfont_charsets);
 
1220
  }
 
1221
  g_free(spec);
 
1222
}
 
1223
#endif /* MOZ_WIDGET_GTK2 && MOZ_ENABLE_COREXFONTS */