Back to index

lightning-sunbird  0.9+nobinonly
nsFontMetricsQt.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla.org code.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1998
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Lars Knoll <knoll@kde.org>
00023  *   Zack Rusin <zack@kde.org>
00024  *   John C. Griggs <jcgriggs@sympatico.ca>
00025  *   Jean Claude Batista <jcb@macadamian.com>
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsQuickSort.h"
00042 #include "nsFontMetricsQt.h"
00043 #include "nsFont.h"
00044 #include "nsString.h"
00045 #include "nsXPIDLString.h"
00046 #include "nsReadableUtils.h"
00047 #include "nsIServiceManager.h"
00048 #include "nsISaveAsCharset.h"
00049 #include "nsIPrefBranch.h"
00050 #include "nsIPrefService.h"
00051 #include "nsCOMPtr.h"
00052 #include "nspr.h"
00053 #include "nsHashtable.h"
00054 #include "nsDrawingSurfaceQt.h"
00055 #include "nsRenderingContextQt.h"
00056 #include "nsILanguageAtomService.h"
00057 #include "nsDrawingSurfaceQt.h"
00058 #include "nsRenderingContextQt.h"
00059 
00060 #include <qapplication.h>
00061 #include <qfont.h>
00062 #include <qfontdatabase.h>
00063 
00064 #include "qtlog.h"
00065 
00066 nsFontQt::nsFontQt(const nsFont &aFont, nsIAtom *aLangGroup, nsIDeviceContext *aContext)
00067 {
00068     mLangGroup = aLangGroup;
00069     mDeviceContext = aContext;
00070 
00071     float a2d = aContext->AppUnitsToDevUnits();
00072     mPixelSize = NSToIntRound(a2d * aFont.size);
00073 
00074     if (mLangGroup) {
00075         nsCAutoString name("font.min-size.variable.");
00076         const char* langGroup = nsnull;
00077         mLangGroup->GetUTF8String(&langGroup);
00078 
00079         PRInt32 minimum = 0;
00080         nsresult res;
00081         nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &res);
00082         if (NS_SUCCEEDED(res)) {
00083             nsCOMPtr<nsIPrefBranch> branch;
00084             prefs->GetBranch(name.get(), getter_AddRefs(branch));
00085             branch->GetIntPref(langGroup, &minimum);
00086         }
00087         if (minimum < 0) {
00088             minimum = 0;
00089         }
00090         if (mPixelSize < minimum) {
00091             mPixelSize = minimum;
00092         }
00093     }
00094 
00095     font.setFamily(QString::fromUcs2(aFont.name.get()));
00096     font.setPixelSize(mPixelSize);
00097     font.setWeight(aFont.weight/10);
00098     font.setItalic(aFont.style != NS_FONT_STYLE_NORMAL);
00099 
00100     RealizeFont();
00101 }
00102 
00103 void nsFontQt::RealizeFont()
00104 {
00105     QFontMetrics fm(font);
00106 
00107     float f = mDeviceContext->DevUnitsToAppUnits();
00108 
00109     mMaxAscent = nscoord(fm.ascent() * f) ;
00110     mMaxDescent = nscoord(fm.descent() * f);
00111     mMaxHeight = mMaxAscent + mMaxDescent;
00112 
00113     mEmHeight = nscoord(fm.height() * f);
00114     mMaxAdvance = nscoord(fm.maxWidth() * f);
00115 
00116     mAveCharWidth = nscoord(fm.width(QChar('x')) * f);
00117 
00118     mEmAscent = mMaxAscent;
00119     mEmDescent = mMaxDescent;
00120 
00121     mXHeight = NSToCoordRound(fm.boundingRect('x').height() * f);
00122 
00123     mUnderlineOffset = - nscoord(fm.underlinePos() * f);
00124 
00125     mUnderlineSize = NSToIntRound(fm.lineWidth() * f);
00126 
00127     mSuperscriptOffset = mXHeight;
00128     mSubscriptOffset = mXHeight;
00129 
00130     mStrikeoutOffset = nscoord(fm.strikeOutPos() * f);
00131     mStrikeoutSize = mUnderlineSize;
00132 
00133     mLeading = nscoord(fm.leading() * f);
00134     mSpaceWidth = nscoord(fm.width(QChar(' ')) * f);
00135 }
00136 
00137 nsFontMetricsQt::nsFontMetricsQt()
00138 {
00139     qFont = 0;
00140 }
00141 
00142 nsFontMetricsQt::~nsFontMetricsQt()
00143 {
00144     NS_ASSERTION(qFont == 0, "deleting non destroyed nsFontMetricsQt");
00145 }
00146 
00147 NS_IMPL_ISUPPORTS1(nsFontMetricsQt,nsIFontMetrics)
00148 
00149     NS_IMETHODIMP nsFontMetricsQt::Init(const nsFont &aFont, nsIAtom *aLangGroup,
00150                                         nsIDeviceContext *aContext)
00151 {
00152     NS_ASSERTION(!(nsnull == aContext), "attempt to init fontmetrics with null device context");
00153 
00154     mFont = aFont;
00155     qFont = new nsFontQt(aFont, aLangGroup, aContext);
00156     return NS_OK;
00157 }
00158 
00159 NS_IMETHODIMP nsFontMetricsQt::Destroy()
00160 {
00161     delete qFont;
00162     qFont = 0;
00163     return NS_OK;
00164 }
00165 
00166 NS_IMETHODIMP nsFontMetricsQt::GetXHeight(nscoord &aResult)
00167 {
00168     aResult = qFont->mXHeight;
00169     return NS_OK;
00170 }
00171 
00172 NS_IMETHODIMP nsFontMetricsQt::GetSuperscriptOffset(nscoord &aResult)
00173 {
00174     aResult = qFont->mSuperscriptOffset;
00175     return NS_OK;
00176 }
00177 
00178 NS_IMETHODIMP nsFontMetricsQt::GetSubscriptOffset(nscoord &aResult)
00179 {
00180     aResult = qFont->mSubscriptOffset;
00181     return NS_OK;
00182 }
00183 
00184 NS_IMETHODIMP nsFontMetricsQt::GetStrikeout(nscoord &aOffset,nscoord &aSize)
00185 {
00186     aOffset = qFont->mStrikeoutOffset;
00187     aSize = qFont->mStrikeoutSize;
00188     return NS_OK;
00189 }
00190 
00191 NS_IMETHODIMP nsFontMetricsQt::GetUnderline(nscoord &aOffset,nscoord &aSize)
00192 {
00193     aOffset = qFont->mUnderlineOffset;
00194     aSize = qFont->mUnderlineSize;
00195     return NS_OK;
00196 }
00197 
00198 NS_IMETHODIMP nsFontMetricsQt::GetHeight(nscoord &aHeight)
00199 {
00200     aHeight = qFont->mMaxHeight;
00201     return NS_OK;
00202 }
00203 
00204 NS_IMETHODIMP nsFontMetricsQt::GetNormalLineHeight(nscoord &aHeight)
00205 {
00206     aHeight = qFont->mEmHeight + qFont->mLeading;
00207     return NS_OK;
00208 }
00209 
00210 NS_IMETHODIMP nsFontMetricsQt::GetLeading(nscoord &aLeading)
00211 {
00212     aLeading = qFont->mLeading;
00213     return NS_OK;
00214 }
00215 
00216 NS_IMETHODIMP nsFontMetricsQt::GetEmHeight(nscoord &aHeight)
00217 {
00218     aHeight = qFont->mEmHeight;
00219     return NS_OK;
00220 }
00221 
00222 NS_IMETHODIMP nsFontMetricsQt::GetEmAscent(nscoord &aAscent)
00223 {
00224     aAscent = qFont->mEmAscent;
00225     return NS_OK;
00226 }
00227 
00228 NS_IMETHODIMP nsFontMetricsQt::GetEmDescent(nscoord &aDescent)
00229 {
00230     aDescent = qFont->mEmDescent;
00231     return NS_OK;
00232 }
00233 
00234 NS_IMETHODIMP nsFontMetricsQt::GetMaxHeight(nscoord &aHeight)
00235 {
00236     aHeight = qFont->mMaxHeight;
00237     return NS_OK;
00238 }
00239 
00240 NS_IMETHODIMP nsFontMetricsQt::GetMaxAscent(nscoord &aAscent)
00241 {
00242     aAscent = qFont->mMaxAscent;
00243     return NS_OK;
00244 }
00245 
00246 NS_IMETHODIMP nsFontMetricsQt::GetMaxDescent(nscoord &aDescent)
00247 {
00248     aDescent = qFont->mMaxDescent;
00249     return NS_OK;
00250 }
00251 
00252 NS_IMETHODIMP nsFontMetricsQt::GetMaxAdvance(nscoord &aAdvance)
00253 {
00254     aAdvance = qFont->mMaxAdvance;
00255     return NS_OK;
00256 }
00257 
00258 NS_IMETHODIMP nsFontMetricsQt::GetAveCharWidth(nscoord &aAveCharWidth)
00259 {
00260     aAveCharWidth = qFont->mAveCharWidth;
00261     return NS_OK;
00262 }
00263 
00264 NS_IMETHODIMP nsFontMetricsQt::GetSpaceWidth(nscoord &aSpaceWidth)
00265 {
00266     aSpaceWidth = qFont->mSpaceWidth;
00267     return NS_OK;
00268 }
00269 
00270 NS_IMETHODIMP nsFontMetricsQt::GetLangGroup(nsIAtom **aLangGroup)
00271 {
00272     if (!aLangGroup) {
00273         return NS_ERROR_NULL_POINTER;
00274     }
00275     *aLangGroup = qFont->mLangGroup;
00276     NS_IF_ADDREF(*aLangGroup);
00277     return NS_OK;
00278 }
00279 
00280 
00281 NS_IMETHODIMP nsFontMetricsQt::GetFontHandle(nsFontHandle &aHandle)
00282 {
00283     aHandle = (nsFontHandle)qFont;
00284     return NS_OK;
00285 }
00286 
00287 static nsresult EnumFonts(nsIAtom *aLangGroup,const char *aGeneric,
00288                           PRUint32 *aCount,PRUnichar ***aResult)
00289 {
00290     *aResult = nsnull;
00291     *aCount = 0;
00292     /* Get list of all fonts */
00293     QStringList qFamilies = QFontDatabase().families();
00294     int count = qFamilies.count();
00295 
00296     PRUnichar **array = (PRUnichar**)nsMemory::Alloc(count * sizeof(PRUnichar*));
00297     NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
00298 
00299     int i = 0;
00300     for (QStringList::ConstIterator famIt = qFamilies.begin(); famIt != qFamilies.end(); ++famIt) {
00301         QString family = *famIt;
00302         array[i] = new PRUnichar[family.length()];
00303         if (array[i]) {
00304             memcpy(array[i], family.unicode(), family.length()*sizeof(PRUnichar));
00305             i++;
00306         }
00307         else {
00308             // OOM. Decrease the count and resize the array accordingly.
00309             count--;
00310             array = (PRUnichar**)nsMemory::Realloc((void*)array, count * sizeof(PRUnichar*));
00311         }
00312     }
00313 
00314     *aCount = count;
00315     *aResult = array;
00316     return NS_OK;
00317 }
00318 
00319 nsFontEnumeratorQt::nsFontEnumeratorQt()
00320 {
00321 }
00322 
00323 NS_IMPL_ISUPPORTS1(nsFontEnumeratorQt, nsIFontEnumerator)
00324 
00325 NS_IMETHODIMP
00326 nsFontEnumeratorQt::EnumerateAllFonts(PRUint32 *aCount,PRUnichar ***aResult)
00327 {
00328     NS_ENSURE_ARG_POINTER(aResult);
00329     *aResult = nsnull;
00330     NS_ENSURE_ARG_POINTER(aCount);
00331     *aCount = 0;
00332 
00333     return EnumFonts(nsnull,nsnull,aCount,aResult);
00334 }
00335 
00336 NS_IMETHODIMP
00337 nsFontEnumeratorQt::EnumerateFonts(const char *aLangGroup,const char *aGeneric,
00338                                    PRUint32 *aCount,PRUnichar ***aResult)
00339 {
00340     nsresult res;
00341 
00342     NS_ENSURE_ARG_POINTER(aResult);
00343     *aResult = nsnull;
00344     NS_ENSURE_ARG_POINTER(aCount);
00345     *aCount = 0;
00346     NS_ENSURE_ARG_POINTER(aGeneric);
00347     NS_ENSURE_ARG_POINTER(aLangGroup);
00348 
00349     nsIAtom *langGroup = NS_NewAtom(aLangGroup);
00350     res = EnumFonts(langGroup,aGeneric,aCount,aResult);
00351     NS_IF_RELEASE(langGroup);
00352     return(res);
00353 }
00354 
00355 NS_IMETHODIMP
00356 nsFontEnumeratorQt::HaveFontFor(const char *aLangGroup,PRBool *aResult)
00357 {
00358     NS_ENSURE_ARG_POINTER(aResult);
00359     NS_ENSURE_ARG_POINTER(aLangGroup);
00360 
00361     *aResult = PR_TRUE; // always return true for now.
00362     // Finish me
00363     return NS_OK;
00364 }
00365 
00366 NS_IMETHODIMP
00367 nsFontEnumeratorQt::GetDefaultFont(const char *aLangGroup,
00368                                    const char *aGeneric,
00369                                    PRUnichar **aResult)
00370 {
00371     // aLangGroup=null or ""  means any (i.e., don't care)
00372     // aGeneric=null or ""  means any (i.e, don't care)
00373 
00374     NS_ENSURE_ARG_POINTER(aResult);
00375     *aResult = nsnull;
00376 
00377     return NS_OK;
00378 }
00379 
00380 NS_IMETHODIMP
00381 nsFontEnumeratorQt::UpdateFontList(PRBool *updateFontList)
00382 {
00383     *updateFontList = PR_FALSE; // always return false for now
00384     return NS_OK;
00385 }