Back to index

lightning-sunbird  0.9+nobinonly
nsDeviceContextBeOS.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Pierre Phaneuf <pp@ludusdesign.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either of the GNU General Public License Version 2 or later (the "GPL"),
00027  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include <math.h>
00040 #include <Menu.h>
00041 #include "nspr.h"
00042 #include "nsIPref.h"
00043 #include "nsIServiceManager.h"
00044 #include "nsCRT.h"
00045 #include "nsReadableUtils.h"
00046 
00047 #include "nsDeviceContextBeOS.h"
00048 #include "nsFontMetricsBeOS.h"
00049 #include "nsGfxCIID.h"
00050 
00051 #ifdef USE_POSTSCRIPT
00052 #include "nsGfxPSCID.h"
00053 #include "nsIDeviceContextPS.h"
00054 #endif /* USE_POSTSCRIPT */
00055 
00056 #include <ScrollBar.h>
00057 #include <Screen.h>
00058 
00059 #include "nsIScreenManager.h"
00060 
00061 static NS_DEFINE_CID(kPrefCID, NS_PREF_CID); 
00062  
00063 nscoord nsDeviceContextBeOS::mDpi = 96; 
00064 
00065 nsDeviceContextBeOS::nsDeviceContextBeOS()
00066   : DeviceContextImpl()
00067 {
00068   mTwipsToPixels = 1.0;
00069   mPixelsToTwips = 1.0;
00070   mDepth = 0 ;
00071   mNumCells = 0;
00072   
00073   mWidthFloat = 0.0f; 
00074   mHeightFloat = 0.0f; 
00075   mWidth = -1; 
00076   mHeight = -1; 
00077 }
00078 
00079 nsDeviceContextBeOS::~nsDeviceContextBeOS()
00080 {
00081   nsresult rv; 
00082   nsCOMPtr<nsIPref> prefs = do_GetService(kPrefCID, &rv); 
00083   if (NS_SUCCEEDED(rv))
00084     prefs->UnregisterCallback("layout.css.dpi", prefChanged, (void *)this); 
00085 }
00086 
00087 NS_IMETHODIMP nsDeviceContextBeOS::Init(nsNativeWidget aNativeWidget)
00088 {
00089   // get the screen object and its width/height 
00090   // XXXRight now this will only get the primary monitor. 
00091 
00092   nsresult ignore; 
00093   mWidget = aNativeWidget;
00094   nsCOMPtr<nsIScreenManager> sm ( do_GetService("@mozilla.org/gfx/screenmanager;1", &ignore) ); 
00095   if (sm) 
00096   { 
00097     nsCOMPtr<nsIScreen> screen; 
00098     sm->GetPrimaryScreen(getter_AddRefs(screen)); 
00099     if (screen)
00100     { 
00101       PRInt32 x, y, width, height, depth; 
00102       screen->GetAvailRect ( &x, &y, &width, &height ); 
00103       screen->GetPixelDepth ( &depth ); 
00104       mWidthFloat = float(width); 
00105       mHeightFloat = float(height); 
00106       mDepth = NS_STATIC_CAST ( PRUint32, depth ); 
00107     } 
00108   } 
00109   
00110   static int initialized = 0; 
00111   if (!initialized) 
00112   {
00113     initialized = 1; 
00114 
00115     // Set prefVal the value of the preference "layout.css.dpi" 
00116     // or -1 if we can't get it. 
00117     // If it's negative, we pretend it's not set. 
00118     // If it's 0, it means force use of the operating system's logical resolution. 
00119     // If it's positive, we use it as the logical resolution 
00120     PRInt32 prefVal = -1; 
00121     nsresult res; 
00122 
00123     nsCOMPtr<nsIPref> prefs(do_GetService(kPrefCID, &res)); 
00124     if (NS_SUCCEEDED(res) && prefs)
00125     { 
00126       res = prefs->GetIntPref("layout.css.dpi", &prefVal); 
00127       if (! NS_SUCCEEDED(res))
00128       { 
00129         prefVal = -1; 
00130       } 
00131       prefs->RegisterCallback("layout.css.dpi", prefChanged, (void *)this); 
00132     } 
00133  
00134     // Set OSVal to what the operating system thinks the logical resolution is. 
00135     // BeOS lacks monitor info, so we use fixed value for now
00136     PRInt32 OSVal = 85;
00137     if (prefVal > 0)
00138     { 
00139       // If there's a valid pref value for the logical resolution, 
00140       // use it. 
00141       mDpi = prefVal; 
00142     }
00143     else if ((prefVal == 0) || (OSVal > 96))
00144     { 
00145       // Either if the pref is 0 (force use of OS value) or the OS 
00146       // value is bigger than 96, use the OS value. 
00147       mDpi = OSVal; 
00148     }
00149     else
00150     { 
00151       // if we couldn't get the pref or it's negative, and the OS 
00152       // value is under 96ppi, then use 96. 
00153       mDpi = 96; 
00154     } 
00155   } 
00156  
00157   SetDPI(mDpi); 
00158 
00159   mScrollbarHeight = PRInt16(B_H_SCROLL_BAR_HEIGHT); 
00160   mScrollbarWidth = PRInt16(B_V_SCROLL_BAR_WIDTH); 
00161 
00162   menu_info info;
00163   get_menu_info(&info);
00164   mMenuFont.SetFamilyAndStyle(info.f_family,info.f_style);
00165   mMenuFont.SetSize(info.font_size);
00166   
00167 #ifdef DEBUG 
00168   static PRBool once = PR_TRUE; 
00169   if (once)
00170   { 
00171     printf("GFX: dpi=%d t2p=%g p2t=%g depth=%d\n", mDpi, mTwipsToPixels, mPixelsToTwips,mDepth); 
00172     once = PR_FALSE; 
00173   } 
00174 #endif 
00175 
00176   DeviceContextImpl::CommonInit();
00177   
00178   return NS_OK;
00179 }
00180 
00181 NS_IMETHODIMP nsDeviceContextBeOS::CreateRenderingContext(nsIRenderingContext *&aContext) 
00182 { 
00183   nsIRenderingContext *pContext; 
00184   nsresult             rv; 
00185   nsDrawingSurfaceBeOS  *surf; 
00186   BView *w; 
00187 
00188   w = (BView*)mWidget;
00189 
00190   // to call init for this, we need to have a valid nsDrawingSurfaceBeOS created 
00191   pContext = new nsRenderingContextBeOS(); 
00192  
00193   if (nsnull != pContext) 
00194   { 
00195     NS_ADDREF(pContext); 
00196  
00197     // create the nsDrawingSurfaceBeOS 
00198     surf = new nsDrawingSurfaceBeOS(); 
00199  
00200     if (surf && w) 
00201     {
00202       // init the nsDrawingSurfaceBeOS 
00203       rv = surf->Init(w);
00204       if (NS_OK == rv)
00205         // Init the nsRenderingContextBeOS 
00206         rv = pContext->Init(this, surf);
00207     } 
00208     else
00209     {
00210       rv = NS_ERROR_OUT_OF_MEMORY;
00211     }
00212   }
00213   else
00214   {
00215     rv = NS_ERROR_OUT_OF_MEMORY;
00216   }
00217 
00218   if (NS_OK != rv)
00219     NS_IF_RELEASE(pContext); 
00220 
00221   aContext = pContext; 
00222  
00223   return rv; 
00224 } 
00225  
00226 NS_IMETHODIMP nsDeviceContextBeOS::SupportsNativeWidgets(PRBool &aSupportsWidgets)
00227 {
00228   //XXX it is very critical that this not lie!! MMP
00229   // read the comments in the mac code for this
00230   aSupportsWidgets = PR_TRUE;
00231   return NS_OK;
00232 }
00233 
00234 NS_IMETHODIMP nsDeviceContextBeOS::GetScrollBarDimensions(float &aWidth, float &aHeight) const
00235 {
00236   float scale;
00237   GetCanonicalPixelScale(scale);
00238   aWidth = mScrollbarWidth * mPixelsToTwips * scale;
00239   aHeight = mScrollbarHeight * mPixelsToTwips * scale;
00240 
00241   return NS_OK;
00242 }
00243 
00244 NS_IMETHODIMP nsDeviceContextBeOS::GetSystemFont(nsSystemFontID aID, nsFont *aFont) const
00245 {
00246   nsresult status = NS_OK;
00247 
00248   switch (aID) 
00249   {
00250     case eSystemFont_PullDownMenu: 
00251     case eSystemFont_Menu:
00252       status = GetSystemFontInfo(&mMenuFont, aID, aFont); 
00253       break;
00254     case eSystemFont_Caption:             // css2 bold  
00255       status = GetSystemFontInfo(be_bold_font, aID, aFont); 
00256       break;
00257     case eSystemFont_List:   
00258     case eSystemFont_Field:
00259     case eSystemFont_Icon : 
00260     case eSystemFont_MessageBox : 
00261     case eSystemFont_SmallCaption : 
00262     case eSystemFont_StatusBar : 
00263     case eSystemFont_Window:              // css3 
00264     case eSystemFont_Document: 
00265     case eSystemFont_Workspace: 
00266     case eSystemFont_Desktop: 
00267     case eSystemFont_Info: 
00268     case eSystemFont_Dialog: 
00269     case eSystemFont_Button: 
00270     case eSystemFont_Tooltips:            // moz 
00271     case eSystemFont_Widget: 
00272     default:
00273       status = GetSystemFontInfo(be_plain_font, aID, aFont);
00274   }
00275 
00276   return status;
00277 }
00278 
00279 NS_IMETHODIMP nsDeviceContextBeOS::CheckFontExistence(const nsString& aFontName)
00280 {
00281   return nsFontMetricsBeOS::FamilyExists(aFontName); 
00282 } 
00283 
00284 /* 
00285 NS_IMETHODIMP nsDeviceContextBeOS::CheckFontExistence(const nsString& aFontName) 
00286 {
00287   PRBool  isthere = PR_FALSE;
00288 
00289   char* cStr = ToNewCString(aFontName);
00290 
00291        int32 numFamilies = count_font_families();
00292        for(int32 i = 0; i < numFamilies; i++)
00293        {
00294               font_family family; 
00295               uint32 flags; 
00296               if(get_font_family(i, &family, &flags) == B_OK)
00297               {
00298                      if(strcmp(family, cStr) == 0)
00299                      {
00300                             isthere = PR_TRUE;
00301                             break;
00302                      }
00303               } 
00304        }
00305 
00306        //printf("%s there? %s\n", cStr, isthere?"Yes":"No" );
00307        
00308   delete[] cStr;
00309 
00310   if (PR_TRUE == isthere)
00311     return NS_OK;
00312   else
00313     return NS_ERROR_FAILURE;
00314 }
00315 */
00316 
00317 NS_IMETHODIMP nsDeviceContextBeOS::GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight)
00318 {
00319   if (mWidth == -1) 
00320     mWidth = NSToIntRound(mWidthFloat * mDevUnitsToAppUnits);
00321 
00322   if (mHeight == -1) 
00323     mHeight = NSToIntRound(mHeightFloat * mDevUnitsToAppUnits); 
00324  
00325   aWidth = mWidth; 
00326   aHeight = mHeight; 
00327  
00328   return NS_OK; 
00329 }
00330 
00331 NS_IMETHODIMP nsDeviceContextBeOS::GetRect(nsRect &aRect)
00332 {
00333   PRInt32 width, height; 
00334   nsresult rv; 
00335   rv = GetDeviceSurfaceDimensions(width, height);
00336   aRect.x = 0;
00337   aRect.y = 0;
00338   aRect.width = width; 
00339   aRect.height = height; 
00340   return rv; 
00341 } 
00342  
00343 NS_IMETHODIMP nsDeviceContextBeOS::GetClientRect(nsRect &aRect) 
00344 { 
00345 //XXX do we know if the client rect should ever differ from the screen rect? 
00346   return GetRect(aRect);
00347 }
00348 
00349 NS_IMETHODIMP nsDeviceContextBeOS::GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
00350                                                       nsIDeviceContext *&aContext)
00351 {
00352 #ifdef USE_POSTSCRIPT
00353   static NS_DEFINE_CID(kCDeviceContextPS, NS_DEVICECONTEXTPS_CID);
00354   
00355   // Create a Postscript device context 
00356   nsresult rv;
00357   nsIDeviceContextPS *dcps;
00358   
00359   rv = CallCreateInstance(kCDeviceContextPS, &dcps);
00360 
00361   NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create PS Device context");
00362   
00363   dcps->SetSpec(aDevice);
00364   dcps->InitDeviceContextPS((nsIDeviceContext*)aContext, (nsIDeviceContext*)this);
00365 
00366   rv = dcps->QueryInterface(NS_GET_IID(nsIDeviceContext), (void **)&aContext);
00367 
00368   NS_RELEASE(dcps);
00369   
00370   return rv;
00371 #else
00372   return NS_ERROR_NOT_IMPLEMENTED;
00373 #endif /* USE_POSTSCRIPT */
00374 }
00375 
00376 NS_IMETHODIMP nsDeviceContextBeOS::BeginDocument(PRUnichar * aTitle, PRUnichar* aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage)
00377 {
00378   return NS_OK;
00379 }
00380 
00381 NS_IMETHODIMP nsDeviceContextBeOS::EndDocument(void)
00382 {
00383   return NS_OK;
00384 }
00385 
00386 NS_IMETHODIMP nsDeviceContextBeOS::BeginPage(void)
00387 {
00388   return NS_OK;
00389 }
00390 
00391 NS_IMETHODIMP nsDeviceContextBeOS::EndPage(void)
00392 {
00393   return NS_OK;
00394 } 
00395  
00396 NS_IMETHODIMP nsDeviceContextBeOS::GetDepth(PRUint32& aDepth) 
00397 { 
00398   aDepth = mDepth; 
00399   return NS_OK; 
00400 } 
00401  
00402 nsresult 
00403 nsDeviceContextBeOS::SetDPI(PRInt32 aDpi) 
00404 { 
00405   mDpi = aDpi; 
00406   
00407   int pt2t = 72; 
00408 
00409   mPixelsToTwips = float(NSToIntRound(float(NSIntPointsToTwips(pt2t)) / float(aDpi))); 
00410   mTwipsToPixels = 1.0f / mPixelsToTwips; 
00411  
00412   // XXX need to reflow all documents 
00413   return NS_OK; 
00414 } 
00415  
00416 int nsDeviceContextBeOS::prefChanged(const char *aPref, void *aClosure) 
00417 { 
00418   nsDeviceContextBeOS *context = (nsDeviceContextBeOS*)aClosure; 
00419   nsresult rv; 
00420   
00421   if (nsCRT::strcmp(aPref, "layout.css.dpi")==0)
00422   {
00423     PRInt32 dpi; 
00424     nsCOMPtr<nsIPref> prefs(do_GetService(kPrefCID, &rv)); 
00425     rv = prefs->GetIntPref(aPref, &dpi); 
00426     if (NS_SUCCEEDED(rv)) 
00427       context->SetDPI(dpi); 
00428   } 
00429   
00430   return 0; 
00431 } 
00432  
00433 nsresult 
00434 nsDeviceContextBeOS::GetSystemFontInfo(const BFont *theFont, nsSystemFontID anID, nsFont* aFont) const 
00435 { 
00436   nsresult status = NS_OK; 
00437  
00438   aFont->style       = NS_FONT_STYLE_NORMAL; 
00439   aFont->weight      = NS_FONT_WEIGHT_NORMAL; 
00440   aFont->decorations = NS_FONT_DECORATION_NONE; 
00441   
00442   // do we have the default_font defined by BeOS, if not then 
00443   // we error out. 
00444   if (!theFont)
00445   {
00446     switch (anID) 
00447        {
00448       case eSystemFont_Menu:
00449         status = GetSystemFontInfo(&mMenuFont, anID, aFont); 
00450         break;
00451       case eSystemFont_List:
00452       case eSystemFont_Field:
00453         theFont = be_plain_font;
00454         break;
00455       case eSystemFont_Caption:
00456         theFont = be_bold_font;
00457         break;
00458       default:
00459         theFont = be_plain_font; // BeOS default font 
00460     }
00461   }
00462   
00463   if (!theFont) 
00464   { 
00465     status = NS_ERROR_FAILURE; 
00466   } 
00467   else 
00468   { 
00469     font_family family; 
00470     font_style style; 
00471     font_height height;
00472     uint16 face; 
00473  
00474     theFont->GetFamilyAndStyle(&family, &style);
00475 
00476     face = theFont->Face();
00477     aFont->name.Assign(NS_ConvertUTF8toUCS2(family));
00478     aFont->size = NSIntPixelsToTwips(uint32(theFont->Size()), mPixelsToTwips); 
00479 
00480     if(face & B_ITALIC_FACE)
00481       aFont->style = NS_FONT_STYLE_ITALIC;
00482     
00483     if(face & B_BOLD_FACE)
00484       aFont->weight = NS_FONT_WEIGHT_BOLD;
00485 
00486     if(face & B_UNDERSCORE_FACE)
00487       aFont->decorations |= NS_FONT_DECORATION_UNDERLINE;
00488 
00489     if(face & B_STRIKEOUT_FACE)
00490       aFont->decorations |= NS_FONT_DECORATION_LINE_THROUGH;
00491 
00492     aFont->systemFont = PR_TRUE;
00493 
00494     status = NS_OK; 
00495   } 
00496   return (status); 
00497 }