1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Boris Zbarsky <bzbarsky@mit.edu>.
20 : * Portions created by the Initial Developer are Copyright (C) 2001
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : /*
41 : * representation of media lists used when linking to style sheets or by
42 : * @media rules
43 : */
44 :
45 : #ifndef nsIMediaList_h_
46 : #define nsIMediaList_h_
47 :
48 : #include "nsIDOMMediaList.h"
49 : #include "nsTArray.h"
50 : #include "nsIAtom.h"
51 : #include "nsCSSValue.h"
52 :
53 : class nsPresContext;
54 : class nsCSSStyleSheet;
55 : class nsAString;
56 : struct nsMediaFeature;
57 :
58 0 : struct nsMediaExpression {
59 : enum Range { eMin, eMax, eEqual };
60 :
61 : const nsMediaFeature *mFeature;
62 : Range mRange;
63 : nsCSSValue mValue;
64 :
65 : // aActualValue must be obtained from mFeature->mGetter
66 : bool Matches(nsPresContext* aPresContext,
67 : const nsCSSValue& aActualValue) const;
68 : };
69 :
70 : /**
71 : * An nsMediaQueryResultCacheKey records what feature/value combinations
72 : * a set of media query results are valid for. This allows the caller
73 : * to quickly learn whether a prior result of media query evaluation is
74 : * still valid (e.g., due to a window size change) without rerunning all
75 : * of the evaluation and rebuilding the list of rules.
76 : *
77 : * This object may not be used after any media rules in any of the
78 : * sheets it was given to have been modified. However, this is
79 : * generally not a problem since ClearRuleCascades is called on the
80 : * sheet whenever this happens, and these objects are stored inside the
81 : * rule cascades. (FIXME: We're not actually doing this all the time.)
82 : *
83 : * The implementation could be further optimized in the future to store
84 : * ranges (combinations of less-than, less-than-or-equal, greater-than,
85 : * greater-than-or-equal, equal, not-equal, present, not-present) for
86 : * each feature rather than simply storing the list of expressions.
87 : * However, this requires combining any such ranges.
88 : */
89 0 : class nsMediaQueryResultCacheKey {
90 : public:
91 0 : nsMediaQueryResultCacheKey(nsIAtom* aMedium)
92 0 : : mMedium(aMedium)
93 0 : {}
94 :
95 : /**
96 : * Record that aExpression was tested while building the cached set
97 : * that this cache key is for, and that aExpressionMatches was whether
98 : * it matched.
99 : */
100 : void AddExpression(const nsMediaExpression* aExpression,
101 : bool aExpressionMatches);
102 : bool Matches(nsPresContext* aPresContext) const;
103 : private:
104 0 : struct ExpressionEntry {
105 : // FIXME: if we were better at maintaining invariants about clearing
106 : // rule cascades when media lists change, this could be a |const
107 : // nsMediaExpression*| instead.
108 : nsMediaExpression mExpression;
109 : bool mExpressionMatches;
110 : };
111 0 : struct FeatureEntry {
112 : const nsMediaFeature *mFeature;
113 : InfallibleTArray<ExpressionEntry> mExpressions;
114 : };
115 : nsCOMPtr<nsIAtom> mMedium;
116 : nsTArray<FeatureEntry> mFeatureCache;
117 : };
118 :
119 0 : class nsMediaQuery {
120 : public:
121 0 : nsMediaQuery()
122 : : mNegated(false)
123 : , mHasOnly(false)
124 : , mTypeOmitted(false)
125 0 : , mHadUnknownExpression(false)
126 : {
127 0 : }
128 :
129 : private:
130 : // for Clone only
131 0 : nsMediaQuery(const nsMediaQuery& aOther)
132 : : mNegated(aOther.mNegated)
133 : , mHasOnly(aOther.mHasOnly)
134 : , mTypeOmitted(aOther.mTypeOmitted)
135 : , mHadUnknownExpression(aOther.mHadUnknownExpression)
136 : , mMediaType(aOther.mMediaType)
137 : // Clone checks the result of this deep copy for allocation failure
138 0 : , mExpressions(aOther.mExpressions)
139 : {
140 0 : }
141 :
142 : public:
143 :
144 0 : void SetNegated() { mNegated = true; }
145 0 : void SetHasOnly() { mHasOnly = true; }
146 0 : void SetTypeOmitted() { mTypeOmitted = true; }
147 0 : void SetHadUnknownExpression() { mHadUnknownExpression = true; }
148 0 : void SetType(nsIAtom* aMediaType) {
149 0 : NS_ASSERTION(aMediaType,
150 : "expected non-null");
151 0 : mMediaType = aMediaType;
152 0 : }
153 :
154 : // Return a new nsMediaExpression in the array for the caller to fill
155 : // in. The caller must either fill it in completely, or call
156 : // SetHadUnknownExpression on this nsMediaQuery.
157 : // Returns null on out-of-memory.
158 0 : nsMediaExpression* NewExpression() { return mExpressions.AppendElement(); }
159 :
160 : void AppendToString(nsAString& aString) const;
161 :
162 : nsMediaQuery* Clone() const;
163 :
164 : // Does this query apply to the presentation?
165 : // If |aKey| is non-null, add cache information to it.
166 : bool Matches(nsPresContext* aPresContext,
167 : nsMediaQueryResultCacheKey* aKey) const;
168 :
169 : private:
170 : bool mNegated;
171 : bool mHasOnly; // only needed for serialization
172 : bool mTypeOmitted; // only needed for serialization
173 : bool mHadUnknownExpression;
174 : nsCOMPtr<nsIAtom> mMediaType;
175 : nsTArray<nsMediaExpression> mExpressions;
176 : };
177 :
178 : class nsMediaList : public nsIDOMMediaList {
179 : public:
180 : nsMediaList();
181 :
182 : NS_DECL_ISUPPORTS
183 :
184 : NS_DECL_NSIDOMMEDIALIST
185 :
186 : nsresult GetText(nsAString& aMediaText);
187 : nsresult SetText(const nsAString& aMediaText);
188 :
189 : // Does this query apply to the presentation?
190 : // If |aKey| is non-null, add cache information to it.
191 : bool Matches(nsPresContext* aPresContext,
192 : nsMediaQueryResultCacheKey* aKey);
193 :
194 : nsresult SetStyleSheet(nsCSSStyleSheet* aSheet);
195 0 : void AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) {
196 : // Takes ownership of aQuery
197 0 : mArray.AppendElement(aQuery.forget());
198 0 : }
199 :
200 : nsresult Clone(nsMediaList** aResult);
201 :
202 0 : PRInt32 Count() { return mArray.Length(); }
203 : nsMediaQuery* MediumAt(PRInt32 aIndex) { return mArray[aIndex]; }
204 0 : void Clear() { mArray.Clear(); }
205 :
206 : protected:
207 : ~nsMediaList();
208 :
209 : nsresult Delete(const nsAString & aOldMedium);
210 : nsresult Append(const nsAString & aOldMedium);
211 :
212 : InfallibleTArray<nsAutoPtr<nsMediaQuery> > mArray;
213 : // not refcounted; sheet will let us know when it goes away
214 : // mStyleSheet is the sheet that needs to be dirtied when this medialist
215 : // changes
216 : nsCSSStyleSheet* mStyleSheet;
217 : };
218 : #endif /* !defined(nsIMediaList_h_) */
|