Back to index

lightning-sunbird  0.9+nobinonly
nsTreeStyleCache.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) 2003
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *   Dave Hyatt <hyatt@mozilla.org> (Original Author)
00024  *   Jan Varga <varga@ku.sk>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 #include "nsTreeStyleCache.h"
00041 #include "nsISupportsArray.h"
00042 #include "nsStyleSet.h"
00043 
00044 // The style context cache impl
00045 nsStyleContext*
00046 nsTreeStyleCache::GetStyleContext(nsICSSPseudoComparator* aComparator,
00047                                   nsPresContext* aPresContext,
00048                                   nsIContent* aContent, 
00049                                   nsStyleContext* aContext,
00050                                   nsIAtom* aPseudoElement,
00051                                   nsISupportsArray* aInputWord)
00052 {
00053   PRUint32 count;
00054   aInputWord->Count(&count);
00055   nsDFAState startState(0);
00056   nsDFAState* currState = &startState;
00057 
00058   // Go ahead and init the transition table.
00059   if (!mTransitionTable) {
00060     // Automatic miss. Build the table
00061     mTransitionTable =
00062       new nsObjectHashtable(nsnull, nsnull, DeleteDFAState, nsnull);
00063     if (!mTransitionTable)
00064       return nsnull;
00065   }
00066 
00067   // The first transition is always made off the supplied pseudo-element.
00068   nsTransitionKey key(currState->GetStateID(), aPseudoElement);
00069   currState = NS_STATIC_CAST(nsDFAState*, mTransitionTable->Get(&key));
00070 
00071   if (!currState) {
00072     // We had a miss. Make a new state and add it to our hash.
00073     currState = new nsDFAState(mNextState);
00074     if (!currState)
00075       return nsnull;
00076     mNextState++;
00077     mTransitionTable->Put(&key, currState);
00078   }
00079 
00080   for (PRUint32 i = 0; i < count; i++) {
00081     nsCOMPtr<nsIAtom> pseudo = getter_AddRefs(NS_STATIC_CAST(nsIAtom*, aInputWord->ElementAt(i)));
00082     nsTransitionKey key(currState->GetStateID(), pseudo);
00083     currState = NS_STATIC_CAST(nsDFAState*, mTransitionTable->Get(&key));
00084 
00085     if (!currState) {
00086       // We had a miss. Make a new state and add it to our hash.
00087       currState = new nsDFAState(mNextState);
00088       if (!currState)
00089         return nsnull;
00090 
00091       mNextState++;
00092       mTransitionTable->Put(&key, currState);
00093     }
00094   }
00095 
00096   // We're in a final state.
00097   // Look up our style context for this state.
00098   nsStyleContext* result = nsnull;
00099   if (mCache)
00100     result = NS_STATIC_CAST(nsStyleContext*, mCache->Get(currState));
00101   if (!result) {
00102     // We missed the cache. Resolve this pseudo-style.
00103     result = aPresContext->StyleSet()->
00104       ResolvePseudoStyleFor(aContent, aPseudoElement,
00105                             aContext, aComparator).get();
00106 
00107     // Put the style context in our table, transferring the owning reference to the table.
00108     if (!mCache) {
00109       mCache = new nsObjectHashtable(nsnull, nsnull, ReleaseStyleContext, nsnull);
00110       if (!mCache)
00111         return nsnull;
00112     }
00113     mCache->Put(currState, result);
00114   }
00115 
00116   return result;
00117 }
00118 
00119 PRBool PR_CALLBACK
00120 nsTreeStyleCache::DeleteDFAState(nsHashKey *aKey,
00121                                  void *aData,
00122                                  void *closure)
00123 {
00124   nsDFAState* entry = NS_STATIC_CAST(nsDFAState*, aData);
00125   delete entry;
00126   return PR_TRUE;
00127 }
00128 
00129 PRBool PR_CALLBACK
00130 nsTreeStyleCache::ReleaseStyleContext(nsHashKey *aKey,
00131                                       void *aData,
00132                                       void *closure)
00133 {
00134   nsStyleContext* context = NS_STATIC_CAST(nsStyleContext*, aData);
00135   context->Release();
00136   return PR_TRUE;
00137 }