LCOV - code coverage report
Current view: directory - gfx/thebes - gfxUserFontSet.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 267 2 0.7 %
Date: 2012-06-02 Functions: 28 2 7.1 %

       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 thebes gfx code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is Mozilla Foundation.
      18                 :  * Portions created by the Initial Developer are Copyright (C) 2008-2009
      19                 :  * the Initial Developer. All Rights Reserved.
      20                 :  *
      21                 :  * Contributor(s):
      22                 :  *   John Daggett <jdaggett@mozilla.com>
      23                 :  *   Jonathan Kew <jfkthame@gmail.com>
      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                 : #ifdef MOZ_LOGGING
      40                 : #define FORCE_PR_LOG /* Allow logging in the release build */
      41                 : #endif /* MOZ_LOGGING */
      42                 : #include "prlog.h"
      43                 : 
      44                 : #include "gfxUserFontSet.h"
      45                 : #include "gfxPlatform.h"
      46                 : #include "nsReadableUtils.h"
      47                 : #include "nsUnicharUtils.h"
      48                 : #include "prlong.h"
      49                 : 
      50                 : #include "woff.h"
      51                 : 
      52                 : #include "opentype-sanitiser.h"
      53                 : #include "ots-memory-stream.h"
      54                 : 
      55                 : using namespace mozilla;
      56                 : 
      57                 : #ifdef PR_LOGGING
      58            1464 : PRLogModuleInfo *gfxUserFontSet::sUserFontsLog = PR_NewLogModule("userfonts");
      59                 : #endif /* PR_LOGGING */
      60                 : 
      61                 : #define LOG(args) PR_LOG(sUserFontsLog, PR_LOG_DEBUG, args)
      62                 : #define LOG_ENABLED() PR_LOG_TEST(sUserFontsLog, PR_LOG_DEBUG)
      63                 : 
      64                 : static PRUint64 sFontSetGeneration = LL_INIT(0, 0);
      65                 : 
      66                 : // TODO: support for unicode ranges not yet implemented
      67                 : 
      68               0 : gfxProxyFontEntry::gfxProxyFontEntry(const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
      69                 :              gfxMixedFontFamily *aFamily,
      70                 :              PRUint32 aWeight,
      71                 :              PRUint32 aStretch,
      72                 :              PRUint32 aItalicStyle,
      73                 :              const nsTArray<gfxFontFeature>& aFeatureSettings,
      74                 :              PRUint32 aLanguageOverride,
      75                 :              gfxSparseBitSet *aUnicodeRanges)
      76               0 :     : gfxFontEntry(NS_LITERAL_STRING("Proxy"), aFamily),
      77                 :       mLoadingState(NOT_LOADING),
      78               0 :       mUnsupportedFormat(false)
      79                 : {
      80               0 :     mIsProxy = true;
      81               0 :     mSrcList = aFontFaceSrcList;
      82               0 :     mSrcIndex = 0;
      83               0 :     mWeight = aWeight;
      84               0 :     mStretch = aStretch;
      85               0 :     mItalic = (aItalicStyle & (FONT_STYLE_ITALIC | FONT_STYLE_OBLIQUE)) != 0;
      86               0 :     mFeatureSettings.AppendElements(aFeatureSettings);
      87               0 :     mLanguageOverride = aLanguageOverride;
      88               0 :     mIsUserFont = true;
      89               0 : }
      90                 : 
      91               0 : gfxProxyFontEntry::~gfxProxyFontEntry()
      92                 : {
      93               0 : }
      94                 : 
      95                 : gfxFont*
      96               0 : gfxProxyFontEntry::CreateFontInstance(const gfxFontStyle *aFontStyle, bool aNeedsBold)
      97                 : {
      98                 :     // cannot create an actual font for a proxy entry
      99               0 :     return nsnull;
     100                 : }
     101                 : 
     102               0 : gfxUserFontSet::gfxUserFontSet()
     103                 : {
     104               0 :     mFontFamilies.Init(5);
     105               0 :     IncrementGeneration();
     106               0 : }
     107                 : 
     108               0 : gfxUserFontSet::~gfxUserFontSet()
     109                 : {
     110               0 : }
     111                 : 
     112                 : gfxFontEntry*
     113               0 : gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
     114                 :                             const nsTArray<gfxFontFaceSrc>& aFontFaceSrcList,
     115                 :                             PRUint32 aWeight,
     116                 :                             PRUint32 aStretch,
     117                 :                             PRUint32 aItalicStyle,
     118                 :                             const nsString& aFeatureSettings,
     119                 :                             const nsString& aLanguageOverride,
     120                 :                             gfxSparseBitSet *aUnicodeRanges)
     121                 : {
     122               0 :     gfxProxyFontEntry *proxyEntry = nsnull;
     123                 : 
     124               0 :     nsAutoString key(aFamilyName);
     125               0 :     ToLowerCase(key);
     126                 : 
     127                 :     bool found;
     128                 : 
     129               0 :     if (aWeight == 0)
     130               0 :         aWeight = FONT_WEIGHT_NORMAL;
     131                 : 
     132                 :     // stretch, italic/oblique ==> zero implies normal
     133                 : 
     134               0 :     gfxMixedFontFamily *family = mFontFamilies.GetWeak(key, &found);
     135               0 :     if (!family) {
     136               0 :         family = new gfxMixedFontFamily(aFamilyName);
     137               0 :         mFontFamilies.Put(key, family);
     138                 :     }
     139                 : 
     140                 :     // construct a new face and add it into the family
     141               0 :     nsTArray<gfxFontFeature> featureSettings;
     142                 :     gfxFontStyle::ParseFontFeatureSettings(aFeatureSettings,
     143               0 :                                            featureSettings);
     144                 :     PRUint32 languageOverride =
     145               0 :         gfxFontStyle::ParseFontLanguageOverride(aLanguageOverride);
     146                 :     proxyEntry =
     147                 :         new gfxProxyFontEntry(aFontFaceSrcList, family, aWeight, aStretch,
     148                 :                               aItalicStyle,
     149                 :                               featureSettings,
     150                 :                               languageOverride,
     151               0 :                               aUnicodeRanges);
     152               0 :     family->AddFontEntry(proxyEntry);
     153                 : #ifdef PR_LOGGING
     154               0 :     if (LOG_ENABLED()) {
     155               0 :         LOG(("userfonts (%p) added (%s) with style: %s weight: %d stretch: %d",
     156                 :              this, NS_ConvertUTF16toUTF8(aFamilyName).get(),
     157                 :              (aItalicStyle & FONT_STYLE_ITALIC ? "italic" :
     158                 :                  (aItalicStyle & FONT_STYLE_OBLIQUE ? "oblique" : "normal")),
     159                 :              aWeight, aStretch));
     160                 :     }
     161                 : #endif
     162                 : 
     163               0 :     return proxyEntry;
     164                 : }
     165                 : 
     166                 : void
     167               0 : gfxUserFontSet::AddFontFace(const nsAString& aFamilyName,
     168                 :                             gfxFontEntry     *aFontEntry)
     169                 : {
     170               0 :     nsAutoString key(aFamilyName);
     171               0 :     ToLowerCase(key);
     172                 : 
     173                 :     bool found;
     174                 : 
     175               0 :     gfxMixedFontFamily *family = mFontFamilies.GetWeak(key, &found);
     176               0 :     if (!family) {
     177               0 :         family = new gfxMixedFontFamily(aFamilyName);
     178               0 :         mFontFamilies.Put(key, family);
     179                 :     }
     180                 : 
     181               0 :     family->AddFontEntry(aFontEntry);
     182               0 : }
     183                 : 
     184                 : gfxFontEntry*
     185               0 : gfxUserFontSet::FindFontEntry(const nsAString& aName, 
     186                 :                               const gfxFontStyle& aFontStyle, 
     187                 :                               bool& aFoundFamily,
     188                 :                               bool& aNeedsBold,
     189                 :                               bool& aWaitForUserFont)
     190                 : {
     191               0 :     aWaitForUserFont = false;
     192               0 :     gfxMixedFontFamily *family = GetFamily(aName);
     193                 : 
     194                 :     // no user font defined for this name
     195               0 :     if (!family) {
     196               0 :         aFoundFamily = false;
     197               0 :         return nsnull;
     198                 :     }
     199                 : 
     200               0 :     aFoundFamily = true;
     201               0 :     gfxFontEntry* fe = family->FindFontForStyle(aFontStyle, aNeedsBold);
     202                 : 
     203                 :     // if not a proxy, font has already been loaded
     204               0 :     if (!fe->mIsProxy) {
     205               0 :         return fe;
     206                 :     }
     207                 : 
     208               0 :     gfxProxyFontEntry *proxyEntry = static_cast<gfxProxyFontEntry*> (fe);
     209                 : 
     210                 :     // if currently loading, return null for now
     211               0 :     if (proxyEntry->mLoadingState > gfxProxyFontEntry::NOT_LOADING) {
     212                 :         aWaitForUserFont =
     213               0 :             (proxyEntry->mLoadingState < gfxProxyFontEntry::LOADING_SLOWLY);
     214               0 :         return nsnull;
     215                 :     }
     216                 : 
     217                 :     // hasn't been loaded yet, start the load process
     218                 :     LoadStatus status;
     219                 : 
     220                 :     // NOTE that if all sources in the entry fail, this will delete proxyEntry,
     221                 :     // so we cannot use it again if status==STATUS_END_OF_LIST
     222               0 :     status = LoadNext(proxyEntry);
     223                 : 
     224                 :     // if the load succeeded immediately, the font entry was replaced so
     225                 :     // search again
     226               0 :     if (status == STATUS_LOADED) {
     227               0 :         return family->FindFontForStyle(aFontStyle, aNeedsBold);
     228                 :     }
     229                 : 
     230                 :     // check whether we should wait for load to complete before painting
     231                 :     // a fallback font -- but not if all sources failed (bug 633500)
     232                 :     aWaitForUserFont = (status != STATUS_END_OF_LIST) &&
     233               0 :         (proxyEntry->mLoadingState < gfxProxyFontEntry::LOADING_SLOWLY);
     234                 : 
     235                 :     // if either loading or an error occurred, return null
     236               0 :     return nsnull;
     237                 : }
     238                 : 
     239                 : // Given a buffer of downloaded font data, do any necessary preparation
     240                 : // to make it into usable OpenType.
     241                 : // May return the original pointer unchanged, or a newly-allocated
     242                 : // block (in which case the passed-in block is NS_Free'd).
     243                 : // aLength is updated if necessary to the new length of the data.
     244                 : // Returns NULL and NS_Free's the incoming data in case of errors.
     245                 : static const PRUint8*
     246               0 : PrepareOpenTypeData(const PRUint8* aData, PRUint32* aLength)
     247                 : {
     248               0 :     switch(gfxFontUtils::DetermineFontDataType(aData, *aLength)) {
     249                 :     
     250                 :     case GFX_USERFONT_OPENTYPE:
     251                 :         // nothing to do
     252               0 :         return aData;
     253                 :         
     254                 :     case GFX_USERFONT_WOFF: {
     255               0 :         PRUint32 status = eWOFF_ok;
     256               0 :         PRUint32 bufferSize = woffGetDecodedSize(aData, *aLength, &status);
     257               0 :         if (WOFF_FAILURE(status)) {
     258               0 :             break;
     259                 :         }
     260               0 :         PRUint8* decodedData = static_cast<PRUint8*>(NS_Alloc(bufferSize));
     261               0 :         if (!decodedData) {
     262               0 :             break;
     263                 :         }
     264                 :         woffDecodeToBuffer(aData, *aLength,
     265                 :                            decodedData, bufferSize,
     266               0 :                            aLength, &status);
     267                 :         // replace original data with the decoded version
     268               0 :         NS_Free((void*)aData);
     269               0 :         aData = decodedData;
     270               0 :         if (WOFF_FAILURE(status)) {
     271                 :             // something went wrong, discard the data and return NULL
     272               0 :             break;
     273                 :         }
     274                 :         // success, return the decoded data
     275               0 :         return aData;
     276                 :     }
     277                 : 
     278                 :     // xxx - add support for other wrappers here
     279                 : 
     280                 :     default:
     281               0 :         NS_WARNING("unknown font format");
     282               0 :         break;
     283                 :     }
     284                 : 
     285                 :     // discard downloaded data that couldn't be used
     286               0 :     NS_Free((void*)aData);
     287                 : 
     288               0 :     return nsnull;
     289                 : }
     290                 : 
     291                 : // Based on ots::ExpandingMemoryStream from ots-memory-stream.h,
     292                 : // adapted to use Mozilla allocators and to allow the final
     293                 : // memory buffer to be adopted by the client.
     294                 : class ExpandingMemoryStream : public ots::OTSStream {
     295                 : public:
     296               0 :     ExpandingMemoryStream(size_t initial, size_t limit)
     297               0 :         : mLength(initial), mLimit(limit), mOff(0) {
     298               0 :         mPtr = NS_Alloc(mLength);
     299               0 :     }
     300                 : 
     301               0 :     ~ExpandingMemoryStream() {
     302               0 :         NS_Free(mPtr);
     303               0 :     }
     304                 : 
     305                 :     // return the buffer, and give up ownership of it
     306                 :     // so the caller becomes responsible to call NS_Free
     307                 :     // when finished with it
     308               0 :     void* forget() {
     309               0 :         void* p = mPtr;
     310               0 :         mPtr = nsnull;
     311               0 :         return p;
     312                 :     }
     313                 : 
     314               0 :     bool WriteRaw(const void *data, size_t length) {
     315               0 :         if ((mOff + length > mLength) ||
     316               0 :             (mLength > std::numeric_limits<size_t>::max() - mOff)) {
     317               0 :             if (mLength == mLimit) {
     318               0 :                 return false;
     319                 :             }
     320               0 :             size_t newLength = (mLength + 1) * 2;
     321               0 :             if (newLength < mLength) {
     322               0 :                 return false;
     323                 :             }
     324               0 :             if (newLength > mLimit) {
     325               0 :                 newLength = mLimit;
     326                 :             }
     327               0 :             mPtr = NS_Realloc(mPtr, newLength);
     328               0 :             mLength = newLength;
     329               0 :             return WriteRaw(data, length);
     330                 :         }
     331               0 :         std::memcpy(static_cast<char*>(mPtr) + mOff, data, length);
     332               0 :         mOff += length;
     333               0 :         return true;
     334                 :     }
     335                 : 
     336               0 :     bool Seek(off_t position) {
     337               0 :         if (position < 0) {
     338               0 :             return false;
     339                 :         }
     340               0 :         if (static_cast<size_t>(position) > mLength) {
     341               0 :             return false;
     342                 :         }
     343               0 :         mOff = position;
     344               0 :         return true;
     345                 :     }
     346                 : 
     347               0 :     off_t Tell() const {
     348               0 :         return mOff;
     349                 :     }
     350                 : 
     351                 : private:
     352                 :     void*        mPtr;
     353                 :     size_t       mLength;
     354                 :     const size_t mLimit;
     355                 :     off_t        mOff;
     356                 : };
     357                 : 
     358                 : // Call the OTS library to sanitize an sfnt before attempting to use it.
     359                 : // Returns a newly-allocated block, or NULL in case of fatal errors.
     360                 : static const PRUint8*
     361               0 : SanitizeOpenTypeData(const PRUint8* aData, PRUint32 aLength,
     362                 :                      PRUint32& aSaneLength, bool aIsCompressed)
     363                 : {
     364                 :     // limit output/expansion to 256MB
     365                 :     ExpandingMemoryStream output(aIsCompressed ? aLength * 2 : aLength,
     366               0 :                                  1024 * 1024 * 256);
     367                 : #ifdef MOZ_GRAPHITE
     368                 : #define PRESERVE_GRAPHITE true
     369                 : #else
     370                 : #define PRESERVE_GRAPHITE false
     371                 : #endif
     372               0 :     if (ots::Process(&output, aData, aLength, PRESERVE_GRAPHITE)) {
     373               0 :         aSaneLength = output.Tell();
     374               0 :         return static_cast<PRUint8*>(output.forget());
     375                 :     } else {
     376               0 :         aSaneLength = 0;
     377               0 :         return nsnull;
     378                 :     }
     379                 : }
     380                 : 
     381                 : static void
     382               0 : StoreUserFontData(gfxFontEntry* aFontEntry, gfxProxyFontEntry* aProxy,
     383                 :                   const nsAString& aOriginalName,
     384                 :                   nsTArray<PRUint8>* aMetadata, PRUint32 aMetaOrigLen)
     385                 : {
     386               0 :     if (!aFontEntry->mUserFontData) {
     387               0 :         aFontEntry->mUserFontData = new gfxUserFontData;
     388                 :     }
     389               0 :     gfxUserFontData* userFontData = aFontEntry->mUserFontData;
     390               0 :     userFontData->mSrcIndex = aProxy->mSrcIndex;
     391               0 :     const gfxFontFaceSrc& src = aProxy->mSrcList[aProxy->mSrcIndex];
     392               0 :     if (src.mIsLocal) {
     393               0 :         userFontData->mLocalName = src.mLocalName;
     394                 :     } else {
     395               0 :         userFontData->mURI = src.mURI;
     396                 :     }
     397               0 :     userFontData->mFormat = src.mFormatFlags;
     398               0 :     userFontData->mRealName = aOriginalName;
     399               0 :     if (aMetadata) {
     400               0 :         userFontData->mMetadata.SwapElements(*aMetadata);
     401               0 :         userFontData->mMetaOrigLen = aMetaOrigLen;
     402                 :     }
     403               0 : }
     404                 : 
     405                 : struct WOFFHeader {
     406                 :     AutoSwap_PRUint32 signature;
     407                 :     AutoSwap_PRUint32 flavor;
     408                 :     AutoSwap_PRUint32 length;
     409                 :     AutoSwap_PRUint16 numTables;
     410                 :     AutoSwap_PRUint16 reserved;
     411                 :     AutoSwap_PRUint32 totalSfntSize;
     412                 :     AutoSwap_PRUint16 majorVersion;
     413                 :     AutoSwap_PRUint16 minorVersion;
     414                 :     AutoSwap_PRUint32 metaOffset;
     415                 :     AutoSwap_PRUint32 metaCompLen;
     416                 :     AutoSwap_PRUint32 metaOrigLen;
     417                 :     AutoSwap_PRUint32 privOffset;
     418                 :     AutoSwap_PRUint32 privLen;
     419                 : };
     420                 : 
     421                 : void
     422               0 : gfxUserFontSet::CopyWOFFMetadata(const PRUint8* aFontData,
     423                 :                                  PRUint32 aLength,
     424                 :                                  nsTArray<PRUint8>* aMetadata,
     425                 :                                  PRUint32* aMetaOrigLen)
     426                 : {
     427                 :     // This function may be called with arbitrary, unvalidated "font" data
     428                 :     // from @font-face, so it needs to be careful to bounds-check, etc.,
     429                 :     // before trying to read anything.
     430                 :     // This just saves a copy of the compressed data block; it does NOT check
     431                 :     // that the block can be successfully decompressed, or that it contains
     432                 :     // well-formed/valid XML metadata.
     433               0 :     if (aLength < sizeof(WOFFHeader)) {
     434               0 :         return;
     435                 :     }
     436               0 :     const WOFFHeader* woff = reinterpret_cast<const WOFFHeader*>(aFontData);
     437               0 :     PRUint32 metaOffset = woff->metaOffset;
     438               0 :     PRUint32 metaCompLen = woff->metaCompLen;
     439               0 :     if (!metaOffset || !metaCompLen || !woff->metaOrigLen) {
     440               0 :         return;
     441                 :     }
     442               0 :     if (metaOffset >= aLength || metaCompLen > aLength - metaOffset) {
     443               0 :         return;
     444                 :     }
     445               0 :     if (!aMetadata->SetLength(woff->metaCompLen)) {
     446               0 :         return;
     447                 :     }
     448               0 :     memcpy(aMetadata->Elements(), aFontData + metaOffset, metaCompLen);
     449               0 :     *aMetaOrigLen = woff->metaOrigLen;
     450                 : }
     451                 : 
     452                 : // This is called when a font download finishes.
     453                 : // Ownership of aFontData passes in here, and the font set must
     454                 : // ensure that it is eventually deleted via NS_Free().
     455                 : bool 
     456               0 : gfxUserFontSet::OnLoadComplete(gfxProxyFontEntry *aProxy,
     457                 :                                const PRUint8 *aFontData, PRUint32 aLength,
     458                 :                                nsresult aDownloadStatus)
     459                 : {
     460                 :     // download successful, make platform font using font data
     461               0 :     if (NS_SUCCEEDED(aDownloadStatus)) {
     462                 : 
     463                 :         // if the proxy doesn't belong to a family, we just bail as it won't be
     464                 :         // accessible/usable anyhow (maybe the font set got modified right as
     465                 :         // the load was completing?)
     466               0 :         if (!aProxy->Family()) {
     467               0 :             NS_Free(const_cast<PRUint8*>(aFontData));
     468               0 :             return true;
     469                 :         }
     470                 : 
     471               0 :         gfxFontEntry *fe = nsnull;
     472                 : 
     473                 :         gfxUserFontType fontType =
     474               0 :             gfxFontUtils::DetermineFontDataType(aFontData, aLength);
     475                 : 
     476                 :         // Save a copy of the metadata block (if present) for nsIDOMFontFace
     477                 :         // to use if required. Ownership of the metadata block will be passed
     478                 :         // to the gfxUserFontData record below.
     479                 :         // NOTE: after the non-OTS codepath using PrepareOpenTypeData is
     480                 :         // removed, we should defer this until after we've created the new
     481                 :         // fontEntry.
     482               0 :         nsTArray<PRUint8> metadata;
     483               0 :         PRUint32 metaOrigLen = 0;
     484               0 :         if (fontType == GFX_USERFONT_WOFF) {
     485               0 :             CopyWOFFMetadata(aFontData, aLength, &metadata, &metaOrigLen);
     486                 :         }
     487                 : 
     488                 :         // Unwrap/decompress/sanitize or otherwise munge the downloaded data
     489                 :         // to make a usable sfnt structure.
     490                 : 
     491                 :         // Because platform font activation code may replace the name table
     492                 :         // in the font with a synthetic one, we save the original name so that
     493                 :         // it can be reported via the nsIDOMFontFace API.
     494               0 :         nsAutoString originalFullName;
     495                 : 
     496               0 :         if (gfxPlatform::GetPlatform()->SanitizeDownloadedFonts()) {
     497                 :            // Call the OTS sanitizer; this will also decode WOFF to sfnt
     498                 :             // if necessary. The original data in aFontData is left unchanged.
     499                 :             PRUint32 saneLen;
     500                 :             const PRUint8* saneData =
     501                 :                 SanitizeOpenTypeData(aFontData, aLength, saneLen,
     502               0 :                                      fontType == GFX_USERFONT_WOFF);
     503               0 :             if (!saneData) {
     504               0 :                 LogMessage(aProxy, "rejected by sanitizer");
     505                 :             }
     506               0 :             if (saneData) {
     507                 :                 // The sanitizer ensures that we have a valid sfnt and a usable
     508                 :                 // name table, so this should never fail unless we're out of
     509                 :                 // memory, and GetFullNameFromSFNT is not directly exposed to
     510                 :                 // arbitrary/malicious data from the web.
     511                 :                 gfxFontUtils::GetFullNameFromSFNT(saneData, saneLen,
     512               0 :                                                   originalFullName);
     513                 :                 // Here ownership of saneData is passed to the platform,
     514                 :                 // which will delete it when no longer required
     515               0 :                 fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy,
     516                 :                                                                   saneData,
     517               0 :                                                                   saneLen);
     518               0 :                 if (!fe) {
     519               0 :                     LogMessage(aProxy, "not usable by platform");
     520                 :                 }
     521                 :             }
     522                 :         } else {
     523                 :             // FIXME: this code can be removed once we remove the pref to
     524                 :             // disable the sanitizer; the PrepareOpenTypeData and
     525                 :             // ValidateSFNTHeaders functions will then be obsolete.
     526               0 :             aFontData = PrepareOpenTypeData(aFontData, &aLength);
     527                 : 
     528               0 :             if (aFontData) {
     529               0 :                 if (gfxFontUtils::ValidateSFNTHeaders(aFontData, aLength)) {
     530                 :                     // ValidateSFNTHeaders has checked that we have a valid
     531                 :                     // sfnt structure and a usable 'name' table
     532                 :                     gfxFontUtils::GetFullNameFromSFNT(aFontData, aLength,
     533               0 :                                                       originalFullName);
     534                 :                     // Here ownership of aFontData is passed to the platform,
     535                 :                     // which will delete it when no longer required
     536               0 :                     fe = gfxPlatform::GetPlatform()->MakePlatformFont(aProxy,
     537                 :                                                                       aFontData,
     538               0 :                                                                       aLength);
     539               0 :                     if (!fe) {
     540               0 :                         LogMessage(aProxy, "not usable by platform");
     541                 :                     }
     542               0 :                     aFontData = nsnull; // we must NOT free this below!
     543                 :                 } else {
     544                 :                     // the data was unusable, so just discard it
     545                 :                     // (error will be reported below, if logging is enabled)
     546               0 :                     LogMessage(aProxy, "SFNT header or tables invalid");
     547                 :                 }
     548                 :             }
     549                 :         }
     550                 : 
     551               0 :         if (aFontData) {
     552               0 :             NS_Free((void*)aFontData);
     553               0 :             aFontData = nsnull;
     554                 :         }
     555                 : 
     556               0 :         if (fe) {
     557                 :             // copy OpenType feature/language settings from the proxy to the
     558                 :             // newly-created font entry
     559               0 :             fe->mFeatureSettings.AppendElements(aProxy->mFeatureSettings);
     560               0 :             fe->mLanguageOverride = aProxy->mLanguageOverride;
     561                 :             StoreUserFontData(fe, aProxy, originalFullName,
     562               0 :                               &metadata, metaOrigLen);
     563                 : #ifdef PR_LOGGING
     564                 :             // must do this before ReplaceFontEntry() because that will
     565                 :             // clear the proxy's mFamily pointer!
     566               0 :             if (LOG_ENABLED()) {
     567               0 :                 nsCAutoString fontURI;
     568               0 :                 aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI);
     569               0 :                 LOG(("userfonts (%p) [src %d] loaded uri: (%s) for (%s) gen: %8.8x\n",
     570                 :                      this, aProxy->mSrcIndex, fontURI.get(),
     571                 :                      NS_ConvertUTF16toUTF8(aProxy->mFamily->Name()).get(),
     572                 :                      PRUint32(mGeneration)));
     573                 :             }
     574                 : #endif
     575               0 :             ReplaceFontEntry(aProxy, fe);
     576               0 :             IncrementGeneration();
     577               0 :             return true;
     578                 :         } else {
     579                 : #ifdef PR_LOGGING
     580               0 :             if (LOG_ENABLED()) {
     581               0 :                 nsCAutoString fontURI;
     582               0 :                 aProxy->mSrcList[aProxy->mSrcIndex].mURI->GetSpec(fontURI);
     583               0 :                 LOG(("userfonts (%p) [src %d] failed uri: (%s) for (%s) error making platform font\n",
     584                 :                      this, aProxy->mSrcIndex, fontURI.get(),
     585                 :                      NS_ConvertUTF16toUTF8(aProxy->mFamily->Name()).get()));
     586                 :             }
     587                 : #endif
     588                 :         }
     589                 :     } else {
     590                 :         // download failed
     591                 :         LogMessage(aProxy, "download failed", nsIScriptError::errorFlag,
     592               0 :                    aDownloadStatus);
     593                 :     }
     594                 : 
     595               0 :     if (aFontData) {
     596               0 :         NS_Free((void*)aFontData);
     597                 :     }
     598                 : 
     599                 :     // error occurred, load next src
     600               0 :     (void)LoadNext(aProxy);
     601                 : 
     602                 :     // We ignore the status returned by LoadNext();
     603                 :     // even if loading failed, we need to bump the font-set generation
     604                 :     // and return true in order to trigger reflow, so that fallback
     605                 :     // will be used where the text was "masked" by the pending download
     606               0 :     IncrementGeneration();
     607               0 :     return true;
     608                 : }
     609                 : 
     610                 : 
     611                 : gfxUserFontSet::LoadStatus
     612               0 : gfxUserFontSet::LoadNext(gfxProxyFontEntry *aProxyEntry)
     613                 : {
     614               0 :     PRUint32 numSrc = aProxyEntry->mSrcList.Length();
     615                 : 
     616               0 :     NS_ASSERTION(aProxyEntry->mSrcIndex < numSrc,
     617                 :                  "already at the end of the src list for user font");
     618                 : 
     619               0 :     if (aProxyEntry->mLoadingState == gfxProxyFontEntry::NOT_LOADING) {
     620               0 :         aProxyEntry->mLoadingState = gfxProxyFontEntry::LOADING_STARTED;
     621               0 :         aProxyEntry->mUnsupportedFormat = false;
     622                 :     } else {
     623                 :         // we were already loading; move to the next source,
     624                 :         // but don't reset state - if we've already timed out,
     625                 :         // that counts against the new download
     626               0 :         aProxyEntry->mSrcIndex++;
     627                 :     }
     628                 : 
     629                 :     // load each src entry in turn, until a local face is found
     630                 :     // or a download begins successfully
     631               0 :     while (aProxyEntry->mSrcIndex < numSrc) {
     632               0 :         const gfxFontFaceSrc& currSrc = aProxyEntry->mSrcList[aProxyEntry->mSrcIndex];
     633                 : 
     634                 :         // src local ==> lookup and load
     635                 : 
     636               0 :         if (currSrc.mIsLocal) {
     637                 :             gfxFontEntry *fe =
     638               0 :                 gfxPlatform::GetPlatform()->LookupLocalFont(aProxyEntry,
     639               0 :                                                             currSrc.mLocalName);
     640               0 :             if (fe) {
     641               0 :                 LOG(("userfonts (%p) [src %d] loaded local: (%s) for (%s) gen: %8.8x\n",
     642                 :                      this, aProxyEntry->mSrcIndex,
     643                 :                      NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
     644                 :                      NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get(),
     645                 :                      PRUint32(mGeneration)));
     646               0 :                 fe->mFeatureSettings.AppendElements(aProxyEntry->mFeatureSettings);
     647               0 :                 fe->mLanguageOverride = aProxyEntry->mLanguageOverride;
     648               0 :                 StoreUserFontData(fe, aProxyEntry, nsString(), nsnull, 0);
     649               0 :                 ReplaceFontEntry(aProxyEntry, fe);
     650               0 :                 return STATUS_LOADED;
     651                 :             } else {
     652               0 :                 LOG(("userfonts (%p) [src %d] failed local: (%s) for (%s)\n",
     653                 :                      this, aProxyEntry->mSrcIndex,
     654                 :                      NS_ConvertUTF16toUTF8(currSrc.mLocalName).get(),
     655                 :                      NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
     656                 :             }
     657                 :         }
     658                 : 
     659                 :         // src url ==> start the load process
     660                 :         else {
     661               0 :             if (gfxPlatform::GetPlatform()->IsFontFormatSupported(currSrc.mURI,
     662               0 :                     currSrc.mFormatFlags)) {
     663               0 :                 nsresult rv = StartLoad(aProxyEntry, &currSrc);
     664               0 :                 bool loadOK = NS_SUCCEEDED(rv);
     665               0 :                 if (loadOK) {
     666                 : #ifdef PR_LOGGING
     667               0 :                     if (LOG_ENABLED()) {
     668               0 :                         nsCAutoString fontURI;
     669               0 :                         currSrc.mURI->GetSpec(fontURI);
     670               0 :                         LOG(("userfonts (%p) [src %d] loading uri: (%s) for (%s)\n",
     671                 :                              this, aProxyEntry->mSrcIndex, fontURI.get(),
     672                 :                              NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
     673                 :                     }
     674                 : #endif
     675               0 :                     return STATUS_LOADING;
     676                 :                 } else {
     677                 :                     LogMessage(aProxyEntry, "download failed",
     678               0 :                                nsIScriptError::errorFlag, rv);
     679                 :                 }
     680                 :             } else {
     681                 :                 // We don't log a warning to the web console yet,
     682                 :                 // as another source may load successfully
     683               0 :                 aProxyEntry->mUnsupportedFormat = true;
     684                 :             }
     685                 :         }
     686                 : 
     687               0 :         aProxyEntry->mSrcIndex++;
     688                 :     }
     689                 : 
     690               0 :     if (aProxyEntry->mUnsupportedFormat) {
     691                 :         LogMessage(aProxyEntry, "no supported format found",
     692               0 :                    nsIScriptError::warningFlag);
     693                 :     }
     694                 : 
     695                 :     // all src's failed; mark this entry as unusable (so fallback will occur)
     696               0 :     LOG(("userfonts (%p) failed all src for (%s)\n",
     697                 :         this, NS_ConvertUTF16toUTF8(aProxyEntry->mFamily->Name()).get()));
     698               0 :     aProxyEntry->mLoadingState = gfxProxyFontEntry::LOADING_FAILED;
     699                 : 
     700               0 :     return STATUS_END_OF_LIST;
     701                 : }
     702                 : 
     703                 : void
     704               0 : gfxUserFontSet::IncrementGeneration()
     705                 : {
     706                 :     // add one, increment again if zero
     707               0 :     LL_ADD(sFontSetGeneration, sFontSetGeneration, 1);
     708               0 :     if (LL_IS_ZERO(sFontSetGeneration))
     709               0 :         LL_ADD(sFontSetGeneration, sFontSetGeneration, 1);
     710               0 :     mGeneration = sFontSetGeneration;
     711               0 : }
     712                 : 
     713                 : 
     714                 : gfxMixedFontFamily*
     715               0 : gfxUserFontSet::GetFamily(const nsAString& aFamilyName) const
     716                 : {
     717               0 :     nsAutoString key(aFamilyName);
     718               0 :     ToLowerCase(key);
     719                 : 
     720               0 :     return mFontFamilies.GetWeak(key);
     721            4392 : }

Generated by: LCOV version 1.7