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
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/
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
16
* The Original Code is mozilla.org code.
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.
24
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
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.
39
* ***** END LICENSE BLOCK ***** */
45
#include "nsIServiceManager.h"
48
#include "nsDeviceContextGTK.h"
49
#include "nsGfxCIID.h"
52
#include "nsGfxPSCID.h"
53
#include "nsIDeviceContextPS.h"
54
#endif /* USE_POSTSCRIPT */
56
#include "nsGfxXPrintCID.h"
57
#include "nsIDeviceContextXPrint.h"
58
#endif /* USE_XPRINT */
60
#include "nsFontMetricsUtils.h"
66
#include "gdksuperwin.h"
67
#endif /* MOZ_WIDGET_GTK */
69
#ifdef MOZ_WIDGET_GTK2
70
#include <pango/pango.h>
71
#include <pango/pangox.h>
72
#include <pango/pango-fontmap.h>
76
#include "nsFontMetricsUtils.h"
78
#include <X11/Xft/Xft.h>
80
static PRInt32 GetXftDPI(void);
83
#include <X11/Xatom.h>
85
#include "nsDeviceContextSpecG.h"
87
static PRInt32 GetOSDPI(void);
89
static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
91
#define GDK_DEFAULT_FONT1 "-*-helvetica-medium-r-*--*-120-*-*-*-*-iso8859-1"
92
#define GDK_DEFAULT_FONT2 "-*-fixed-medium-r-*-*-*-120-*-*-*-*-*-*"
95
// this is specific to gtk 1.2
96
extern GdkFont *default_font;
97
#endif /* MOZ_WIDGET_GTK */
100
* A singleton instance of nsSystemFontsGTK is created by the first
101
* device context and destroyed by the module destructor.
103
class nsSystemFontsGTK {
106
nsSystemFontsGTK(float aPixelsToTwips);
108
const nsFont& GetDefaultFont() { return mDefaultFont; }
109
const nsFont& GetMenuFont() { return mMenuFont; }
110
const nsFont& GetFieldFont() { return mFieldFont; }
111
const nsFont& GetButtonFont() { return mButtonFont; }
114
nsresult GetSystemFontInfo(GtkWidget *aWidget, nsFont* aFont,
115
float aPixelsToTwips) const;
118
* The following system font constants exist:
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,
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,
131
* eSystemFont_Tooltips, eSystemFont_Widget
140
nscoord nsDeviceContextGTK::mDpi = 96;
141
static nsSystemFontsGTK *gSystemFonts = nsnull;
143
nsDeviceContextGTK::nsDeviceContextGTK()
144
: DeviceContextImpl()
146
mTwipsToPixels = 1.0;
147
mPixelsToTwips = 1.0;
155
mDeviceWindow = nsnull;
158
nsDeviceContextGTK::~nsDeviceContextGTK()
161
nsCOMPtr<nsIPref> prefs = do_GetService(kPrefCID, &rv);
162
if (NS_SUCCEEDED(rv)) {
163
prefs->UnregisterCallback("browser.display.screen_resolution",
164
prefChanged, (void *)this);
168
/* static */ void nsDeviceContextGTK::Shutdown()
172
gSystemFonts = nsnull;
176
NS_IMETHODIMP nsDeviceContextGTK::Init(nsNativeWidget aNativeWidget)
181
// get the screen object and its width/height
182
// XXXRight now this will only get the primary monitor.
185
mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1");
186
if (!mScreenManager) {
187
return NS_ERROR_FAILURE;
190
#ifdef MOZ_WIDGET_GTK
194
if (GDK_IS_SUPERWIN(aNativeWidget)) {
195
mDeviceWindow = GDK_SUPERWIN(aNativeWidget)->shell_window;
198
else if (GTK_IS_WIDGET(aNativeWidget)) {
199
mDeviceWindow = GTK_WIDGET(aNativeWidget)->window;
201
// must be a bin_window
203
mDeviceWindow = NS_STATIC_CAST(GdkWindow *, aNativeWidget);
207
#endif /* MOZ_WIDGET_GTK */
209
#ifdef MOZ_WIDGET_GTK2
212
// can only be a gdk window
213
if (GDK_IS_WINDOW(aNativeWidget))
214
mDeviceWindow = GDK_WINDOW(aNativeWidget);
216
NS_WARNING("unsupported native widget type!");
221
nsCOMPtr<nsIScreen> screen;
222
mScreenManager->GetPrimaryScreen ( getter_AddRefs(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 );
232
static int initialized = 0;
233
PRInt32 prefVal = -1;
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
243
// If it's positive, we use it as the logical resolution
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)) {
252
prefs->RegisterCallback("browser.display.screen_resolution", prefChanged,
258
SetDPI(mDpi); // to setup p2t and t2p
261
sb = gtk_vscrollbar_new(NULL);
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);
273
sb = gtk_hscrollbar_new(NULL);
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);
286
static PRBool once = PR_TRUE;
288
printf("GFX: dpi=%d t2p=%g p2t=%g depth=%d\n", mDpi, mTwipsToPixels, mPixelsToTwips,mDepth);
293
DeviceContextImpl::CommonInit();
298
NS_IMETHODIMP nsDeviceContextGTK::CreateRenderingContext(nsIRenderingContext *&aContext)
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);
307
nsIRenderingContext *pContext;
309
nsDrawingSurfaceGTK *surf;
312
w = (GtkWidget*)mWidget;
314
// to call init for this, we need to have a valid nsDrawingSurfaceGTK created
315
pContext = new nsRenderingContextGTK();
317
if (nsnull != pContext)
321
// create the nsDrawingSurfaceGTK
322
surf = new nsDrawingSurfaceGTK();
326
GdkDrawable *gwin = nsnull;
327
GdkDrawable *win = nsnull;
329
if (GTK_IS_LAYOUT(w))
330
gwin = (GdkDrawable*)GTK_LAYOUT(w)->bin_window;
332
gwin = (GdkDrawable*)(w)->window;
334
// window might not be realized... ugh
336
gdk_window_ref(gwin);
338
win = gdk_pixmap_new(nsnull,
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());
347
GdkGC *gc = gdk_gc_new(win);
349
// init the nsDrawingSurfaceGTK
350
rv = surf->Init(win,gc);
353
// Init the nsRenderingContextGTK
354
rv = pContext->Init(this, surf);
357
rv = NS_ERROR_OUT_OF_MEMORY;
360
rv = NS_ERROR_OUT_OF_MEMORY;
364
NS_IF_RELEASE(pContext);
372
NS_IMETHODIMP nsDeviceContextGTK::CreateRenderingContextInstance(nsIRenderingContext *&aContext)
374
nsCOMPtr<nsIRenderingContext> renderingContext = new nsRenderingContextGTK();
375
if (!renderingContext)
376
return NS_ERROR_OUT_OF_MEMORY;
378
aContext = renderingContext;
384
NS_IMETHODIMP nsDeviceContextGTK::SupportsNativeWidgets(PRBool &aSupportsWidgets)
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;
393
NS_IMETHODIMP nsDeviceContextGTK::GetScrollBarDimensions(float &aWidth, float &aHeight) const
396
GetCanonicalPixelScale(scale);
397
aWidth = mScrollbarWidth * mPixelsToTwips * scale;
398
aHeight = mScrollbarHeight * mPixelsToTwips * scale;
403
NS_IMETHODIMP nsDeviceContextGTK::GetSystemFont(nsSystemFontID aID, nsFont *aFont) const
405
nsresult status = NS_OK;
408
gSystemFonts = new nsSystemFontsGTK(mPixelsToTwips);
412
case eSystemFont_Menu: // css2
413
case eSystemFont_PullDownMenu: // css3
414
*aFont = gSystemFonts->GetMenuFont();
417
case eSystemFont_Field: // css3
418
case eSystemFont_List: // css3
419
*aFont = gSystemFonts->GetFieldFont();
422
case eSystemFont_Button: // css3
423
*aFont = gSystemFonts->GetButtonFont();
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();
446
NS_IMETHODIMP nsDeviceContextGTK::CheckFontExistence(const nsString& aFontName)
448
return NS_FontMetricsFamilyExists(this, aFontName);
451
NS_IMETHODIMP nsDeviceContextGTK::GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight)
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);
461
mWidth = NSToIntRound(mWidthFloat * mDevUnitsToAppUnits);
464
mHeight = NSToIntRound(mHeightFloat * mDevUnitsToAppUnits);
474
NS_IMETHODIMP nsDeviceContextGTK::GetRect(nsRect &aRect)
476
// if we have an initialized widget for this device context, use it
477
// to try and get real screen coordinates.
479
gint x, y, width, height, depth;
480
x = y = width = height = 0;
482
gdk_window_get_geometry(mDeviceWindow, &x, &y, &width, &height,
484
gdk_window_get_origin(mDeviceWindow, &x, &y);
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);
495
PRInt32 width, height;
496
GetDeviceSurfaceDimensions(width, height);
500
aRect.height = height;
506
NS_IMETHODIMP nsDeviceContextGTK::GetClientRect(nsRect &aRect)
508
// if we have an initialized widget for this device context, use it
509
// to try and get real screen coordinates.
511
gint x, y, width, height, depth;
512
x = y = width = height = 0;
514
gdk_window_get_geometry(mDeviceWindow, &x, &y, &width, &height,
516
gdk_window_get_origin(mDeviceWindow, &x, &y);
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);
527
PRInt32 width, height;
528
GetDeviceSurfaceDimensions(width, height);
532
aRect.height = height;
538
NS_IMETHODIMP nsDeviceContextGTK::GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
539
nsIDeviceContext *&aContext)
543
nsDeviceContextSpecGTK *spec = NS_STATIC_CAST(nsDeviceContextSpecGTK *, aDevice);
545
rv = spec->GetPrintMethod(method);
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.");
555
return NS_ERROR_GFX_COULD_NOT_LOAD_PRINT_MODULE;
557
rv = dcxp->SetSpec(aDevice);
561
rv = dcxp->InitDeviceContextXP((nsIDeviceContext*)aContext,
562
(nsIDeviceContext*)this);
566
rv = dcxp->QueryInterface(NS_GET_IID(nsIDeviceContext),
571
#endif /* USE_XPRINT */
572
#ifdef USE_POSTSCRIPT
573
if (method == pmPostScript) { // PostScript
575
static NS_DEFINE_CID(kCDeviceContextPS, NS_DEVICECONTEXTPS_CID);
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.");
581
return NS_ERROR_GFX_COULD_NOT_LOAD_PRINT_MODULE;
583
rv = dcps->SetSpec(aDevice);
587
rv = dcps->InitDeviceContextPS((nsIDeviceContext*)aContext,
588
(nsIDeviceContext*)this);
592
rv = dcps->QueryInterface(NS_GET_IID(nsIDeviceContext),
596
#endif /* USE_POSTSCRIPT */
598
NS_WARNING("no print module created.");
599
return NS_ERROR_UNEXPECTED;
602
NS_IMETHODIMP nsDeviceContextGTK::BeginDocument(PRUnichar * aTitle, PRUnichar* aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage)
607
NS_IMETHODIMP nsDeviceContextGTK::EndDocument(void)
612
NS_IMETHODIMP nsDeviceContextGTK::AbortDocument(void)
617
NS_IMETHODIMP nsDeviceContextGTK::BeginPage(void)
622
NS_IMETHODIMP nsDeviceContextGTK::EndPage(void)
627
NS_IMETHODIMP nsDeviceContextGTK::GetDepth(PRUint32& aDepth)
634
nsDeviceContextGTK::SetDPI(PRInt32 aPrefDPI)
636
PRInt32 OSVal = GetOSDPI();
639
// If there's a valid pref value for the logical resolution,
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.
647
// if we couldn't get the pref or it's negative, and the OS
648
// value is under 96ppi, then use 96.
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;
658
// XXX need to reflow all documents
662
int nsDeviceContextGTK::prefChanged(const char *aPref, void *aClosure)
664
nsDeviceContextGTK *context = (nsDeviceContextGTK*)aClosure;
667
if (nsCRT::strcmp(aPref, "browser.display.screen_resolution")==0) {
669
nsCOMPtr<nsIPref> prefs(do_GetService(kPrefCID, &rv));
670
rv = prefs->GetIntPref(aPref, &dpi);
671
if (NS_SUCCEEDED(rv))
672
context->SetDPI(dpi);
674
// If this pref changes, we have to clear our cache of stored system
678
gSystemFonts = nsnull;
685
#define DEFAULT_TWIP_FONT_SIZE 240
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)
702
* Much of the widget creation code here is similar to the code in
703
* nsLookAndFeel::InitColors().
707
GtkWidget *label = gtk_label_new("M");
708
GtkWidget *parent = gtk_fixed_new();
709
GtkWidget *window = gtk_window_new(GTK_WINDOW_POPUP);
711
gtk_container_add(GTK_CONTAINER(parent), label);
712
gtk_container_add(GTK_CONTAINER(window), parent);
714
gtk_widget_ensure_style(label);
716
GetSystemFontInfo(label, &mDefaultFont, aPixelsToTwips);
718
gtk_widget_destroy(window); // no unref, windows are different
721
GtkWidget *entry = gtk_entry_new();
722
parent = gtk_fixed_new();
723
window = gtk_window_new(GTK_WINDOW_POPUP);
725
gtk_container_add(GTK_CONTAINER(parent), entry);
726
gtk_container_add(GTK_CONTAINER(window), parent);
727
gtk_widget_ensure_style(entry);
729
GetSystemFontInfo(entry, &mFieldFont, aPixelsToTwips);
731
gtk_widget_destroy(window); // no unref, windows are different
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));
740
gtk_container_add(GTK_CONTAINER(menuitem), accel_label);
741
gtk_menu_append(GTK_MENU(menu), menuitem);
743
gtk_widget_ensure_style(accel_label);
745
GetSystemFontInfo(accel_label, &mMenuFont, aPixelsToTwips);
747
gtk_widget_unref(menu);
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);
755
gtk_container_add(GTK_CONTAINER(button), label);
756
gtk_container_add(GTK_CONTAINER(parent), button);
757
gtk_container_add(GTK_CONTAINER(window), parent);
759
gtk_widget_ensure_style(label);
761
GetSystemFontInfo(label, &mButtonFont, aPixelsToTwips);
763
gtk_widget_destroy(window); // no unref, windows are different
767
#if 0 // debugging code to list the font properties
769
ListFontProps(XFontStruct *aFont, Display *aDisplay)
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)
779
printf("%s : %ld (%s)\n", atomName, prop->card32, cardName?cardName:"");
788
#if defined(MOZ_ENABLE_COREXFONTS) || defined(MOZ_WIDGET_GTK)
790
#define LOCATE_MINUS(pos, str) { \
791
pos = str.FindChar('-'); \
795
#define NEXT_MINUS(pos, str) { \
796
pos = str.FindChar('-', pos+1); \
802
AppendFontFFREName(nsString& aString, const char* aXLFDName)
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
807
// adobe-courier-iso8859-15
808
nsCAutoString nameStr(aXLFDName);
810
// remove first '-' and everything before it.
811
LOCATE_MINUS(pos1, nameStr);
812
nameStr.Cut(0, pos1+1);
814
// skip foundry and family name
815
LOCATE_MINUS(pos1, nameStr);
816
NEXT_MINUS(pos1, nameStr);
819
// find '-' just before charset registry
820
for (PRInt32 i=0; i < 10; i++) {
821
NEXT_MINUS(pos2, nameStr);
824
// remove everything in between
825
nameStr.Cut(pos1, pos2-pos1);
827
aString.AppendWithConversion(nameStr.get());
829
#endif /* MOZ_ENABLE_COREXFONTS || MOZ_WIDGET_GTK*/
831
#ifdef MOZ_WIDGET_GTK
833
AppendFontName(XFontStruct* aFontStruct, nsString& aString, Display *aDisplay)
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);
844
aString.Append(PRUnichar(','));
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)) &&
850
char *fontName = ::XGetAtomName(aDisplay, pr);
851
aString.AppendWithConversion(fontName);
857
GetFontWeight(XFontStruct* aFontStruct, Display *aDisplay)
859
PRUint16 weight = NS_FONT_WEIGHT_NORMAL;
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);
875
if (::XGetFontProperty(aFontStruct, XA_WEIGHT, &pr) && pr > 10 )
876
weight = NS_FONT_WEIGHT_BOLD;
882
GetFontSize(XFontStruct *aFontStruct, float aPixelsToTwips)
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);
892
nsSystemFontsGTK::GetSystemFontInfo(GtkWidget *aWidget, nsFont* aFont,
893
float aPixelsToTwips) const
895
GtkStyle *style = gtk_widget_get_style(aWidget);
897
GdkFont *theFont = style->font;
899
aFont->style = NS_FONT_STYLE_NORMAL;
900
aFont->weight = NS_FONT_WEIGHT_NORMAL;
901
aFont->decorations = NS_FONT_DECORATION_NONE;
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.
907
theFont = default_font; // GTK default font
910
theFont = ::gdk_font_load( GDK_DEFAULT_FONT1 );
913
theFont = ::gdk_font_load( GDK_DEFAULT_FONT2 );
916
return NS_ERROR_FAILURE;
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));
923
aFont->name.Truncate();
924
AppendFontName(fontStruct, aFont->name, fontDisplay);
925
aFont->weight = GetFontWeight(fontStruct, fontDisplay);
926
aFont->size = GetFontSize(fontStruct, aPixelsToTwips);
928
NS_ASSERTION(theFont->type == GDK_FONT_FONTSET,
929
"theFont->type can only have two values");
931
XFontSet fontSet = NS_REINTERPRET_CAST(XFontSet, GDK_FONT_XFONT(theFont));
932
XFontStruct **fontStructs;
934
int numFonts = ::XFontsOfFontSet(fontSet, &fontStructs, &fontNames);
936
return NS_ERROR_FAILURE;
938
// Use the weight and size from the first font, but append all
940
aFont->weight = GetFontWeight(*fontStructs, fontDisplay);
941
aFont->size = GetFontSize(*fontStructs, aPixelsToTwips);
942
nsString& fontName = aFont->name;
945
// we need to append FFRE name instead of family name in this case
946
AppendFontFFREName(fontName, *fontNames);
951
fontName.Append(PRUnichar(','));
956
#endif /* MOZ_WIDGET_GTK */
958
#ifdef MOZ_WIDGET_GTK2
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 */
967
nsSystemFontsGTK::GetSystemFontInfo(GtkWidget *aWidget, nsFont* aFont,
968
float aPixelsToTwips) const
970
GtkSettings *settings = gtk_widget_get_settings(aWidget);
972
aFont->style = NS_FONT_STYLE_NORMAL;
973
aFont->decorations = NS_FONT_DECORATION_NONE;
976
g_object_get(settings, "gtk-font-name", &fontname, NULL);
978
PangoFontDescription *desc;
979
desc = pango_font_description_from_string(fontname);
981
aFont->systemFont = PR_TRUE;
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('"'));
992
#endif /* MOZ_ENABLE_XFT */
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);
999
#endif /* MOZ_ENABLE_COREXFONTS */
1000
aFont->weight = pango_font_description_get_weight(desc);
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();
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);
1012
#endif /* MOZ_ENABLE_XFT */
1013
aFont->size = NSFloatPointsToTwips(size);
1015
pango_font_description_free(desc);
1019
#endif /* MOZ_WIDGET_GTK2 */
1021
#ifdef MOZ_WIDGET_GTK
1027
#ifdef MOZ_ENABLE_XFT
1028
// try to get it from xft
1029
if (NS_IsXftEnabled()) {
1030
PRInt32 xftdpi = GetXftDPI();
1034
#endif /* MOZ_ENABLE_XFT */
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);
1040
#endif /* MOZ_WIDGET_GTK */
1042
#ifdef MOZ_WIDGET_GTK2
1047
GtkSettings *settings = gtk_settings_get_default();
1049
// first try to get the gtk2 dpi
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.
1058
spec = g_object_class_find_property(G_OBJECT_GET_CLASS(G_OBJECT(settings)),
1061
g_object_get(G_OBJECT(settings),
1062
"gtk-xft-dpi", &dpi,
1067
return NSToCoordRound(dpi / 1024.0);
1069
#ifdef MOZ_ENABLE_XFT
1070
// try to get it from xft
1071
PRInt32 xftdpi = GetXftDPI();
1075
#endif /* MOZ_ENABLE_XFT */
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);
1081
#endif /* MOZ_WIDGET_GTK2 */
1083
#ifdef MOZ_ENABLE_XFT
1088
char *val = XGetDefault(GDK_DISPLAY(), "Xft", "dpi");
1091
double d = strtod(val, &e);
1094
return NSToCoordRound(d);
1099
#endif /* MOZ_ENABLE_XFT */
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.
1105
xlfd_from_pango_font_description(GtkWidget *aWidget,
1106
const PangoFontDescription *aFontDesc,
1107
nsString& aFontName)
1110
PangoContext *context;
1112
PangoXSubfont *subfont_ids;
1113
PangoFontMap *fontmap;
1114
int *subfont_charsets, i, count = 0;
1115
char *tmp, *subfont;
1116
char *encodings[] = {
1151
"misc-fontspecific",
1153
#if XlibSpecificationRelease >= 6
1160
context = gtk_widget_get_pango_context(GTK_WIDGET(aWidget));
1162
pango_context_set_language (context, gtk_get_default_language ());
1163
fontmap = pango_x_font_map_for_display(GDK_DISPLAY());
1169
font = pango_font_map_load_font(fontmap, context, aFontDesc);
1174
#if XlibSpecificationRelease >= 6
1175
xom = XOpenOM (GDK_DISPLAY(), NULL, NULL, NULL);
1177
XOMCharSetList cslist;
1178
int n_encodings = 0;
1179
cslist.charset_count = 0;
1181
XNRequiredCharSet, &cslist,
1183
n_encodings = cslist.charset_count;
1185
char **xom_encodings = (char**) g_malloc (sizeof(char*) * n_encodings);
1187
for (i = 0; i < n_encodings; i++) {
1188
xom_encodings[i] = g_ascii_strdown (cslist.charset_list[i], -1);
1190
count = pango_x_list_subfonts(font, xom_encodings, n_encodings,
1191
&subfont_ids, &subfont_charsets);
1193
for(i = 0; i < n_encodings; i++) {
1194
g_free (xom_encodings[i]);
1196
g_free (xom_encodings);
1202
count = pango_x_list_subfonts(font, encodings, G_N_ELEMENTS(encodings),
1203
&subfont_ids, &subfont_charsets);
1206
for (i = 0; i < count; i++) {
1207
subfont = pango_x_font_subfont_xlfd(font, subfont_ids[i]);
1208
AppendFontFFREName(aFontName, subfont);
1210
aFontName.Append(PRUnichar(','));
1213
spec = pango_font_description_to_string(aFontDesc);
1215
if (subfont_ids != NULL) {
1216
g_free(subfont_ids);
1218
if (subfont_charsets != NULL) {
1219
g_free(subfont_charsets);
1223
#endif /* MOZ_WIDGET_GTK2 && MOZ_ENABLE_COREXFONTS */