LCOV - code coverage report
Current view: directory - gfx/src - nsFontMetrics.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 155 0 0.0 %
Date: 2012-06-02 Functions: 40 0 0.0 %

       1                 : /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * mozilla.org.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 2005
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *   Stuart Parmenter <pavlov@pavlov.net>
      24                 :  *
      25                 :  * Alternatively, the contents of this file may be used under the terms of
      26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      29                 :  * of those above. If you wish to allow use of your version of this file only
      30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      31                 :  * use your version of this file under the terms of the MPL, indicate your
      32                 :  * decision by deleting the provisions above and replace them with the notice
      33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      34                 :  * the provisions above, a recipient may use your version of this file under
      35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      36                 :  *
      37                 :  * ***** END LICENSE BLOCK ***** */
      38                 : 
      39                 : #include "nsFontMetrics.h"
      40                 : #include "nsBoundingMetrics.h"
      41                 : #include "nsRenderingContext.h"
      42                 : #include "nsDeviceContext.h"
      43                 : #include "nsStyleConsts.h"
      44                 : 
      45                 : namespace {
      46                 : 
      47               0 : class AutoTextRun {
      48                 : public:
      49               0 :     AutoTextRun(nsFontMetrics* aMetrics, nsRenderingContext* aRC,
      50                 :                 const char* aString, PRInt32 aLength)
      51               0 :     {
      52                 :         mTextRun = aMetrics->GetThebesFontGroup()->MakeTextRun(
      53                 :             reinterpret_cast<const PRUint8*>(aString), aLength,
      54                 :             aRC->ThebesContext(),
      55                 :             aMetrics->AppUnitsPerDevPixel(),
      56               0 :             ComputeFlags(aMetrics));
      57               0 :     }
      58                 : 
      59               0 :     AutoTextRun(nsFontMetrics* aMetrics, nsRenderingContext* aRC,
      60                 :                 const PRUnichar* aString, PRInt32 aLength)
      61               0 :     {
      62                 :         mTextRun = aMetrics->GetThebesFontGroup()->MakeTextRun(
      63                 :             aString, aLength,
      64                 :             aRC->ThebesContext(),
      65                 :             aMetrics->AppUnitsPerDevPixel(),
      66               0 :             ComputeFlags(aMetrics));
      67               0 :     }
      68                 : 
      69               0 :     gfxTextRun *get() { return mTextRun; }
      70               0 :     gfxTextRun *operator->() { return mTextRun; }
      71                 : 
      72                 : private:
      73               0 :     static PRUint32 ComputeFlags(nsFontMetrics* aMetrics) {
      74               0 :         PRUint32 flags = 0;
      75               0 :         if (aMetrics->GetTextRunRTL()) {
      76               0 :             flags |= gfxTextRunFactory::TEXT_IS_RTL;
      77                 :         }
      78               0 :         return flags;
      79                 :     }
      80                 : 
      81                 :     nsAutoPtr<gfxTextRun> mTextRun;
      82                 : };
      83                 : 
      84               0 : class StubPropertyProvider : public gfxTextRun::PropertyProvider {
      85                 : public:
      86               0 :     virtual void GetHyphenationBreaks(PRUint32 aStart, PRUint32 aLength,
      87                 :                                       bool* aBreakBefore) {
      88               0 :         NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText");
      89               0 :     }
      90               0 :     virtual PRInt8 GetHyphensOption() {
      91               0 :         NS_ERROR("This shouldn't be called because we never call BreakAndMeasureText");
      92               0 :         return NS_STYLE_HYPHENS_NONE;
      93                 :     }
      94               0 :     virtual gfxFloat GetHyphenWidth() {
      95               0 :         NS_ERROR("This shouldn't be called because we never enable hyphens");
      96               0 :         return 0;
      97                 :     }
      98               0 :     virtual void GetSpacing(PRUint32 aStart, PRUint32 aLength,
      99                 :                             Spacing* aSpacing) {
     100               0 :         NS_ERROR("This shouldn't be called because we never enable spacing");
     101               0 :     }
     102                 : };
     103                 : 
     104                 : } // anon namespace
     105                 : 
     106               0 : nsFontMetrics::nsFontMetrics()
     107               0 :     : mDeviceContext(nsnull), mP2A(0), mTextRunRTL(false)
     108                 : {
     109               0 : }
     110                 : 
     111               0 : nsFontMetrics::~nsFontMetrics()
     112                 : {
     113               0 :     if (mDeviceContext)
     114               0 :         mDeviceContext->FontMetricsDeleted(this);
     115               0 : }
     116                 : 
     117                 : nsresult
     118               0 : nsFontMetrics::Init(const nsFont& aFont, nsIAtom* aLanguage,
     119                 :                     nsDeviceContext *aContext,
     120                 :                     gfxUserFontSet *aUserFontSet)
     121                 : {
     122               0 :     NS_ABORT_IF_FALSE(mP2A == 0, "already initialized");
     123                 : 
     124               0 :     mFont = aFont;
     125               0 :     mLanguage = aLanguage;
     126               0 :     mDeviceContext = aContext;
     127               0 :     mP2A = mDeviceContext->AppUnitsPerDevPixel();
     128                 : 
     129                 :     gfxFontStyle style(aFont.style,
     130                 :                        aFont.weight,
     131                 :                        aFont.stretch,
     132                 :                        gfxFloat(aFont.size) / mP2A,
     133                 :                        aLanguage,
     134                 :                        aFont.sizeAdjust,
     135                 :                        aFont.systemFont,
     136               0 :                        mDeviceContext->IsPrinterSurface(),
     137                 :                        aFont.featureSettings,
     138               0 :                        aFont.languageOverride);
     139                 : 
     140               0 :     mFontGroup = gfxPlatform::GetPlatform()->
     141               0 :         CreateFontGroup(aFont.name, &style, aUserFontSet);
     142               0 :     if (mFontGroup->FontListLength() < 1)
     143               0 :         return NS_ERROR_UNEXPECTED;
     144                 : 
     145               0 :     return NS_OK;
     146                 : }
     147                 : 
     148                 : void
     149               0 : nsFontMetrics::Destroy()
     150                 : {
     151               0 :     mDeviceContext = nsnull;
     152               0 : }
     153                 : 
     154                 : // XXXTODO get rid of this macro
     155                 : #define ROUND_TO_TWIPS(x) (nscoord)floor(((x) * mP2A) + 0.5)
     156                 : #define CEIL_TO_TWIPS(x) (nscoord)ceil((x) * mP2A)
     157                 : 
     158               0 : const gfxFont::Metrics& nsFontMetrics::GetMetrics() const
     159                 : {
     160               0 :     return mFontGroup->GetFontAt(0)->GetMetrics();
     161                 : }
     162                 : 
     163                 : nscoord
     164               0 : nsFontMetrics::XHeight()
     165                 : {
     166               0 :     return ROUND_TO_TWIPS(GetMetrics().xHeight);
     167                 : }
     168                 : 
     169                 : nscoord
     170               0 : nsFontMetrics::SuperscriptOffset()
     171                 : {
     172               0 :     return ROUND_TO_TWIPS(GetMetrics().superscriptOffset);
     173                 : }
     174                 : 
     175                 : nscoord
     176               0 : nsFontMetrics::SubscriptOffset()
     177                 : {
     178               0 :     return ROUND_TO_TWIPS(GetMetrics().subscriptOffset);
     179                 : }
     180                 : 
     181                 : void
     182               0 : nsFontMetrics::GetStrikeout(nscoord& aOffset, nscoord& aSize)
     183                 : {
     184               0 :     aOffset = ROUND_TO_TWIPS(GetMetrics().strikeoutOffset);
     185               0 :     aSize = ROUND_TO_TWIPS(GetMetrics().strikeoutSize);
     186               0 : }
     187                 : 
     188                 : void
     189               0 : nsFontMetrics::GetUnderline(nscoord& aOffset, nscoord& aSize)
     190                 : {
     191               0 :     aOffset = ROUND_TO_TWIPS(mFontGroup->GetUnderlineOffset());
     192               0 :     aSize = ROUND_TO_TWIPS(GetMetrics().underlineSize);
     193               0 : }
     194                 : 
     195                 : // GetMaxAscent/GetMaxDescent/GetMaxHeight must contain the
     196                 : // text-decoration lines drawable area. See bug 421353.
     197                 : // BE CAREFUL for rounding each values. The logic MUST be same as
     198                 : // nsCSSRendering::GetTextDecorationRectInternal's.
     199                 : 
     200               0 : static gfxFloat ComputeMaxDescent(const gfxFont::Metrics& aMetrics,
     201                 :                                   gfxFontGroup* aFontGroup)
     202                 : {
     203               0 :     gfxFloat offset = floor(-aFontGroup->GetUnderlineOffset() + 0.5);
     204               0 :     gfxFloat size = NS_round(aMetrics.underlineSize);
     205               0 :     gfxFloat minDescent = floor(offset + size + 0.5);
     206               0 :     return NS_MAX(minDescent, aMetrics.maxDescent);
     207                 : }
     208                 : 
     209               0 : static gfxFloat ComputeMaxAscent(const gfxFont::Metrics& aMetrics)
     210                 : {
     211               0 :     return floor(aMetrics.maxAscent + 0.5);
     212                 : }
     213                 : 
     214                 : nscoord
     215               0 : nsFontMetrics::InternalLeading()
     216                 : {
     217               0 :     return ROUND_TO_TWIPS(GetMetrics().internalLeading);
     218                 : }
     219                 : 
     220                 : nscoord
     221               0 : nsFontMetrics::ExternalLeading()
     222                 : {
     223               0 :     return ROUND_TO_TWIPS(GetMetrics().externalLeading);
     224                 : }
     225                 : 
     226                 : nscoord
     227               0 : nsFontMetrics::EmHeight()
     228                 : {
     229               0 :     return ROUND_TO_TWIPS(GetMetrics().emHeight);
     230                 : }
     231                 : 
     232                 : nscoord
     233               0 : nsFontMetrics::EmAscent()
     234                 : {
     235               0 :     return ROUND_TO_TWIPS(GetMetrics().emAscent);
     236                 : }
     237                 : 
     238                 : nscoord
     239               0 : nsFontMetrics::EmDescent()
     240                 : {
     241               0 :     return ROUND_TO_TWIPS(GetMetrics().emDescent);
     242                 : }
     243                 : 
     244                 : nscoord
     245               0 : nsFontMetrics::MaxHeight()
     246                 : {
     247               0 :     return CEIL_TO_TWIPS(ComputeMaxAscent(GetMetrics())) +
     248               0 :         CEIL_TO_TWIPS(ComputeMaxDescent(GetMetrics(), mFontGroup));
     249                 : }
     250                 : 
     251                 : nscoord
     252               0 : nsFontMetrics::MaxAscent()
     253                 : {
     254               0 :     return CEIL_TO_TWIPS(ComputeMaxAscent(GetMetrics()));
     255                 : }
     256                 : 
     257                 : nscoord
     258               0 : nsFontMetrics::MaxDescent()
     259                 : {
     260               0 :     return CEIL_TO_TWIPS(ComputeMaxDescent(GetMetrics(), mFontGroup));
     261                 : }
     262                 : 
     263                 : nscoord
     264               0 : nsFontMetrics::MaxAdvance()
     265                 : {
     266               0 :     return CEIL_TO_TWIPS(GetMetrics().maxAdvance);
     267                 : }
     268                 : 
     269                 : nscoord
     270               0 : nsFontMetrics::AveCharWidth()
     271                 : {
     272                 :     // Use CEIL instead of ROUND for consistency with GetMaxAdvance
     273               0 :     return CEIL_TO_TWIPS(GetMetrics().aveCharWidth);
     274                 : }
     275                 : 
     276                 : nscoord
     277               0 : nsFontMetrics::SpaceWidth()
     278                 : {
     279               0 :     return CEIL_TO_TWIPS(GetMetrics().spaceWidth);
     280                 : }
     281                 : 
     282                 : PRInt32
     283               0 : nsFontMetrics::GetMaxStringLength()
     284                 : {
     285               0 :     const gfxFont::Metrics& m = GetMetrics();
     286               0 :     const double x = 32767.0 / m.maxAdvance;
     287               0 :     PRInt32 len = (PRInt32)floor(x);
     288               0 :     return NS_MAX(1, len);
     289                 : }
     290                 : 
     291                 : nscoord
     292               0 : nsFontMetrics::GetWidth(const char* aString, PRUint32 aLength,
     293                 :                         nsRenderingContext *aContext)
     294                 : {
     295               0 :     if (aLength == 0)
     296               0 :         return 0;
     297                 : 
     298               0 :     if (aLength == 1 && aString[0] == ' ')
     299               0 :         return SpaceWidth();
     300                 : 
     301               0 :     StubPropertyProvider provider;
     302               0 :     AutoTextRun textRun(this, aContext, aString, aLength);
     303               0 :     return textRun.get() ?
     304               0 :         NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider)) : 0;
     305                 : }
     306                 : 
     307                 : nscoord
     308               0 : nsFontMetrics::GetWidth(const PRUnichar* aString, PRUint32 aLength,
     309                 :                         nsRenderingContext *aContext)
     310                 : {
     311               0 :     if (aLength == 0)
     312               0 :         return 0;
     313                 : 
     314               0 :     if (aLength == 1 && aString[0] == ' ')
     315               0 :         return SpaceWidth();
     316                 : 
     317               0 :     StubPropertyProvider provider;
     318               0 :     AutoTextRun textRun(this, aContext, aString, aLength);
     319               0 :     return textRun.get() ?
     320               0 :         NSToCoordRound(textRun->GetAdvanceWidth(0, aLength, &provider)) : 0;
     321                 : }
     322                 : 
     323                 : // Draw a string using this font handle on the surface passed in.
     324                 : void
     325               0 : nsFontMetrics::DrawString(const char *aString, PRUint32 aLength,
     326                 :                           nscoord aX, nscoord aY,
     327                 :                           nsRenderingContext *aContext)
     328                 : {
     329               0 :     if (aLength == 0)
     330               0 :         return;
     331                 : 
     332               0 :     StubPropertyProvider provider;
     333               0 :     AutoTextRun textRun(this, aContext, aString, aLength);
     334               0 :     if (!textRun.get()) {
     335                 :         return;
     336                 :     }
     337               0 :     gfxPoint pt(aX, aY);
     338               0 :     if (mTextRunRTL) {
     339               0 :         pt.x += textRun->GetAdvanceWidth(0, aLength, &provider);
     340                 :     }
     341                 :     textRun->Draw(aContext->ThebesContext(), pt, gfxFont::GLYPH_FILL, 0, aLength,
     342               0 :                   &provider, nsnull, nsnull);
     343                 : }
     344                 : 
     345                 : void
     346               0 : nsFontMetrics::DrawString(const PRUnichar* aString, PRUint32 aLength,
     347                 :                           nscoord aX, nscoord aY,
     348                 :                           nsRenderingContext *aContext,
     349                 :                           nsRenderingContext *aTextRunConstructionContext)
     350                 : {
     351               0 :     if (aLength == 0)
     352               0 :         return;
     353                 : 
     354               0 :     StubPropertyProvider provider;
     355               0 :     AutoTextRun textRun(this, aTextRunConstructionContext, aString, aLength);
     356               0 :     if (!textRun.get()) {
     357                 :         return;
     358                 :     }
     359               0 :     gfxPoint pt(aX, aY);
     360               0 :     if (mTextRunRTL) {
     361               0 :         pt.x += textRun->GetAdvanceWidth(0, aLength, &provider);
     362                 :     }
     363                 :     textRun->Draw(aContext->ThebesContext(), pt, gfxFont::GLYPH_FILL, 0, aLength,
     364               0 :                   &provider, nsnull, nsnull);
     365                 : }
     366                 : 
     367                 : nsBoundingMetrics
     368               0 : nsFontMetrics::GetBoundingMetrics(const PRUnichar *aString, PRUint32 aLength,
     369                 :                                   nsRenderingContext *aContext)
     370                 : {
     371               0 :     if (aLength == 0)
     372               0 :         return nsBoundingMetrics();
     373                 : 
     374               0 :     StubPropertyProvider provider;
     375               0 :     AutoTextRun textRun(this, aContext, aString, aLength);
     376               0 :     nsBoundingMetrics m;
     377               0 :     if (textRun.get()) {
     378                 :         gfxTextRun::Metrics theMetrics =
     379                 :             textRun->MeasureText(0, aLength,
     380                 :                                  gfxFont::TIGHT_HINTED_OUTLINE_EXTENTS,
     381               0 :                                  aContext->ThebesContext(), &provider);
     382                 : 
     383               0 :         m.leftBearing  = NSToCoordFloor( theMetrics.mBoundingBox.X());
     384               0 :         m.rightBearing = NSToCoordCeil(  theMetrics.mBoundingBox.XMost());
     385               0 :         m.ascent       = NSToCoordCeil( -theMetrics.mBoundingBox.Y());
     386               0 :         m.descent      = NSToCoordCeil(  theMetrics.mBoundingBox.YMost());
     387               0 :         m.width        = NSToCoordRound( theMetrics.mAdvanceWidth);
     388                 :     }
     389               0 :     return m;
     390                 : }

Generated by: LCOV version 1.7