Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /* representation of simple property values within CSS declarations */
8 :
9 : #include "nsCSSValue.h"
10 :
11 : #include "mozilla/ServoStyleSet.h"
12 : #include "mozilla/StyleSheetInlines.h"
13 : #include "mozilla/Likely.h"
14 : #include "mozilla/MemoryReporting.h"
15 : #include "mozilla/css/ImageLoader.h"
16 : #include "CSSCalc.h"
17 : #include "gfxFontConstants.h"
18 : #include "imgIRequest.h"
19 : #include "imgRequestProxy.h"
20 : #include "nsIDocument.h"
21 : #include "nsCSSProps.h"
22 : #include "nsNetUtil.h"
23 : #include "nsPresContext.h"
24 : #include "nsStyleUtil.h"
25 : #include "nsDeviceContext.h"
26 : #include "nsStyleSet.h"
27 : #include "nsContentUtils.h"
28 :
29 : using namespace mozilla;
30 : using namespace mozilla::css;
31 :
32 : static bool
33 1 : MightHaveRef(const nsString& aString)
34 : {
35 1 : const char16_t* current = aString.get();
36 119 : for (; *current != '\0'; current++) {
37 59 : if (*current == '#') {
38 0 : return true;
39 : }
40 : }
41 :
42 1 : return false;
43 : }
44 :
45 252 : nsCSSValue::nsCSSValue(int32_t aValue, nsCSSUnit aUnit)
46 252 : : mUnit(aUnit)
47 : {
48 252 : MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
49 : aUnit == eCSSUnit_EnumColor,
50 : "not an int value");
51 252 : if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
52 : aUnit == eCSSUnit_EnumColor) {
53 252 : mValue.mInt = aValue;
54 : }
55 : else {
56 0 : mUnit = eCSSUnit_Null;
57 0 : mValue.mInt = 0;
58 : }
59 252 : }
60 :
61 783 : nsCSSValue::nsCSSValue(float aValue, nsCSSUnit aUnit)
62 783 : : mUnit(aUnit)
63 : {
64 783 : MOZ_ASSERT(eCSSUnit_Percent <= aUnit, "not a float value");
65 783 : if (eCSSUnit_Percent <= aUnit) {
66 783 : mValue.mFloat = aValue;
67 783 : MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
68 : }
69 : else {
70 0 : mUnit = eCSSUnit_Null;
71 0 : mValue.mInt = 0;
72 : }
73 783 : }
74 :
75 0 : nsCSSValue::nsCSSValue(const nsString& aValue, nsCSSUnit aUnit)
76 0 : : mUnit(aUnit)
77 : {
78 0 : MOZ_ASSERT(UnitHasStringValue(), "not a string value");
79 0 : if (UnitHasStringValue()) {
80 0 : mValue.mString = BufferFromString(aValue).take();
81 : }
82 : else {
83 0 : mUnit = eCSSUnit_Null;
84 0 : mValue.mInt = 0;
85 : }
86 0 : }
87 :
88 0 : nsCSSValue::nsCSSValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
89 0 : : mUnit(aUnit)
90 : {
91 0 : MOZ_ASSERT(UnitHasArrayValue(), "bad unit");
92 0 : mValue.mArray = aValue;
93 0 : mValue.mArray->AddRef();
94 0 : }
95 :
96 0 : nsCSSValue::nsCSSValue(mozilla::css::URLValue* aValue)
97 0 : : mUnit(eCSSUnit_URL)
98 : {
99 0 : mValue.mURL = aValue;
100 0 : mValue.mURL->AddRef();
101 0 : }
102 :
103 0 : nsCSSValue::nsCSSValue(mozilla::css::ImageValue* aValue)
104 0 : : mUnit(eCSSUnit_Image)
105 : {
106 0 : mValue.mImage = aValue;
107 0 : mValue.mImage->AddRef();
108 0 : }
109 :
110 0 : nsCSSValue::nsCSSValue(nsCSSValueGradient* aValue)
111 0 : : mUnit(eCSSUnit_Gradient)
112 : {
113 0 : mValue.mGradient = aValue;
114 0 : mValue.mGradient->AddRef();
115 0 : }
116 :
117 0 : nsCSSValue::nsCSSValue(nsCSSValueTokenStream* aValue)
118 0 : : mUnit(eCSSUnit_TokenStream)
119 : {
120 0 : mValue.mTokenStream = aValue;
121 0 : mValue.mTokenStream->AddRef();
122 0 : }
123 :
124 0 : nsCSSValue::nsCSSValue(mozilla::css::GridTemplateAreasValue* aValue)
125 0 : : mUnit(eCSSUnit_GridTemplateAreas)
126 : {
127 0 : mValue.mGridTemplateAreas = aValue;
128 0 : mValue.mGridTemplateAreas->AddRef();
129 0 : }
130 :
131 0 : nsCSSValue::nsCSSValue(css::FontFamilyListRefCnt* aValue)
132 0 : : mUnit(eCSSUnit_FontFamilyList)
133 : {
134 0 : mValue.mFontFamilyList = aValue;
135 0 : mValue.mFontFamilyList->AddRef();
136 0 : }
137 :
138 45268 : nsCSSValue::nsCSSValue(const nsCSSValue& aCopy)
139 45268 : : mUnit(aCopy.mUnit)
140 : {
141 45268 : if (mUnit <= eCSSUnit_DummyInherit) {
142 : // nothing to do, but put this important case first
143 : }
144 38021 : else if (eCSSUnit_Percent <= mUnit) {
145 17951 : mValue.mFloat = aCopy.mValue.mFloat;
146 17951 : MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
147 : }
148 20070 : else if (UnitHasStringValue()) {
149 2146 : mValue.mString = aCopy.mValue.mString;
150 2146 : mValue.mString->AddRef();
151 : }
152 17924 : else if (eCSSUnit_Integer <= mUnit && mUnit <= eCSSUnit_EnumColor) {
153 9874 : mValue.mInt = aCopy.mValue.mInt;
154 : }
155 8050 : else if (IsIntegerColorUnit()) {
156 358 : mValue.mColor = aCopy.mValue.mColor;
157 : }
158 7692 : else if (IsFloatColorUnit()) {
159 461 : mValue.mFloatColor = aCopy.mValue.mFloatColor;
160 461 : mValue.mFloatColor->AddRef();
161 : }
162 7231 : else if (eCSSUnit_ComplexColor == mUnit) {
163 0 : mValue.mComplexColor = aCopy.mValue.mComplexColor;
164 0 : mValue.mComplexColor->AddRef();
165 : }
166 7231 : else if (UnitHasArrayValue()) {
167 673 : mValue.mArray = aCopy.mValue.mArray;
168 673 : mValue.mArray->AddRef();
169 : }
170 6558 : else if (eCSSUnit_URL == mUnit) {
171 765 : mValue.mURL = aCopy.mValue.mURL;
172 765 : mValue.mURL->AddRef();
173 : }
174 5793 : else if (eCSSUnit_Image == mUnit) {
175 117 : mValue.mImage = aCopy.mValue.mImage;
176 117 : mValue.mImage->AddRef();
177 : }
178 5676 : else if (eCSSUnit_Gradient == mUnit) {
179 5 : mValue.mGradient = aCopy.mValue.mGradient;
180 5 : mValue.mGradient->AddRef();
181 : }
182 5671 : else if (eCSSUnit_TokenStream == mUnit) {
183 1489 : mValue.mTokenStream = aCopy.mValue.mTokenStream;
184 1489 : mValue.mTokenStream->AddRef();
185 : }
186 4182 : else if (eCSSUnit_Pair == mUnit) {
187 367 : mValue.mPair = aCopy.mValue.mPair;
188 367 : mValue.mPair->AddRef();
189 : }
190 3815 : else if (eCSSUnit_Triplet == mUnit) {
191 32 : mValue.mTriplet = aCopy.mValue.mTriplet;
192 32 : mValue.mTriplet->AddRef();
193 : }
194 3783 : else if (eCSSUnit_Rect == mUnit) {
195 1002 : mValue.mRect = aCopy.mValue.mRect;
196 1002 : mValue.mRect->AddRef();
197 : }
198 2781 : else if (eCSSUnit_List == mUnit) {
199 2342 : mValue.mList = aCopy.mValue.mList;
200 2342 : mValue.mList->AddRef();
201 : }
202 439 : else if (eCSSUnit_ListDep == mUnit) {
203 0 : mValue.mListDependent = aCopy.mValue.mListDependent;
204 : }
205 439 : else if (eCSSUnit_SharedList == mUnit) {
206 96 : mValue.mSharedList = aCopy.mValue.mSharedList;
207 96 : mValue.mSharedList->AddRef();
208 : }
209 343 : else if (eCSSUnit_PairList == mUnit) {
210 251 : mValue.mPairList = aCopy.mValue.mPairList;
211 251 : mValue.mPairList->AddRef();
212 : }
213 92 : else if (eCSSUnit_PairListDep == mUnit) {
214 0 : mValue.mPairListDependent = aCopy.mValue.mPairListDependent;
215 : }
216 92 : else if (eCSSUnit_GridTemplateAreas == mUnit) {
217 0 : mValue.mGridTemplateAreas = aCopy.mValue.mGridTemplateAreas;
218 0 : mValue.mGridTemplateAreas->AddRef();
219 : }
220 92 : else if (eCSSUnit_FontFamilyList == mUnit) {
221 16 : mValue.mFontFamilyList = aCopy.mValue.mFontFamilyList;
222 16 : mValue.mFontFamilyList->AddRef();
223 : }
224 76 : else if (eCSSUnit_AtomIdent == mUnit) {
225 76 : mValue.mAtom = aCopy.mValue.mAtom;
226 76 : mValue.mAtom->AddRef();
227 : }
228 : else {
229 0 : MOZ_ASSERT(false, "unknown unit");
230 : }
231 45268 : }
232 :
233 42291 : nsCSSValue& nsCSSValue::operator=(const nsCSSValue& aCopy)
234 : {
235 42291 : if (this != &aCopy) {
236 42291 : Reset();
237 42291 : new (this) nsCSSValue(aCopy);
238 : }
239 42291 : return *this;
240 : }
241 :
242 : nsCSSValue&
243 49 : nsCSSValue::operator=(nsCSSValue&& aOther)
244 : {
245 49 : MOZ_ASSERT(this != &aOther, "Self assigment with rvalue reference");
246 :
247 49 : Reset();
248 49 : mUnit = aOther.mUnit;
249 49 : mValue = aOther.mValue;
250 49 : aOther.mUnit = eCSSUnit_Null;
251 :
252 49 : return *this;
253 : }
254 :
255 14503 : bool nsCSSValue::operator==(const nsCSSValue& aOther) const
256 : {
257 14503 : MOZ_ASSERT(mUnit != eCSSUnit_ListDep &&
258 : aOther.mUnit != eCSSUnit_ListDep &&
259 : mUnit != eCSSUnit_PairListDep &&
260 : aOther.mUnit != eCSSUnit_PairListDep,
261 : "don't use operator== with dependent lists");
262 :
263 14503 : if (mUnit == aOther.mUnit) {
264 1510 : if (mUnit <= eCSSUnit_DummyInherit) {
265 22 : return true;
266 : }
267 1488 : else if (UnitHasStringValue()) {
268 0 : return (NS_strcmp(GetBufferValue(mValue.mString),
269 0 : GetBufferValue(aOther.mValue.mString)) == 0);
270 : }
271 1488 : else if ((eCSSUnit_Integer <= mUnit) && (mUnit <= eCSSUnit_EnumColor)) {
272 21 : return mValue.mInt == aOther.mValue.mInt;
273 : }
274 1467 : else if (IsIntegerColorUnit()) {
275 48 : return mValue.mColor == aOther.mValue.mColor;
276 : }
277 1419 : else if (IsFloatColorUnit()) {
278 0 : return *mValue.mFloatColor == *aOther.mValue.mFloatColor;
279 : }
280 1419 : else if (eCSSUnit_ComplexColor == mUnit) {
281 0 : return *mValue.mComplexColor == *aOther.mValue.mComplexColor;
282 : }
283 1419 : else if (UnitHasArrayValue()) {
284 0 : return *mValue.mArray == *aOther.mValue.mArray;
285 : }
286 1419 : else if (eCSSUnit_URL == mUnit) {
287 0 : return mValue.mURL->Equals(*aOther.mValue.mURL);
288 : }
289 1419 : else if (eCSSUnit_Image == mUnit) {
290 0 : return mValue.mImage->Equals(*aOther.mValue.mImage);
291 : }
292 1419 : else if (eCSSUnit_Gradient == mUnit) {
293 0 : return *mValue.mGradient == *aOther.mValue.mGradient;
294 : }
295 1419 : else if (eCSSUnit_TokenStream == mUnit) {
296 0 : return *mValue.mTokenStream == *aOther.mValue.mTokenStream;
297 : }
298 1419 : else if (eCSSUnit_Pair == mUnit) {
299 0 : return *mValue.mPair == *aOther.mValue.mPair;
300 : }
301 1419 : else if (eCSSUnit_Triplet == mUnit) {
302 0 : return *mValue.mTriplet == *aOther.mValue.mTriplet;
303 : }
304 1419 : else if (eCSSUnit_Rect == mUnit) {
305 2 : return *mValue.mRect == *aOther.mValue.mRect;
306 : }
307 1417 : else if (eCSSUnit_List == mUnit) {
308 5 : return nsCSSValueList::Equal(mValue.mList, aOther.mValue.mList);
309 : }
310 1412 : else if (eCSSUnit_SharedList == mUnit) {
311 0 : return *mValue.mSharedList == *aOther.mValue.mSharedList;
312 : }
313 1412 : else if (eCSSUnit_PairList == mUnit) {
314 3 : return nsCSSValuePairList::Equal(mValue.mPairList,
315 6 : aOther.mValue.mPairList);
316 : }
317 1409 : else if (eCSSUnit_GridTemplateAreas == mUnit) {
318 0 : return *mValue.mGridTemplateAreas == *aOther.mValue.mGridTemplateAreas;
319 : }
320 1409 : else if (eCSSUnit_FontFamilyList == mUnit) {
321 0 : return *mValue.mFontFamilyList == *aOther.mValue.mFontFamilyList;
322 : }
323 1409 : else if (eCSSUnit_AtomIdent == mUnit) {
324 0 : return mValue.mAtom == aOther.mValue.mAtom;
325 : }
326 : else {
327 1409 : return mValue.mFloat == aOther.mValue.mFloat;
328 : }
329 : }
330 12993 : return false;
331 : }
332 :
333 : double
334 0 : nsCSSValue::GetAngleValueInRadians() const
335 : {
336 0 : double angle = GetFloatValue();
337 :
338 0 : switch (GetUnit()) {
339 0 : case eCSSUnit_Radian: return angle;
340 0 : case eCSSUnit_Turn: return angle * 2 * M_PI;
341 0 : case eCSSUnit_Degree: return angle * M_PI / 180.0;
342 0 : case eCSSUnit_Grad: return angle * M_PI / 200.0;
343 :
344 : default:
345 0 : MOZ_ASSERT(false, "unrecognized angular unit");
346 : return 0.0;
347 : }
348 : }
349 :
350 : double
351 0 : nsCSSValue::GetAngleValueInDegrees() const
352 : {
353 0 : double angle = GetFloatValue();
354 :
355 0 : switch (GetUnit()) {
356 0 : case eCSSUnit_Degree: return angle;
357 0 : case eCSSUnit_Grad: return angle * 0.9; // grad / 400 * 360
358 0 : case eCSSUnit_Radian: return angle * 180.0 / M_PI; // rad / 2pi * 360
359 0 : case eCSSUnit_Turn: return angle * 360.0;
360 :
361 : default:
362 0 : MOZ_ASSERT(false, "unrecognized angular unit");
363 : return 0.0;
364 : }
365 : }
366 :
367 242 : imgRequestProxy* nsCSSValue::GetImageValue(nsIDocument* aDocument) const
368 : {
369 242 : MOZ_ASSERT(mUnit == eCSSUnit_Image, "not an Image value");
370 242 : return mValue.mImage->mRequests.GetWeak(aDocument);
371 : }
372 :
373 : already_AddRefed<imgRequestProxy>
374 141 : nsCSSValue::GetPossiblyStaticImageValue(nsIDocument* aDocument,
375 : nsPresContext* aPresContext) const
376 : {
377 141 : imgRequestProxy* req = GetImageValue(aDocument);
378 141 : if (aPresContext->IsDynamic()) {
379 141 : return do_AddRef(req);
380 : }
381 0 : return nsContentUtils::GetStaticRequest(req);
382 : }
383 :
384 0 : nscoord nsCSSValue::GetFixedLength(nsPresContext* aPresContext) const
385 : {
386 0 : MOZ_ASSERT(mUnit == eCSSUnit_PhysicalMillimeter,
387 : "not a fixed length unit");
388 :
389 0 : float inches = mValue.mFloat / MM_PER_INCH_FLOAT;
390 0 : return NSToCoordFloorClamped(inches *
391 0 : float(aPresContext->DeviceContext()->AppUnitsPerPhysicalInch()));
392 : }
393 :
394 2495 : nscoord nsCSSValue::GetPixelLength() const
395 : {
396 2495 : MOZ_ASSERT(IsPixelLengthUnit(), "not a fixed length unit");
397 :
398 : double scaleFactor;
399 2495 : switch (mUnit) {
400 2495 : case eCSSUnit_Pixel: return nsPresContext::CSSPixelsToAppUnits(mValue.mFloat);
401 0 : case eCSSUnit_Pica: scaleFactor = 16.0; break;
402 0 : case eCSSUnit_Point: scaleFactor = 4/3.0; break;
403 0 : case eCSSUnit_Inch: scaleFactor = 96.0; break;
404 0 : case eCSSUnit_Millimeter: scaleFactor = 96/25.4; break;
405 0 : case eCSSUnit_Centimeter: scaleFactor = 96/2.54; break;
406 0 : case eCSSUnit_Quarter: scaleFactor = 96/101.6; break;
407 : default:
408 0 : NS_ERROR("should never get here");
409 0 : return 0;
410 : }
411 0 : return nsPresContext::CSSPixelsToAppUnits(float(mValue.mFloat*scaleFactor));
412 : }
413 :
414 : // Assert against resetting non-trivial CSS values from the parallel Servo
415 : // traversal, since the refcounts aren't thread-safe.
416 : // Note that the caller might be an OMTA thread, which is allowed to operate off
417 : // main thread because it owns all of the corresponding nsCSSValues and any that
418 : // they might be sharing members with.
419 : #define DO_RELEASE(member) { \
420 : MOZ_ASSERT(NS_IsInCompositorThread() || !ServoStyleSet::IsInServoTraversal()); \
421 : mValue.member->Release(); \
422 : }
423 :
424 44454 : void nsCSSValue::DoReset()
425 : {
426 44454 : if (UnitHasStringValue()) {
427 2448 : mValue.mString->Release();
428 42006 : } else if (IsFloatColorUnit()) {
429 522 : DO_RELEASE(mFloatColor);
430 41484 : } else if (eCSSUnit_ComplexColor == mUnit) {
431 0 : DO_RELEASE(mComplexColor);
432 41484 : } else if (UnitHasArrayValue()) {
433 1248 : DO_RELEASE(mArray);
434 40236 : } else if (eCSSUnit_URL == mUnit) {
435 807 : DO_RELEASE(mURL);
436 39429 : } else if (eCSSUnit_Image == mUnit) {
437 117 : DO_RELEASE(mImage);
438 39312 : } else if (eCSSUnit_Gradient == mUnit) {
439 8 : DO_RELEASE(mGradient);
440 39304 : } else if (eCSSUnit_TokenStream == mUnit) {
441 1496 : DO_RELEASE(mTokenStream);
442 37808 : } else if (eCSSUnit_Pair == mUnit) {
443 456 : DO_RELEASE(mPair);
444 37352 : } else if (eCSSUnit_Triplet == mUnit) {
445 32 : DO_RELEASE(mTriplet);
446 37320 : } else if (eCSSUnit_Rect == mUnit) {
447 1272 : DO_RELEASE(mRect);
448 36048 : } else if (eCSSUnit_List == mUnit) {
449 2927 : DO_RELEASE(mList);
450 33121 : } else if (eCSSUnit_SharedList == mUnit) {
451 96 : DO_RELEASE(mSharedList);
452 33025 : } else if (eCSSUnit_PairList == mUnit) {
453 277 : DO_RELEASE(mPairList);
454 32748 : } else if (eCSSUnit_GridTemplateAreas == mUnit) {
455 0 : DO_RELEASE(mGridTemplateAreas);
456 32748 : } else if (eCSSUnit_FontFamilyList == mUnit) {
457 16 : DO_RELEASE(mFontFamilyList);
458 32732 : } else if (eCSSUnit_AtomIdent == mUnit) {
459 76 : DO_RELEASE(mAtom);
460 : }
461 44454 : mUnit = eCSSUnit_Null;
462 44454 : }
463 :
464 : #undef DO_RELEASE
465 :
466 4507 : void nsCSSValue::SetIntValue(int32_t aValue, nsCSSUnit aUnit)
467 : {
468 4507 : MOZ_ASSERT(aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
469 : aUnit == eCSSUnit_EnumColor,
470 : "not an int value");
471 4507 : Reset();
472 4507 : if (aUnit == eCSSUnit_Integer || aUnit == eCSSUnit_Enumerated ||
473 : aUnit == eCSSUnit_EnumColor) {
474 4507 : mUnit = aUnit;
475 4507 : mValue.mInt = aValue;
476 : }
477 4507 : }
478 :
479 321 : void nsCSSValue::SetPercentValue(float aValue)
480 : {
481 321 : Reset();
482 321 : mUnit = eCSSUnit_Percent;
483 321 : mValue.mFloat = aValue;
484 321 : MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
485 321 : }
486 :
487 5700 : void nsCSSValue::SetFloatValue(float aValue, nsCSSUnit aUnit)
488 : {
489 5700 : MOZ_ASSERT(IsFloatUnit(aUnit), "not a float value");
490 5700 : Reset();
491 5700 : if (IsFloatUnit(aUnit)) {
492 5700 : mUnit = aUnit;
493 5700 : mValue.mFloat = aValue;
494 5700 : MOZ_ASSERT(!mozilla::IsNaN(mValue.mFloat));
495 : }
496 5700 : }
497 :
498 2291 : void nsCSSValue::SetStringValue(const nsString& aValue,
499 : nsCSSUnit aUnit)
500 : {
501 2291 : Reset();
502 2291 : mUnit = aUnit;
503 2291 : MOZ_ASSERT(UnitHasStringValue(), "not a string unit");
504 2291 : if (UnitHasStringValue()) {
505 2291 : mValue.mString = BufferFromString(aValue).take();
506 : } else
507 0 : mUnit = eCSSUnit_Null;
508 2291 : }
509 :
510 : void
511 76 : nsCSSValue::SetAtomIdentValue(already_AddRefed<nsIAtom> aValue)
512 : {
513 76 : Reset();
514 76 : mUnit = eCSSUnit_AtomIdent;
515 76 : mValue.mAtom = aValue.take();
516 76 : }
517 :
518 94 : void nsCSSValue::SetColorValue(nscolor aValue)
519 : {
520 94 : SetIntegerColorValue(aValue, eCSSUnit_RGBAColor);
521 94 : }
522 :
523 :
524 :
525 546 : void nsCSSValue::SetIntegerColorValue(nscolor aValue, nsCSSUnit aUnit)
526 : {
527 546 : Reset();
528 546 : mUnit = aUnit;
529 546 : MOZ_ASSERT(IsIntegerColorUnit(), "bad unit");
530 546 : mValue.mColor = aValue;
531 546 : }
532 :
533 0 : void nsCSSValue::SetIntegerCoordValue(nscoord aValue)
534 : {
535 0 : SetFloatValue(nsPresContext::AppUnitsToFloatCSSPixels(aValue),
536 0 : eCSSUnit_Pixel);
537 0 : }
538 :
539 171 : void nsCSSValue::SetFloatColorValue(float aComponent1,
540 : float aComponent2,
541 : float aComponent3,
542 : float aAlpha,
543 : nsCSSUnit aUnit)
544 : {
545 171 : Reset();
546 171 : mUnit = aUnit;
547 171 : MOZ_ASSERT(IsFloatColorUnit(), "bad unit");
548 171 : mValue.mFloatColor =
549 171 : new nsCSSValueFloatColor(aComponent1, aComponent2, aComponent3, aAlpha);
550 171 : mValue.mFloatColor->AddRef();
551 171 : }
552 :
553 : void
554 0 : nsCSSValue::SetRGBAColorValue(const RGBAColorData& aValue)
555 : {
556 0 : SetFloatColorValue(aValue.mR, aValue.mG, aValue.mB,
557 0 : aValue.mA, eCSSUnit_PercentageRGBAColor);
558 0 : }
559 :
560 : void
561 0 : nsCSSValue::SetComplexColorValue(already_AddRefed<ComplexColorValue> aValue)
562 : {
563 0 : Reset();
564 0 : mUnit = eCSSUnit_ComplexColor;
565 0 : mValue.mComplexColor = aValue.take();
566 0 : }
567 :
568 1038 : void nsCSSValue::SetArrayValue(nsCSSValue::Array* aValue, nsCSSUnit aUnit)
569 : {
570 1038 : Reset();
571 1038 : mUnit = aUnit;
572 1038 : MOZ_ASSERT(UnitHasArrayValue(), "bad unit");
573 1038 : mValue.mArray = aValue;
574 1038 : mValue.mArray->AddRef();
575 1038 : }
576 :
577 667 : void nsCSSValue::SetURLValue(mozilla::css::URLValue* aValue)
578 : {
579 667 : Reset();
580 667 : mUnit = eCSSUnit_URL;
581 667 : mValue.mURL = aValue;
582 667 : mValue.mURL->AddRef();
583 667 : }
584 :
585 40 : void nsCSSValue::SetImageValue(mozilla::css::ImageValue* aValue)
586 : {
587 40 : Reset();
588 40 : mUnit = eCSSUnit_Image;
589 40 : mValue.mImage = aValue;
590 40 : mValue.mImage->AddRef();
591 40 : }
592 :
593 45 : void nsCSSValue::SetGradientValue(nsCSSValueGradient* aValue)
594 : {
595 45 : Reset();
596 45 : mUnit = eCSSUnit_Gradient;
597 45 : mValue.mGradient = aValue;
598 45 : mValue.mGradient->AddRef();
599 45 : }
600 :
601 606 : void nsCSSValue::SetTokenStreamValue(nsCSSValueTokenStream* aValue)
602 : {
603 606 : Reset();
604 606 : mUnit = eCSSUnit_TokenStream;
605 606 : mValue.mTokenStream = aValue;
606 606 : mValue.mTokenStream->AddRef();
607 606 : }
608 :
609 0 : void nsCSSValue::SetGridTemplateAreas(mozilla::css::GridTemplateAreasValue* aValue)
610 : {
611 0 : Reset();
612 0 : mUnit = eCSSUnit_GridTemplateAreas;
613 0 : mValue.mGridTemplateAreas = aValue;
614 0 : mValue.mGridTemplateAreas->AddRef();
615 0 : }
616 :
617 16 : void nsCSSValue::SetFontFamilyListValue(css::FontFamilyListRefCnt* aValue)
618 : {
619 16 : Reset();
620 16 : mUnit = eCSSUnit_FontFamilyList;
621 16 : mValue.mFontFamilyList = aValue;
622 16 : mValue.mFontFamilyList->AddRef();
623 16 : }
624 :
625 241 : void nsCSSValue::SetPairValue(const nsCSSValuePair* aValue)
626 : {
627 : // pairs should not be used for null/inherit/initial values
628 241 : MOZ_ASSERT(aValue &&
629 : aValue->mXValue.GetUnit() != eCSSUnit_Null &&
630 : aValue->mYValue.GetUnit() != eCSSUnit_Null &&
631 : aValue->mXValue.GetUnit() != eCSSUnit_Inherit &&
632 : aValue->mYValue.GetUnit() != eCSSUnit_Inherit &&
633 : aValue->mXValue.GetUnit() != eCSSUnit_Initial &&
634 : aValue->mYValue.GetUnit() != eCSSUnit_Initial &&
635 : aValue->mXValue.GetUnit() != eCSSUnit_Unset &&
636 : aValue->mYValue.GetUnit() != eCSSUnit_Unset,
637 : "missing or inappropriate pair value");
638 241 : Reset();
639 241 : mUnit = eCSSUnit_Pair;
640 241 : mValue.mPair = new nsCSSValuePair_heap(aValue->mXValue, aValue->mYValue);
641 241 : mValue.mPair->AddRef();
642 241 : }
643 :
644 62 : void nsCSSValue::SetPairValue(const nsCSSValue& xValue,
645 : const nsCSSValue& yValue)
646 : {
647 62 : MOZ_ASSERT(xValue.GetUnit() != eCSSUnit_Null &&
648 : yValue.GetUnit() != eCSSUnit_Null &&
649 : xValue.GetUnit() != eCSSUnit_Inherit &&
650 : yValue.GetUnit() != eCSSUnit_Inherit &&
651 : xValue.GetUnit() != eCSSUnit_Initial &&
652 : yValue.GetUnit() != eCSSUnit_Initial &&
653 : xValue.GetUnit() != eCSSUnit_Unset &&
654 : yValue.GetUnit() != eCSSUnit_Unset,
655 : "inappropriate pair value");
656 62 : Reset();
657 62 : mUnit = eCSSUnit_Pair;
658 62 : mValue.mPair = new nsCSSValuePair_heap(xValue, yValue);
659 62 : mValue.mPair->AddRef();
660 62 : }
661 :
662 0 : void nsCSSValue::SetTripletValue(const nsCSSValueTriplet* aValue)
663 : {
664 : // triplet should not be used for null/inherit/initial values
665 0 : MOZ_ASSERT(aValue &&
666 : aValue->mXValue.GetUnit() != eCSSUnit_Null &&
667 : aValue->mYValue.GetUnit() != eCSSUnit_Null &&
668 : aValue->mZValue.GetUnit() != eCSSUnit_Null &&
669 : aValue->mXValue.GetUnit() != eCSSUnit_Inherit &&
670 : aValue->mYValue.GetUnit() != eCSSUnit_Inherit &&
671 : aValue->mZValue.GetUnit() != eCSSUnit_Inherit &&
672 : aValue->mXValue.GetUnit() != eCSSUnit_Initial &&
673 : aValue->mYValue.GetUnit() != eCSSUnit_Initial &&
674 : aValue->mZValue.GetUnit() != eCSSUnit_Initial &&
675 : aValue->mXValue.GetUnit() != eCSSUnit_Unset &&
676 : aValue->mYValue.GetUnit() != eCSSUnit_Unset &&
677 : aValue->mZValue.GetUnit() != eCSSUnit_Unset,
678 : "missing or inappropriate triplet value");
679 0 : Reset();
680 0 : mUnit = eCSSUnit_Triplet;
681 0 : mValue.mTriplet = new nsCSSValueTriplet_heap(aValue->mXValue, aValue->mYValue, aValue->mZValue);
682 0 : mValue.mTriplet->AddRef();
683 0 : }
684 :
685 2 : void nsCSSValue::SetTripletValue(const nsCSSValue& xValue,
686 : const nsCSSValue& yValue,
687 : const nsCSSValue& zValue)
688 : {
689 : // Only allow Null for the z component
690 2 : MOZ_ASSERT(xValue.GetUnit() != eCSSUnit_Null &&
691 : yValue.GetUnit() != eCSSUnit_Null &&
692 : xValue.GetUnit() != eCSSUnit_Inherit &&
693 : yValue.GetUnit() != eCSSUnit_Inherit &&
694 : zValue.GetUnit() != eCSSUnit_Inherit &&
695 : xValue.GetUnit() != eCSSUnit_Initial &&
696 : yValue.GetUnit() != eCSSUnit_Initial &&
697 : zValue.GetUnit() != eCSSUnit_Initial &&
698 : xValue.GetUnit() != eCSSUnit_Unset &&
699 : yValue.GetUnit() != eCSSUnit_Unset &&
700 : zValue.GetUnit() != eCSSUnit_Unset,
701 : "inappropriate triplet value");
702 2 : Reset();
703 2 : mUnit = eCSSUnit_Triplet;
704 2 : mValue.mTriplet = new nsCSSValueTriplet_heap(xValue, yValue, zValue);
705 2 : mValue.mTriplet->AddRef();
706 2 : }
707 :
708 806 : nsCSSRect& nsCSSValue::SetRectValue()
709 : {
710 806 : Reset();
711 806 : mUnit = eCSSUnit_Rect;
712 806 : mValue.mRect = new nsCSSRect_heap;
713 806 : mValue.mRect->AddRef();
714 806 : return *mValue.mRect;
715 : }
716 :
717 1870 : nsCSSValueList* nsCSSValue::SetListValue()
718 : {
719 1870 : Reset();
720 1870 : mUnit = eCSSUnit_List;
721 1870 : mValue.mList = new nsCSSValueList_heap;
722 1870 : mValue.mList->AddRef();
723 1870 : return mValue.mList;
724 : }
725 :
726 80 : void nsCSSValue::SetSharedListValue(nsCSSValueSharedList* aList)
727 : {
728 80 : Reset();
729 80 : mUnit = eCSSUnit_SharedList;
730 80 : mValue.mSharedList = aList;
731 80 : mValue.mSharedList->AddRef();
732 80 : }
733 :
734 0 : void nsCSSValue::SetDependentListValue(nsCSSValueList* aList)
735 : {
736 0 : Reset();
737 0 : if (aList) {
738 0 : mUnit = eCSSUnit_ListDep;
739 0 : mValue.mListDependent = aList;
740 : }
741 0 : }
742 :
743 : void
744 0 : nsCSSValue::AdoptListValue(UniquePtr<nsCSSValueList> aValue)
745 : {
746 : // We have to copy the first element since for owned lists the first
747 : // element should be an nsCSSValueList_heap object.
748 0 : SetListValue();
749 0 : mValue.mList->mValue = Move(aValue->mValue);
750 0 : mValue.mList->mNext = aValue->mNext;
751 0 : aValue->mNext = nullptr;
752 0 : aValue.reset();
753 0 : }
754 :
755 228 : nsCSSValuePairList* nsCSSValue::SetPairListValue()
756 : {
757 228 : Reset();
758 228 : mUnit = eCSSUnit_PairList;
759 228 : mValue.mPairList = new nsCSSValuePairList_heap;
760 228 : mValue.mPairList->AddRef();
761 228 : return mValue.mPairList;
762 : }
763 :
764 0 : void nsCSSValue::SetDependentPairListValue(nsCSSValuePairList* aList)
765 : {
766 0 : Reset();
767 0 : if (aList) {
768 0 : mUnit = eCSSUnit_PairListDep;
769 0 : mValue.mPairListDependent = aList;
770 : }
771 0 : }
772 :
773 : void
774 0 : nsCSSValue::AdoptPairListValue(UniquePtr<nsCSSValuePairList> aValue)
775 : {
776 : // We have to copy the first element, since for owned pair lists, the first
777 : // element should be an nsCSSValuePairList_heap object.
778 0 : SetPairListValue();
779 0 : mValue.mPairList->mXValue = Move(aValue->mXValue);
780 0 : mValue.mPairList->mYValue = Move(aValue->mYValue);
781 0 : mValue.mPairList->mNext = aValue->mNext;
782 0 : aValue->mNext = nullptr;
783 0 : aValue.reset();
784 0 : }
785 :
786 211 : void nsCSSValue::SetAutoValue()
787 : {
788 211 : Reset();
789 211 : mUnit = eCSSUnit_Auto;
790 211 : }
791 :
792 434 : void nsCSSValue::SetInheritValue()
793 : {
794 434 : Reset();
795 434 : mUnit = eCSSUnit_Inherit;
796 434 : }
797 :
798 82 : void nsCSSValue::SetInitialValue()
799 : {
800 82 : Reset();
801 82 : mUnit = eCSSUnit_Initial;
802 82 : }
803 :
804 14 : void nsCSSValue::SetUnsetValue()
805 : {
806 14 : Reset();
807 14 : mUnit = eCSSUnit_Unset;
808 14 : }
809 :
810 837 : void nsCSSValue::SetNoneValue()
811 : {
812 837 : Reset();
813 837 : mUnit = eCSSUnit_None;
814 837 : }
815 :
816 106 : void nsCSSValue::SetAllValue()
817 : {
818 106 : Reset();
819 106 : mUnit = eCSSUnit_All;
820 106 : }
821 :
822 32 : void nsCSSValue::SetNormalValue()
823 : {
824 32 : Reset();
825 32 : mUnit = eCSSUnit_Normal;
826 32 : }
827 :
828 0 : void nsCSSValue::SetSystemFontValue()
829 : {
830 0 : Reset();
831 0 : mUnit = eCSSUnit_System_Font;
832 0 : }
833 :
834 0 : void nsCSSValue::SetDummyValue()
835 : {
836 0 : Reset();
837 0 : mUnit = eCSSUnit_Dummy;
838 0 : }
839 :
840 0 : void nsCSSValue::SetDummyInheritValue()
841 : {
842 0 : Reset();
843 0 : mUnit = eCSSUnit_DummyInherit;
844 0 : }
845 :
846 0 : void nsCSSValue::SetCalcValue(const nsStyleCoord::CalcValue* aCalc)
847 : {
848 0 : RefPtr<nsCSSValue::Array> arr = nsCSSValue::Array::Create(1);
849 0 : if (!aCalc->mHasPercent) {
850 0 : arr->Item(0).SetIntegerCoordValue(aCalc->mLength);
851 : } else {
852 0 : nsCSSValue::Array *arr2 = nsCSSValue::Array::Create(2);
853 0 : arr->Item(0).SetArrayValue(arr2, eCSSUnit_Calc_Plus);
854 0 : arr2->Item(0).SetIntegerCoordValue(aCalc->mLength);
855 0 : arr2->Item(1).SetPercentValue(aCalc->mPercent);
856 : }
857 :
858 0 : SetArrayValue(arr, eCSSUnit_Calc);
859 0 : }
860 :
861 : nsStyleCoord::CalcValue
862 0 : nsCSSValue::GetCalcValue() const
863 : {
864 0 : MOZ_ASSERT(mUnit == eCSSUnit_Calc,
865 : "The unit should be eCSSUnit_Calc");
866 :
867 0 : const nsCSSValue::Array* array = GetArrayValue();
868 0 : MOZ_ASSERT(array->Count() == 1,
869 : "There should be a 1-length array");
870 :
871 0 : const nsCSSValue& rootValue = array->Item(0);
872 :
873 : nsStyleCoord::CalcValue result;
874 :
875 0 : if (rootValue.GetUnit() == eCSSUnit_Pixel) {
876 0 : result.mLength = rootValue.GetFloatValue();
877 0 : result.mPercent = 0.0f;
878 0 : result.mHasPercent = false;
879 : } else {
880 0 : MOZ_ASSERT(rootValue.GetUnit() == eCSSUnit_Calc_Plus,
881 : "Calc unit should be eCSSUnit_Calc_Plus");
882 :
883 0 : const nsCSSValue::Array *calcPlusArray = rootValue.GetArrayValue();
884 0 : MOZ_ASSERT(calcPlusArray->Count() == 2,
885 : "eCSSUnit_Calc_Plus should have a 2-length array");
886 :
887 0 : const nsCSSValue& length = calcPlusArray->Item(0);
888 0 : const nsCSSValue& percent = calcPlusArray->Item(1);
889 0 : MOZ_ASSERT(length.GetUnit() == eCSSUnit_Pixel,
890 : "The first value should be eCSSUnit_Pixel");
891 0 : MOZ_ASSERT(percent.GetUnit() == eCSSUnit_Percent,
892 : "The first value should be eCSSUnit_Percent");
893 0 : result.mLength = length.GetFloatValue();
894 0 : result.mPercent = percent.GetPercentValue();
895 0 : result.mHasPercent = true;
896 : }
897 :
898 0 : return result;
899 : }
900 :
901 40 : void nsCSSValue::StartImageLoad(nsIDocument* aDocument) const
902 : {
903 40 : MOZ_ASSERT(eCSSUnit_URL == mUnit, "Not a URL value!");
904 : mozilla::css::ImageValue* image =
905 40 : new mozilla::css::ImageValue(mValue.mURL->GetURI(),
906 40 : mValue.mURL->mString,
907 80 : do_AddRef(mValue.mURL->mExtraData),
908 120 : aDocument);
909 :
910 40 : nsCSSValue* writable = const_cast<nsCSSValue*>(this);
911 40 : writable->SetImageValue(image);
912 40 : }
913 :
914 258 : nscolor nsCSSValue::GetColorValue() const
915 : {
916 258 : MOZ_ASSERT(IsNumericColorUnit(), "not a color value");
917 258 : if (IsFloatColorUnit()) {
918 59 : return mValue.mFloatColor->GetColorValue(mUnit);
919 : }
920 199 : return mValue.mColor;
921 : }
922 :
923 0 : bool nsCSSValue::IsNonTransparentColor() const
924 : {
925 : // We have the value in the form it was specified in at this point, so we
926 : // have to look for both the keyword 'transparent' and its equivalent in
927 : // rgba notation.
928 0 : nsDependentString buf;
929 : return
930 0 : (IsIntegerColorUnit() && NS_GET_A(GetColorValue()) > 0) ||
931 0 : (IsFloatColorUnit() && mValue.mFloatColor->IsNonTransparentColor()) ||
932 0 : (mUnit == eCSSUnit_Ident &&
933 0 : !nsGkAtoms::transparent->Equals(GetStringValue(buf))) ||
934 0 : (mUnit == eCSSUnit_EnumColor);
935 : }
936 :
937 : nsCSSValue::Array*
938 141 : nsCSSValue::InitFunction(nsCSSKeyword aFunctionId, uint32_t aNumArgs)
939 : {
940 282 : RefPtr<nsCSSValue::Array> func = Array::Create(aNumArgs + 1);
941 141 : func->Item(0).SetIntValue(aFunctionId, eCSSUnit_Enumerated);
942 141 : SetArrayValue(func, eCSSUnit_Function);
943 282 : return func;
944 : }
945 :
946 : bool
947 116 : nsCSSValue::EqualsFunction(nsCSSKeyword aFunctionId) const
948 : {
949 116 : if (mUnit != eCSSUnit_Function) {
950 110 : return false;
951 : }
952 :
953 6 : nsCSSValue::Array* func = mValue.mArray;
954 6 : MOZ_ASSERT(func && func->Count() >= 1 &&
955 : func->Item(0).GetUnit() == eCSSUnit_Enumerated,
956 : "illegally structured function value");
957 :
958 6 : nsCSSKeyword thisFunctionId = func->Item(0).GetKeywordValue();
959 6 : return thisFunctionId == aFunctionId;
960 : }
961 :
962 : // static
963 : already_AddRefed<nsStringBuffer>
964 2291 : nsCSSValue::BufferFromString(const nsString& aValue)
965 : {
966 4582 : RefPtr<nsStringBuffer> buffer = nsStringBuffer::FromString(aValue);
967 2291 : if (buffer) {
968 0 : return buffer.forget();
969 : }
970 :
971 2291 : nsString::size_type length = aValue.Length();
972 :
973 : // NOTE: Alloc prouduces a new, already-addref'd (refcnt = 1) buffer.
974 : // NOTE: String buffer allocation is currently fallible.
975 2291 : size_t sz = (length + 1) * sizeof(char16_t);
976 2291 : buffer = nsStringBuffer::Alloc(sz);
977 2291 : if (MOZ_UNLIKELY(!buffer)) {
978 0 : NS_ABORT_OOM(sz);
979 : }
980 :
981 2291 : char16_t* data = static_cast<char16_t*>(buffer->Data());
982 2291 : nsCharTraits<char16_t>::copy(data, aValue.get(), length);
983 : // Null-terminate.
984 2291 : data[length] = 0;
985 2291 : return buffer.forget();
986 : }
987 :
988 : void
989 41 : nsCSSValue::AtomizeIdentValue()
990 : {
991 41 : MOZ_ASSERT(mUnit == eCSSUnit_Ident);
992 82 : nsCOMPtr<nsIAtom> atom = NS_Atomize(GetStringBufferValue());
993 41 : Reset();
994 41 : mUnit = eCSSUnit_AtomIdent;
995 41 : mValue.mAtom = atom.forget().take();
996 41 : }
997 :
998 : namespace {
999 :
1000 : struct CSSValueSerializeCalcOps {
1001 0 : CSSValueSerializeCalcOps(nsCSSPropertyID aProperty, nsAString& aResult,
1002 : nsCSSValue::Serialization aSerialization)
1003 0 : : mProperty(aProperty),
1004 : mResult(aResult),
1005 0 : mValueSerialization(aSerialization)
1006 : {
1007 0 : }
1008 :
1009 : typedef nsCSSValue input_type;
1010 : typedef nsCSSValue::Array input_array_type;
1011 :
1012 0 : static nsCSSUnit GetUnit(const input_type& aValue) {
1013 0 : return aValue.GetUnit();
1014 : }
1015 :
1016 0 : void Append(const char* aString)
1017 : {
1018 0 : mResult.AppendASCII(aString);
1019 0 : }
1020 :
1021 0 : void AppendLeafValue(const input_type& aValue)
1022 : {
1023 0 : MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Percent ||
1024 : aValue.IsLengthUnit() ||
1025 : aValue.GetUnit() == eCSSUnit_Number,
1026 : "unexpected unit");
1027 0 : aValue.AppendToString(mProperty, mResult, mValueSerialization);
1028 0 : }
1029 :
1030 0 : void AppendCoefficient(const input_type& aValue)
1031 : {
1032 0 : MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Number, "unexpected unit");
1033 0 : aValue.AppendToString(mProperty, mResult, mValueSerialization);
1034 0 : }
1035 :
1036 : private:
1037 : nsCSSPropertyID mProperty;
1038 : nsAString &mResult;
1039 : nsCSSValue::Serialization mValueSerialization;
1040 : };
1041 :
1042 : } // namespace
1043 :
1044 : void
1045 0 : nsCSSValue::AppendPolygonToString(nsCSSPropertyID aProperty, nsAString& aResult,
1046 : Serialization aSerialization) const
1047 : {
1048 0 : const nsCSSValue::Array* array = GetArrayValue();
1049 0 : MOZ_ASSERT(array->Count() > 1 && array->Count() <= 3,
1050 : "Polygons must have name and at least one more value.");
1051 : // When the array has 2 elements, the item on index 1 is the coordinate
1052 : // pair list.
1053 : // When the array has 3 elements, the item on index 1 is a fill-rule
1054 : // and item on index 2 is the coordinate pair list.
1055 0 : size_t index = 1;
1056 0 : if (array->Count() == 3) {
1057 0 : const nsCSSValue& fillRuleValue = array->Item(index);
1058 0 : MOZ_ASSERT(fillRuleValue.GetUnit() == eCSSUnit_Enumerated,
1059 : "Expected polygon fill rule.");
1060 0 : int32_t fillRule = fillRuleValue.GetIntValue();
1061 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(fillRule,
1062 0 : nsCSSProps::kFillRuleKTable),
1063 0 : aResult);
1064 0 : aResult.AppendLiteral(", ");
1065 0 : ++index;
1066 : }
1067 0 : array->Item(index).AppendToString(aProperty, aResult, aSerialization);
1068 0 : }
1069 :
1070 : inline void
1071 0 : nsCSSValue::AppendPositionCoordinateToString(
1072 : const nsCSSValue& aValue, nsCSSPropertyID aProperty,
1073 : nsAString& aResult, Serialization aSerialization) const
1074 : {
1075 0 : if (aValue.GetUnit() == eCSSUnit_Enumerated) {
1076 0 : int32_t intValue = aValue.GetIntValue();
1077 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
1078 0 : nsCSSProps::kShapeRadiusKTable), aResult);
1079 : } else {
1080 0 : aValue.AppendToString(aProperty, aResult, aSerialization);
1081 : }
1082 0 : }
1083 :
1084 : void
1085 0 : nsCSSValue::AppendCircleOrEllipseToString(nsCSSKeyword aFunctionId,
1086 : nsCSSPropertyID aProperty,
1087 : nsAString& aResult,
1088 : Serialization aSerialization) const
1089 : {
1090 0 : const nsCSSValue::Array* array = GetArrayValue();
1091 0 : size_t count = aFunctionId == eCSSKeyword_circle ? 2 : 3;
1092 0 : MOZ_ASSERT(array->Count() == count + 1, "wrong number of arguments");
1093 :
1094 0 : bool hasRadii = array->Item(1).GetUnit() != eCSSUnit_Null;
1095 :
1096 : // closest-side is the default, so we don't need to
1097 : // output it if all values are closest-side.
1098 0 : if (array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
1099 0 : StyleShapeRadius(array->Item(1).GetIntValue()) == StyleShapeRadius::ClosestSide &&
1100 0 : (aFunctionId == eCSSKeyword_circle ||
1101 0 : (array->Item(2).GetUnit() == eCSSUnit_Enumerated &&
1102 0 : StyleShapeRadius(array->Item(2).GetIntValue()) == StyleShapeRadius::ClosestSide))) {
1103 0 : hasRadii = false;
1104 : } else {
1105 0 : AppendPositionCoordinateToString(array->Item(1), aProperty,
1106 0 : aResult, aSerialization);
1107 :
1108 0 : if (hasRadii && aFunctionId == eCSSKeyword_ellipse) {
1109 0 : aResult.Append(' ');
1110 0 : AppendPositionCoordinateToString(array->Item(2), aProperty,
1111 0 : aResult, aSerialization);
1112 : }
1113 : }
1114 :
1115 0 : if (hasRadii) {
1116 0 : aResult.Append(' ');
1117 : }
1118 :
1119 : // Any position specified?
1120 0 : if (array->Item(count).GetUnit() != eCSSUnit_Array) {
1121 0 : MOZ_ASSERT(array->Item(count).GetUnit() == eCSSUnit_Null,
1122 : "unexpected value");
1123 : // We only serialize to the 2 or 4 value form
1124 : // |circle()| is valid, but should be expanded
1125 : // to |circle(at 50% 50%)|
1126 0 : aResult.AppendLiteral("at 50% 50%");
1127 0 : return;
1128 : }
1129 :
1130 0 : aResult.AppendLiteral("at ");
1131 0 : array->Item(count).AppendBasicShapePositionToString(aResult, aSerialization);
1132 : }
1133 :
1134 : // https://drafts.csswg.org/css-shapes/#basic-shape-serialization
1135 : // basic-shape asks us to omit a lot of redundant things whilst serializing
1136 : // position values. Other specs are not clear about this
1137 : // (https://github.com/w3c/csswg-drafts/issues/368), so for now we special-case
1138 : // basic shapes only
1139 : void
1140 0 : nsCSSValue::AppendBasicShapePositionToString(nsAString& aResult,
1141 : Serialization aSerialization) const
1142 : {
1143 0 : const nsCSSValue::Array* array = GetArrayValue();
1144 : // We always parse these into an array of four elements
1145 0 : MOZ_ASSERT(array->Count() == 4,
1146 : "basic-shape position value doesn't have enough elements");
1147 :
1148 0 : const nsCSSValue &xEdge = array->Item(0);
1149 0 : const nsCSSValue &xOffset = array->Item(1);
1150 0 : const nsCSSValue &yEdge = array->Item(2);
1151 0 : const nsCSSValue &yOffset = array->Item(3);
1152 :
1153 0 : MOZ_ASSERT(xEdge.GetUnit() == eCSSUnit_Enumerated &&
1154 : yEdge.GetUnit() == eCSSUnit_Enumerated &&
1155 : xOffset.IsLengthPercentCalcUnit() &&
1156 : yOffset.IsLengthPercentCalcUnit() &&
1157 : xEdge.GetIntValue() != NS_STYLE_IMAGELAYER_POSITION_CENTER &&
1158 : yEdge.GetIntValue() != NS_STYLE_IMAGELAYER_POSITION_CENTER,
1159 : "Ensure invariants from ParsePositionValueBasicShape "
1160 : "haven't been modified");
1161 0 : if (xEdge.GetIntValue() == NS_STYLE_IMAGELAYER_POSITION_LEFT &&
1162 0 : yEdge.GetIntValue() == NS_STYLE_IMAGELAYER_POSITION_TOP) {
1163 : // We can omit these defaults
1164 0 : xOffset.AppendToString(eCSSProperty_UNKNOWN, aResult, aSerialization);
1165 0 : aResult.Append(' ');
1166 0 : yOffset.AppendToString(eCSSProperty_UNKNOWN, aResult, aSerialization);
1167 : } else {
1168 : // We only serialize to the two or four valued form
1169 0 : xEdge.AppendToString(eCSSProperty_object_position, aResult, aSerialization);
1170 0 : aResult.Append(' ');
1171 0 : xOffset.AppendToString(eCSSProperty_UNKNOWN, aResult, aSerialization);
1172 0 : aResult.Append(' ');
1173 0 : yEdge.AppendToString(eCSSProperty_object_position, aResult, aSerialization);
1174 0 : aResult.Append(' ');
1175 0 : yOffset.AppendToString(eCSSProperty_UNKNOWN, aResult, aSerialization);
1176 : }
1177 0 : }
1178 :
1179 : // Helper to append |aString| with the shorthand sides notation used in e.g.
1180 : // 'padding'. |aProperties| and |aValues| are expected to have 4 elements.
1181 : /*static*/ void
1182 0 : nsCSSValue::AppendSidesShorthandToString(const nsCSSPropertyID aProperties[],
1183 : const nsCSSValue* aValues[],
1184 : nsAString& aString,
1185 : nsCSSValue::Serialization
1186 : aSerialization)
1187 : {
1188 0 : const nsCSSValue& value1 = *aValues[0];
1189 0 : const nsCSSValue& value2 = *aValues[1];
1190 0 : const nsCSSValue& value3 = *aValues[2];
1191 0 : const nsCSSValue& value4 = *aValues[3];
1192 :
1193 0 : MOZ_ASSERT(value1.GetUnit() != eCSSUnit_Null, "null value 1");
1194 0 : value1.AppendToString(aProperties[0], aString, aSerialization);
1195 0 : if (value1 != value2 || value1 != value3 || value1 != value4) {
1196 0 : aString.Append(char16_t(' '));
1197 0 : MOZ_ASSERT(value2.GetUnit() != eCSSUnit_Null, "null value 2");
1198 0 : value2.AppendToString(aProperties[1], aString, aSerialization);
1199 0 : if (value1 != value3 || value2 != value4) {
1200 0 : aString.Append(char16_t(' '));
1201 0 : MOZ_ASSERT(value3.GetUnit() != eCSSUnit_Null, "null value 3");
1202 0 : value3.AppendToString(aProperties[2], aString, aSerialization);
1203 0 : if (value2 != value4) {
1204 0 : aString.Append(char16_t(' '));
1205 0 : MOZ_ASSERT(value4.GetUnit() != eCSSUnit_Null, "null value 4");
1206 0 : value4.AppendToString(aProperties[3], aString, aSerialization);
1207 : }
1208 : }
1209 : }
1210 0 : }
1211 :
1212 : /*static*/ void
1213 0 : nsCSSValue::AppendBasicShapeRadiusToString(const nsCSSPropertyID aProperties[],
1214 : const nsCSSValue* aValues[],
1215 : nsAString& aResult,
1216 : Serialization aSerialization)
1217 : {
1218 0 : bool needY = false;
1219 : const nsCSSValue* xVals[4];
1220 : const nsCSSValue* yVals[4];
1221 0 : for (int i = 0; i < 4; i++) {
1222 0 : if (aValues[i]->GetUnit() == eCSSUnit_Pair) {
1223 0 : needY = true;
1224 0 : xVals[i] = &aValues[i]->GetPairValue().mXValue;
1225 0 : yVals[i] = &aValues[i]->GetPairValue().mYValue;
1226 : } else {
1227 0 : xVals[i] = yVals[i] = aValues[i];
1228 : }
1229 : }
1230 :
1231 0 : AppendSidesShorthandToString(aProperties, xVals, aResult, aSerialization);
1232 0 : if (needY) {
1233 0 : aResult.AppendLiteral(" / ");
1234 0 : AppendSidesShorthandToString(aProperties, yVals, aResult, aSerialization);
1235 : }
1236 0 : }
1237 :
1238 : void
1239 0 : nsCSSValue::AppendInsetToString(nsCSSPropertyID aProperty, nsAString& aResult,
1240 : Serialization aSerialization) const
1241 : {
1242 0 : const nsCSSValue::Array* array = GetArrayValue();
1243 0 : MOZ_ASSERT(array->Count() == 6,
1244 : "inset function has wrong number of arguments");
1245 0 : if (array->Item(1).GetUnit() != eCSSUnit_Null) {
1246 0 : array->Item(1).AppendToString(aProperty, aResult, aSerialization);
1247 0 : if (array->Item(2).GetUnit() != eCSSUnit_Null) {
1248 0 : aResult.Append(' ');
1249 0 : array->Item(2).AppendToString(aProperty, aResult, aSerialization);
1250 0 : if (array->Item(3).GetUnit() != eCSSUnit_Null) {
1251 0 : aResult.Append(' ');
1252 0 : array->Item(3).AppendToString(aProperty, aResult, aSerialization);
1253 0 : if (array->Item(4).GetUnit() != eCSSUnit_Null) {
1254 0 : aResult.Append(' ');
1255 0 : array->Item(4).AppendToString(aProperty, aResult, aSerialization);
1256 : }
1257 : }
1258 : }
1259 : }
1260 :
1261 0 : if (array->Item(5).GetUnit() == eCSSUnit_Array) {
1262 : const nsCSSPropertyID* subprops =
1263 0 : nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius);
1264 0 : const nsCSSValue::Array* radius = array->Item(5).GetArrayValue();
1265 0 : MOZ_ASSERT(radius->Count() == 4, "expected 4 radii values");
1266 : const nsCSSValue* vals[4] = {
1267 0 : &(radius->Item(0)),
1268 0 : &(radius->Item(1)),
1269 0 : &(radius->Item(2)),
1270 0 : &(radius->Item(3))
1271 0 : };
1272 0 : aResult.AppendLiteral(" round ");
1273 : AppendBasicShapeRadiusToString(subprops, vals, aResult,
1274 0 : aSerialization);
1275 : } else {
1276 0 : MOZ_ASSERT(array->Item(5).GetUnit() == eCSSUnit_Null,
1277 : "unexpected value");
1278 : }
1279 0 : }
1280 :
1281 : /* static */ void
1282 0 : nsCSSValue::AppendAlignJustifyValueToString(int32_t aValue, nsAString& aResult)
1283 : {
1284 0 : auto legacy = aValue & NS_STYLE_ALIGN_LEGACY;
1285 0 : if (legacy) {
1286 0 : aValue &= ~legacy;
1287 0 : aResult.AppendLiteral("legacy ");
1288 : }
1289 0 : auto overflowPos = aValue & (NS_STYLE_ALIGN_SAFE | NS_STYLE_ALIGN_UNSAFE);
1290 0 : aValue &= ~overflowPos;
1291 0 : MOZ_ASSERT(!(aValue & NS_STYLE_ALIGN_FLAG_BITS),
1292 : "unknown bits in align/justify value");
1293 0 : MOZ_ASSERT((aValue != NS_STYLE_ALIGN_AUTO &&
1294 : aValue != NS_STYLE_ALIGN_NORMAL &&
1295 : aValue != NS_STYLE_ALIGN_BASELINE &&
1296 : aValue != NS_STYLE_ALIGN_LAST_BASELINE) ||
1297 : (!legacy && !overflowPos),
1298 : "auto/normal/baseline/'last baseline' never have any flags");
1299 0 : MOZ_ASSERT(legacy == 0 || overflowPos == 0,
1300 : "'legacy' together with <overflow-position>");
1301 0 : if (aValue == NS_STYLE_ALIGN_LAST_BASELINE) {
1302 0 : aResult.AppendLiteral("last ");
1303 0 : aValue = NS_STYLE_ALIGN_BASELINE;
1304 : }
1305 0 : const auto& kwtable(nsCSSProps::kAlignAllKeywords);
1306 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(aValue, kwtable), aResult);
1307 : // Don't serialize the 'unsafe' keyword; it's the default.
1308 0 : if (MOZ_UNLIKELY(overflowPos == NS_STYLE_ALIGN_SAFE)) {
1309 0 : aResult.Append(' ');
1310 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(overflowPos, kwtable),
1311 0 : aResult);
1312 : }
1313 0 : }
1314 :
1315 : void
1316 0 : nsCSSValue::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
1317 : Serialization aSerialization) const
1318 : {
1319 : // eCSSProperty_UNKNOWN gets used for some recursive calls below.
1320 0 : MOZ_ASSERT((0 <= aProperty &&
1321 : aProperty <= eCSSProperty_COUNT_no_shorthands) ||
1322 : aProperty == eCSSProperty_UNKNOWN ||
1323 : aProperty == eCSSProperty_DOM,
1324 : "property ID out of range");
1325 :
1326 0 : nsCSSUnit unit = GetUnit();
1327 0 : if (unit == eCSSUnit_Null) {
1328 0 : return;
1329 : }
1330 :
1331 0 : if (eCSSUnit_String <= unit && unit <= eCSSUnit_Attr) {
1332 0 : if (unit == eCSSUnit_Attr) {
1333 0 : aResult.AppendLiteral("attr(");
1334 : }
1335 0 : nsAutoString buffer;
1336 0 : GetStringValue(buffer);
1337 0 : if (unit == eCSSUnit_String) {
1338 0 : nsStyleUtil::AppendEscapedCSSString(buffer, aResult);
1339 : } else {
1340 0 : nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult);
1341 0 : }
1342 : }
1343 0 : else if (eCSSUnit_Array <= unit && unit <= eCSSUnit_Symbols) {
1344 0 : switch (unit) {
1345 0 : case eCSSUnit_Counter: aResult.AppendLiteral("counter("); break;
1346 0 : case eCSSUnit_Counters: aResult.AppendLiteral("counters("); break;
1347 0 : case eCSSUnit_Cubic_Bezier: aResult.AppendLiteral("cubic-bezier("); break;
1348 0 : case eCSSUnit_Steps: aResult.AppendLiteral("steps("); break;
1349 0 : case eCSSUnit_Symbols: aResult.AppendLiteral("symbols("); break;
1350 0 : default: break;
1351 : }
1352 :
1353 0 : nsCSSValue::Array *array = GetArrayValue();
1354 0 : bool mark = false;
1355 0 : for (size_t i = 0, i_end = array->Count(); i < i_end; ++i) {
1356 0 : if (mark && array->Item(i).GetUnit() != eCSSUnit_Null) {
1357 0 : if ((unit == eCSSUnit_Array &&
1358 0 : eCSSProperty_transition_timing_function != aProperty) ||
1359 : unit == eCSSUnit_Symbols)
1360 0 : aResult.Append(' ');
1361 0 : else if (unit != eCSSUnit_Steps)
1362 0 : aResult.AppendLiteral(", ");
1363 : }
1364 0 : if (unit == eCSSUnit_Steps && i == 1) {
1365 0 : MOZ_ASSERT(array->Item(i).GetUnit() == eCSSUnit_Enumerated,
1366 : "unexpected value");
1367 0 : int32_t side = array->Item(i).GetIntValue();
1368 0 : MOZ_ASSERT(side == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
1369 : side == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END ||
1370 : side == -1,
1371 : "unexpected value");
1372 0 : if (side == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START) {
1373 0 : aResult.AppendLiteral(", start");
1374 0 : } else if (side == NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END) {
1375 0 : aResult.AppendLiteral(", end");
1376 : }
1377 0 : continue;
1378 : }
1379 0 : if (unit == eCSSUnit_Symbols && i == 0) {
1380 0 : MOZ_ASSERT(array->Item(i).GetUnit() == eCSSUnit_Enumerated,
1381 : "unexpected value");
1382 0 : int32_t system = array->Item(i).GetIntValue();
1383 0 : if (system != NS_STYLE_COUNTER_SYSTEM_SYMBOLIC) {
1384 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(
1385 0 : system, nsCSSProps::kCounterSystemKTable), aResult);
1386 0 : mark = true;
1387 : }
1388 0 : continue;
1389 : }
1390 : nsCSSPropertyID prop =
1391 0 : ((eCSSUnit_Counter <= unit && unit <= eCSSUnit_Counters) &&
1392 0 : i == array->Count() - 1)
1393 0 : ? eCSSProperty_list_style_type : aProperty;
1394 0 : if (array->Item(i).GetUnit() != eCSSUnit_Null) {
1395 0 : array->Item(i).AppendToString(prop, aResult, aSerialization);
1396 0 : mark = true;
1397 : }
1398 : }
1399 0 : if (eCSSUnit_Array == unit &&
1400 : aProperty == eCSSProperty_transition_timing_function) {
1401 0 : aResult.Append(')');
1402 0 : }
1403 : }
1404 : /* Although Function is backed by an Array, we'll handle it separately
1405 : * because it's a bit quirky.
1406 : */
1407 0 : else if (eCSSUnit_Function == unit) {
1408 0 : const nsCSSValue::Array* array = GetArrayValue();
1409 0 : MOZ_ASSERT(array->Count() >= 1,
1410 : "Functions must have at least one element for the name.");
1411 :
1412 0 : const nsCSSValue& functionName = array->Item(0);
1413 0 : MOZ_ASSERT(functionName.GetUnit() == eCSSUnit_Enumerated,
1414 : "Functions must have an enumerated name.");
1415 : // The first argument is always of nsCSSKeyword type.
1416 0 : const nsCSSKeyword functionId = functionName.GetKeywordValue();
1417 :
1418 : // minmax(auto, <flex>) is equivalent to (and is our internal representation
1419 : // of) <flex>, and both are serialized as <flex>
1420 0 : if (functionId == eCSSKeyword_minmax &&
1421 0 : array->Count() == 3 &&
1422 0 : array->Item(1).GetUnit() == eCSSUnit_Auto &&
1423 0 : array->Item(2).GetUnit() == eCSSUnit_FlexFraction) {
1424 0 : array->Item(2).AppendToString(aProperty, aResult, aSerialization);
1425 0 : MOZ_ASSERT(aProperty == eCSSProperty_grid_template_columns ||
1426 : aProperty == eCSSProperty_grid_template_rows ||
1427 : aProperty == eCSSProperty_grid_auto_columns ||
1428 : aProperty == eCSSProperty_grid_auto_rows);
1429 0 : return;
1430 : }
1431 :
1432 : /* Append the function name. */
1433 0 : NS_ConvertASCIItoUTF16 ident(nsCSSKeywords::GetStringValue(functionId));
1434 : // Bug 721136: Normalize the identifier to lowercase, except that things
1435 : // like scaleX should have the last character capitalized. This matches
1436 : // what other browsers do.
1437 0 : switch (functionId) {
1438 : case eCSSKeyword_rotatex:
1439 : case eCSSKeyword_scalex:
1440 : case eCSSKeyword_skewx:
1441 : case eCSSKeyword_translatex:
1442 0 : ident.Replace(ident.Length() - 1, 1, char16_t('X'));
1443 0 : break;
1444 :
1445 : case eCSSKeyword_rotatey:
1446 : case eCSSKeyword_scaley:
1447 : case eCSSKeyword_skewy:
1448 : case eCSSKeyword_translatey:
1449 0 : ident.Replace(ident.Length() - 1, 1, char16_t('Y'));
1450 0 : break;
1451 :
1452 : case eCSSKeyword_rotatez:
1453 : case eCSSKeyword_scalez:
1454 : case eCSSKeyword_translatez:
1455 0 : ident.Replace(ident.Length() - 1, 1, char16_t('Z'));
1456 0 : break;
1457 :
1458 : default:
1459 0 : break;
1460 : }
1461 0 : nsStyleUtil::AppendEscapedCSSIdent(ident, aResult);
1462 0 : aResult.Append('(');
1463 :
1464 0 : switch (functionId) {
1465 : case eCSSKeyword_polygon:
1466 0 : AppendPolygonToString(aProperty, aResult, aSerialization);
1467 0 : break;
1468 :
1469 : case eCSSKeyword_circle:
1470 : case eCSSKeyword_ellipse:
1471 0 : AppendCircleOrEllipseToString(functionId, aProperty, aResult,
1472 0 : aSerialization);
1473 0 : break;
1474 :
1475 : case eCSSKeyword_inset:
1476 0 : AppendInsetToString(aProperty, aResult, aSerialization);
1477 0 : break;
1478 :
1479 : default: {
1480 : // Now, step through the function contents, writing each of
1481 : // them as we go.
1482 0 : for (size_t index = 1; index < array->Count(); ++index) {
1483 0 : array->Item(index).AppendToString(aProperty, aResult,
1484 0 : aSerialization);
1485 :
1486 : /* If we're not at the final element, append a comma. */
1487 0 : if (index + 1 != array->Count())
1488 0 : aResult.AppendLiteral(", ");
1489 : }
1490 : }
1491 : }
1492 :
1493 : /* Finally, append the closing parenthesis. */
1494 0 : aResult.Append(')');
1495 : }
1496 0 : else if (IsCalcUnit()) {
1497 0 : MOZ_ASSERT(GetUnit() == eCSSUnit_Calc, "unexpected unit");
1498 0 : CSSValueSerializeCalcOps ops(aProperty, aResult, aSerialization);
1499 0 : css::SerializeCalc(*this, ops);
1500 : }
1501 0 : else if (eCSSUnit_Integer == unit) {
1502 0 : aResult.AppendInt(GetIntValue(), 10);
1503 : }
1504 0 : else if (eCSSUnit_Enumerated == unit) {
1505 0 : int32_t intValue = GetIntValue();
1506 0 : switch(aProperty) {
1507 :
1508 :
1509 : case eCSSProperty_text_combine_upright:
1510 0 : if (intValue <= NS_STYLE_TEXT_COMBINE_UPRIGHT_ALL) {
1511 0 : AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
1512 0 : aResult);
1513 0 : } else if (intValue == NS_STYLE_TEXT_COMBINE_UPRIGHT_DIGITS_2) {
1514 0 : aResult.AppendLiteral("digits 2");
1515 0 : } else if (intValue == NS_STYLE_TEXT_COMBINE_UPRIGHT_DIGITS_3) {
1516 0 : aResult.AppendLiteral("digits 3");
1517 : } else {
1518 0 : aResult.AppendLiteral("digits 4");
1519 : }
1520 0 : break;
1521 :
1522 : case eCSSProperty_text_decoration_line:
1523 0 : if (NS_STYLE_TEXT_DECORATION_LINE_NONE == intValue) {
1524 0 : AppendASCIItoUTF16(nsCSSProps::LookupPropertyValue(aProperty, intValue),
1525 0 : aResult);
1526 : } else {
1527 : // Ignore the "override all" internal value.
1528 : // (It doesn't have a string representation.)
1529 0 : intValue &= ~NS_STYLE_TEXT_DECORATION_LINE_OVERRIDE_ALL;
1530 : nsStyleUtil::AppendBitmaskCSSValue(
1531 : aProperty, intValue,
1532 : NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE,
1533 : NS_STYLE_TEXT_DECORATION_LINE_BLINK,
1534 0 : aResult);
1535 : }
1536 0 : break;
1537 :
1538 : case eCSSProperty_paint_order:
1539 : static_assert
1540 : (NS_STYLE_PAINT_ORDER_BITWIDTH * NS_STYLE_PAINT_ORDER_LAST_VALUE <= 8,
1541 : "SVGStyleStruct::mPaintOrder and the following cast not big enough");
1542 0 : nsStyleUtil::AppendPaintOrderValue(static_cast<uint8_t>(GetIntValue()),
1543 0 : aResult);
1544 0 : break;
1545 :
1546 : case eCSSProperty_font_synthesis:
1547 : nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
1548 : NS_FONT_SYNTHESIS_WEIGHT,
1549 : NS_FONT_SYNTHESIS_STYLE,
1550 0 : aResult);
1551 0 : break;
1552 :
1553 : case eCSSProperty_font_variant_east_asian:
1554 : nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
1555 : NS_FONT_VARIANT_EAST_ASIAN_JIS78,
1556 : NS_FONT_VARIANT_EAST_ASIAN_RUBY,
1557 0 : aResult);
1558 0 : break;
1559 :
1560 : case eCSSProperty_font_variant_ligatures:
1561 : nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
1562 : NS_FONT_VARIANT_LIGATURES_NONE,
1563 : NS_FONT_VARIANT_LIGATURES_NO_CONTEXTUAL,
1564 0 : aResult);
1565 0 : break;
1566 :
1567 : case eCSSProperty_font_variant_numeric:
1568 : nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
1569 : NS_FONT_VARIANT_NUMERIC_LINING,
1570 : NS_FONT_VARIANT_NUMERIC_ORDINAL,
1571 0 : aResult);
1572 0 : break;
1573 :
1574 : case eCSSProperty_grid_auto_flow:
1575 : nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
1576 : NS_STYLE_GRID_AUTO_FLOW_ROW,
1577 : NS_STYLE_GRID_AUTO_FLOW_DENSE,
1578 0 : aResult);
1579 0 : break;
1580 :
1581 : case eCSSProperty_grid_column_start:
1582 : case eCSSProperty_grid_column_end:
1583 : case eCSSProperty_grid_row_start:
1584 : case eCSSProperty_grid_row_end:
1585 : // "span" is the only enumerated-unit value for these properties
1586 0 : aResult.AppendLiteral("span");
1587 0 : break;
1588 :
1589 : case eCSSProperty_touch_action:
1590 : nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
1591 : NS_STYLE_TOUCH_ACTION_NONE,
1592 : NS_STYLE_TOUCH_ACTION_MANIPULATION,
1593 0 : aResult);
1594 0 : break;
1595 :
1596 : case eCSSProperty_clip_path:
1597 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
1598 0 : nsCSSProps::kClipPathGeometryBoxKTable),
1599 0 : aResult);
1600 0 : break;
1601 :
1602 : case eCSSProperty_shape_outside:
1603 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
1604 0 : nsCSSProps::kShapeOutsideShapeBoxKTable),
1605 0 : aResult);
1606 0 : break;
1607 :
1608 : case eCSSProperty_contain:
1609 0 : if (intValue & NS_STYLE_CONTAIN_STRICT) {
1610 0 : NS_ASSERTION(intValue == (NS_STYLE_CONTAIN_STRICT | NS_STYLE_CONTAIN_ALL_BITS),
1611 : "contain: strict should imply contain: layout style paint");
1612 : // Only output strict.
1613 0 : intValue = NS_STYLE_CONTAIN_STRICT;
1614 : }
1615 : nsStyleUtil::AppendBitmaskCSSValue(aProperty,
1616 : intValue,
1617 : NS_STYLE_CONTAIN_STRICT,
1618 : NS_STYLE_CONTAIN_PAINT,
1619 0 : aResult);
1620 0 : break;
1621 :
1622 : case eCSSProperty_align_content:
1623 : case eCSSProperty_justify_content: {
1624 0 : AppendAlignJustifyValueToString(intValue & NS_STYLE_ALIGN_ALL_BITS, aResult);
1625 0 : auto fallback = intValue >> NS_STYLE_ALIGN_ALL_SHIFT;
1626 0 : if (fallback) {
1627 0 : MOZ_ASSERT(nsCSSProps::ValueToKeywordEnum(fallback & ~NS_STYLE_ALIGN_FLAG_BITS,
1628 : nsCSSProps::kAlignSelfPosition)
1629 : != eCSSKeyword_UNKNOWN, "unknown fallback value");
1630 0 : aResult.Append(' ');
1631 0 : AppendAlignJustifyValueToString(fallback, aResult);
1632 : }
1633 0 : break;
1634 : }
1635 :
1636 : case eCSSProperty_align_items:
1637 : case eCSSProperty_align_self:
1638 : case eCSSProperty_justify_items:
1639 : case eCSSProperty_justify_self:
1640 0 : AppendAlignJustifyValueToString(intValue, aResult);
1641 0 : break;
1642 :
1643 : case eCSSProperty_text_emphasis_position: {
1644 : nsStyleUtil::AppendBitmaskCSSValue(aProperty, intValue,
1645 : NS_STYLE_TEXT_EMPHASIS_POSITION_OVER,
1646 : NS_STYLE_TEXT_EMPHASIS_POSITION_RIGHT,
1647 0 : aResult);
1648 0 : break;
1649 : }
1650 :
1651 : case eCSSProperty_text_emphasis_style: {
1652 0 : auto fill = intValue & NS_STYLE_TEXT_EMPHASIS_STYLE_FILL_MASK;
1653 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(
1654 0 : fill, nsCSSProps::kTextEmphasisStyleFillKTable), aResult);
1655 0 : aResult.Append(' ');
1656 0 : auto shape = intValue & NS_STYLE_TEXT_EMPHASIS_STYLE_SHAPE_MASK;
1657 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(
1658 0 : shape, nsCSSProps::kTextEmphasisStyleShapeKTable), aResult);
1659 0 : break;
1660 : }
1661 :
1662 : default:
1663 0 : const nsCString& name = nsCSSProps::LookupPropertyValue(aProperty, intValue);
1664 0 : AppendASCIItoUTF16(name, aResult);
1665 0 : break;
1666 : }
1667 : }
1668 0 : else if (eCSSUnit_EnumColor == unit) {
1669 : // we can lookup the property in the ColorTable and then
1670 : // get a string mapping the name
1671 0 : nsAutoCString str;
1672 0 : if (nsCSSProps::GetColorName(GetIntValue(), str)){
1673 0 : AppendASCIItoUTF16(str, aResult);
1674 : } else {
1675 0 : MOZ_ASSERT(false, "bad color value");
1676 : }
1677 : }
1678 0 : else if (IsNumericColorUnit(unit)) {
1679 0 : if (aSerialization == eNormalized ||
1680 0 : unit == eCSSUnit_RGBColor ||
1681 : unit == eCSSUnit_RGBAColor) {
1682 0 : nscolor color = GetColorValue();
1683 : // For brevity, we omit the alpha component if it's equal to 255 (full
1684 : // opaque). Also, we use "rgba" rather than "rgb" when the color includes
1685 : // the non-opaque alpha value, for backwards-compat (even though they're
1686 : // aliases as of css-color-4).
1687 : // e.g.:
1688 : // rgba(1, 2, 3, 1.0) => rgb(1, 2, 3)
1689 : // rgba(1, 2, 3, 0.5) => rgba(1, 2, 3, 0.5)
1690 :
1691 0 : uint8_t a = NS_GET_A(color);
1692 0 : bool showAlpha = (a != 255);
1693 :
1694 0 : if (showAlpha) {
1695 0 : aResult.AppendLiteral("rgba(");
1696 : } else {
1697 0 : aResult.AppendLiteral("rgb(");
1698 : }
1699 :
1700 0 : NS_NAMED_LITERAL_STRING(comma, ", ");
1701 :
1702 0 : aResult.AppendInt(NS_GET_R(color), 10);
1703 0 : aResult.Append(comma);
1704 0 : aResult.AppendInt(NS_GET_G(color), 10);
1705 0 : aResult.Append(comma);
1706 0 : aResult.AppendInt(NS_GET_B(color), 10);
1707 0 : if (showAlpha) {
1708 0 : aResult.Append(comma);
1709 0 : aResult.AppendFloat(nsStyleUtil::ColorComponentToFloat(a));
1710 : }
1711 0 : aResult.Append(char16_t(')'));
1712 0 : } else if (eCSSUnit_HexColor == unit ||
1713 : eCSSUnit_HexColorAlpha == unit) {
1714 0 : nscolor color = GetColorValue();
1715 0 : aResult.Append('#');
1716 0 : aResult.AppendPrintf("%02x", NS_GET_R(color));
1717 0 : aResult.AppendPrintf("%02x", NS_GET_G(color));
1718 0 : aResult.AppendPrintf("%02x", NS_GET_B(color));
1719 0 : if (eCSSUnit_HexColorAlpha == unit) {
1720 0 : aResult.AppendPrintf("%02x", NS_GET_A(color));
1721 0 : }
1722 0 : } else if (eCSSUnit_ShortHexColor == unit ||
1723 : eCSSUnit_ShortHexColorAlpha == unit) {
1724 0 : nscolor color = GetColorValue();
1725 0 : aResult.Append('#');
1726 0 : aResult.AppendInt(NS_GET_R(color) / 0x11, 16);
1727 0 : aResult.AppendInt(NS_GET_G(color) / 0x11, 16);
1728 0 : aResult.AppendInt(NS_GET_B(color) / 0x11, 16);
1729 0 : if (eCSSUnit_ShortHexColorAlpha == unit) {
1730 0 : aResult.AppendInt(NS_GET_A(color) / 0x11, 16);
1731 0 : }
1732 : } else {
1733 0 : MOZ_ASSERT(IsFloatColorUnit());
1734 0 : mValue.mFloatColor->AppendToString(unit, aResult);
1735 : }
1736 : }
1737 0 : else if (eCSSUnit_ComplexColor == unit) {
1738 0 : StyleComplexColor color = GetStyleComplexColorValue();
1739 0 : nsCSSValue serializable;
1740 0 : if (color.IsCurrentColor()) {
1741 0 : serializable.SetIntValue(NS_COLOR_CURRENTCOLOR, eCSSUnit_EnumColor);
1742 0 : } else if (color.IsNumericColor()) {
1743 0 : serializable.SetColorValue(color.mColor);
1744 : } else {
1745 0 : MOZ_ASSERT_UNREACHABLE("Cannot serialize a complex color");
1746 : }
1747 0 : serializable.AppendToString(aProperty, aResult, aSerialization);
1748 : }
1749 0 : else if (eCSSUnit_URL == unit || eCSSUnit_Image == unit) {
1750 0 : aResult.AppendLiteral("url(");
1751 : nsStyleUtil::AppendEscapedCSSString(
1752 0 : nsDependentString(GetOriginalURLValue()), aResult);
1753 0 : aResult.Append(')');
1754 : }
1755 0 : else if (eCSSUnit_Element == unit) {
1756 0 : aResult.AppendLiteral("-moz-element(#");
1757 0 : nsAutoString tmpStr;
1758 0 : GetStringValue(tmpStr);
1759 0 : nsStyleUtil::AppendEscapedCSSIdent(tmpStr, aResult);
1760 0 : aResult.Append(')');
1761 : }
1762 0 : else if (eCSSUnit_Percent == unit) {
1763 0 : aResult.AppendFloat(GetPercentValue() * 100.0f);
1764 : }
1765 0 : else if (eCSSUnit_Percent < unit) { // length unit
1766 0 : aResult.AppendFloat(GetFloatValue());
1767 : }
1768 0 : else if (eCSSUnit_Gradient == unit) {
1769 0 : nsCSSValueGradient* gradient = GetGradientValue();
1770 :
1771 0 : if (gradient->mIsLegacySyntax) {
1772 0 : if (gradient->mIsMozLegacySyntax) {
1773 0 : aResult.AppendLiteral("-moz-");
1774 : } else {
1775 0 : aResult.AppendLiteral("-webkit-");
1776 : }
1777 : }
1778 0 : if (gradient->mIsRepeating) {
1779 0 : aResult.AppendLiteral("repeating-");
1780 : }
1781 0 : if (gradient->mIsRadial) {
1782 0 : aResult.AppendLiteral("radial-gradient(");
1783 : } else {
1784 0 : aResult.AppendLiteral("linear-gradient(");
1785 : }
1786 :
1787 0 : bool needSep = false;
1788 0 : if (gradient->mIsRadial && !gradient->mIsLegacySyntax) {
1789 0 : if (!gradient->mIsExplicitSize) {
1790 0 : if (gradient->GetRadialShape().GetUnit() != eCSSUnit_None) {
1791 0 : MOZ_ASSERT(gradient->GetRadialShape().GetUnit() ==
1792 : eCSSUnit_Enumerated,
1793 : "bad unit for radial gradient shape");
1794 0 : int32_t intValue = gradient->GetRadialShape().GetIntValue();
1795 0 : MOZ_ASSERT(intValue != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1796 : "radial gradient with linear shape?!");
1797 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
1798 0 : nsCSSProps::kRadialGradientShapeKTable),
1799 0 : aResult);
1800 0 : needSep = true;
1801 : }
1802 :
1803 0 : if (gradient->GetRadialSize().GetUnit() != eCSSUnit_None) {
1804 0 : if (needSep) {
1805 0 : aResult.Append(' ');
1806 : }
1807 0 : MOZ_ASSERT(gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated,
1808 : "bad unit for radial gradient size");
1809 0 : int32_t intValue = gradient->GetRadialSize().GetIntValue();
1810 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
1811 0 : nsCSSProps::kRadialGradientSizeKTable),
1812 0 : aResult);
1813 0 : needSep = true;
1814 : }
1815 : } else {
1816 0 : MOZ_ASSERT(gradient->GetRadiusX().GetUnit() != eCSSUnit_None,
1817 : "bad unit for radial gradient explicit size");
1818 0 : gradient->GetRadiusX().AppendToString(aProperty, aResult,
1819 0 : aSerialization);
1820 0 : if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) {
1821 0 : aResult.Append(' ');
1822 0 : gradient->GetRadiusY().AppendToString(aProperty, aResult,
1823 0 : aSerialization);
1824 : }
1825 0 : needSep = true;
1826 : }
1827 : }
1828 0 : if (!gradient->mIsRadial &&
1829 0 : !(gradient->mIsLegacySyntax && gradient->mIsMozLegacySyntax)) {
1830 0 : if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
1831 0 : gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
1832 0 : MOZ_ASSERT(gradient->mAngle.GetUnit() == eCSSUnit_None);
1833 0 : MOZ_ASSERT(gradient->mBgPos.mXValue.GetUnit() == eCSSUnit_Enumerated &&
1834 : gradient->mBgPos.mYValue.GetUnit() == eCSSUnit_Enumerated,
1835 : "unexpected unit");
1836 0 : if (!gradient->mIsLegacySyntax) {
1837 0 : aResult.AppendLiteral("to ");
1838 : }
1839 0 : bool didAppendX = false;
1840 0 : if (!(gradient->mBgPos.mXValue.GetIntValue() & NS_STYLE_IMAGELAYER_POSITION_CENTER)) {
1841 0 : gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position_x,
1842 0 : aResult, aSerialization);
1843 0 : didAppendX = true;
1844 : }
1845 0 : if (!(gradient->mBgPos.mYValue.GetIntValue() & NS_STYLE_IMAGELAYER_POSITION_CENTER)) {
1846 0 : if (didAppendX) {
1847 : // We're appending both an x-keyword and a y-keyword.
1848 : // Add a space between them here.
1849 0 : aResult.Append(' ');
1850 : }
1851 0 : gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position_y,
1852 0 : aResult, aSerialization);
1853 : }
1854 0 : needSep = true;
1855 0 : } else if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
1856 0 : gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
1857 0 : needSep = true;
1858 0 : }
1859 0 : } else if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None ||
1860 0 : gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None ||
1861 0 : gradient->mAngle.GetUnit() != eCSSUnit_None) {
1862 0 : if (needSep) {
1863 0 : aResult.Append(' ');
1864 : }
1865 0 : if (gradient->mIsRadial && !gradient->mIsLegacySyntax) {
1866 0 : aResult.AppendLiteral("at ");
1867 : }
1868 0 : if (gradient->mBgPos.mXValue.GetUnit() != eCSSUnit_None) {
1869 0 : gradient->mBgPos.mXValue.AppendToString(eCSSProperty_background_position_x,
1870 0 : aResult, aSerialization);
1871 0 : aResult.Append(' ');
1872 : }
1873 0 : if (gradient->mBgPos.mYValue.GetUnit() != eCSSUnit_None) {
1874 0 : gradient->mBgPos.mYValue.AppendToString(eCSSProperty_background_position_y,
1875 0 : aResult, aSerialization);
1876 0 : aResult.Append(' ');
1877 : }
1878 0 : if (gradient->mAngle.GetUnit() != eCSSUnit_None) {
1879 0 : MOZ_ASSERT(gradient->mIsLegacySyntax,
1880 : "angle is allowed only for legacy syntax");
1881 0 : gradient->mAngle.AppendToString(aProperty, aResult, aSerialization);
1882 : }
1883 0 : needSep = true;
1884 : }
1885 :
1886 0 : if (gradient->mIsRadial && gradient->mIsLegacySyntax &&
1887 0 : (gradient->GetRadialShape().GetUnit() != eCSSUnit_None ||
1888 0 : gradient->GetRadialSize().GetUnit() != eCSSUnit_None)) {
1889 0 : MOZ_ASSERT(!gradient->mIsExplicitSize);
1890 0 : if (needSep) {
1891 0 : aResult.AppendLiteral(", ");
1892 : }
1893 0 : if (gradient->GetRadialShape().GetUnit() != eCSSUnit_None) {
1894 0 : MOZ_ASSERT(gradient->GetRadialShape().GetUnit() == eCSSUnit_Enumerated,
1895 : "bad unit for radial gradient shape");
1896 0 : int32_t intValue = gradient->GetRadialShape().GetIntValue();
1897 0 : MOZ_ASSERT(intValue != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1898 : "radial gradient with linear shape?!");
1899 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
1900 0 : nsCSSProps::kRadialGradientShapeKTable),
1901 0 : aResult);
1902 0 : aResult.Append(' ');
1903 : }
1904 :
1905 0 : if (gradient->GetRadialSize().GetUnit() != eCSSUnit_None) {
1906 0 : MOZ_ASSERT(gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated,
1907 : "bad unit for radial gradient size");
1908 0 : int32_t intValue = gradient->GetRadialSize().GetIntValue();
1909 0 : AppendASCIItoUTF16(nsCSSProps::ValueToKeyword(intValue,
1910 0 : nsCSSProps::kRadialGradientSizeKTable),
1911 0 : aResult);
1912 : }
1913 0 : needSep = true;
1914 : }
1915 0 : if (needSep) {
1916 0 : aResult.AppendLiteral(", ");
1917 : }
1918 :
1919 0 : for (uint32_t i = 0 ;;) {
1920 0 : bool isInterpolationHint = gradient->mStops[i].mIsInterpolationHint;
1921 0 : if (!isInterpolationHint) {
1922 0 : gradient->mStops[i].mColor.AppendToString(aProperty, aResult,
1923 0 : aSerialization);
1924 : }
1925 0 : if (gradient->mStops[i].mLocation.GetUnit() != eCSSUnit_None) {
1926 0 : if (!isInterpolationHint) {
1927 0 : aResult.Append(' ');
1928 : }
1929 0 : gradient->mStops[i].mLocation.AppendToString(aProperty, aResult,
1930 0 : aSerialization);
1931 : }
1932 0 : if (++i == gradient->mStops.Length()) {
1933 0 : break;
1934 : }
1935 0 : aResult.AppendLiteral(", ");
1936 0 : }
1937 :
1938 0 : aResult.Append(')');
1939 0 : } else if (eCSSUnit_TokenStream == unit) {
1940 0 : nsCSSPropertyID shorthand = mValue.mTokenStream->mShorthandPropertyID;
1941 0 : if (shorthand == eCSSProperty_UNKNOWN ||
1942 0 : nsCSSProps::PropHasFlags(shorthand, CSS_PROPERTY_IS_ALIAS) ||
1943 : aProperty == eCSSProperty__x_system_font) {
1944 : // We treat serialization of aliases like '-moz-transform' as a special
1945 : // case, since it really wants to be serialized as if it were a longhand
1946 : // even though it is implemented as a shorthand. We also need to
1947 : // serialize -x-system-font's token stream value, even though the
1948 : // value is set through the font shorthand. This serialization
1949 : // of -x-system-font is needed when we need to output the
1950 : // 'font' shorthand followed by a number of overriding font
1951 : // longhand components.
1952 0 : aResult.Append(mValue.mTokenStream->mTokenStream);
1953 : }
1954 0 : } else if (eCSSUnit_Pair == unit) {
1955 0 : if (eCSSProperty_font_variant_alternates == aProperty) {
1956 0 : int32_t intValue = GetPairValue().mXValue.GetIntValue();
1957 0 : nsAutoString out;
1958 :
1959 : // simple, enumerated values
1960 0 : nsStyleUtil::AppendBitmaskCSSValue(aProperty,
1961 : intValue & NS_FONT_VARIANT_ALTERNATES_ENUMERATED_MASK,
1962 : NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
1963 : NS_FONT_VARIANT_ALTERNATES_HISTORICAL,
1964 0 : out);
1965 :
1966 : // functional values
1967 0 : const nsCSSValueList *list = GetPairValue().mYValue.GetListValue();
1968 0 : AutoTArray<gfxAlternateValue,8> altValues;
1969 :
1970 0 : nsStyleUtil::ComputeFunctionalAlternates(list, altValues);
1971 0 : nsStyleUtil::SerializeFunctionalAlternates(altValues, out);
1972 0 : aResult.Append(out);
1973 : } else {
1974 0 : GetPairValue().AppendToString(aProperty, aResult, aSerialization);
1975 : }
1976 0 : } else if (eCSSUnit_Triplet == unit) {
1977 0 : GetTripletValue().AppendToString(aProperty, aResult, aSerialization);
1978 0 : } else if (eCSSUnit_Rect == unit) {
1979 0 : GetRectValue().AppendToString(aProperty, aResult, aSerialization);
1980 0 : } else if (eCSSUnit_List == unit || eCSSUnit_ListDep == unit) {
1981 0 : GetListValue()->AppendToString(aProperty, aResult, aSerialization);
1982 0 : } else if (eCSSUnit_SharedList == unit) {
1983 0 : GetSharedListValue()->AppendToString(aProperty, aResult, aSerialization);
1984 0 : } else if (eCSSUnit_PairList == unit || eCSSUnit_PairListDep == unit) {
1985 0 : switch (aProperty) {
1986 : case eCSSProperty_font_feature_settings:
1987 0 : nsStyleUtil::AppendFontFeatureSettings(*this, aResult);
1988 0 : break;
1989 : default:
1990 0 : GetPairListValue()->AppendToString(aProperty, aResult, aSerialization);
1991 0 : break;
1992 : }
1993 0 : } else if (eCSSUnit_GridTemplateAreas == unit) {
1994 0 : const mozilla::css::GridTemplateAreasValue* areas = GetGridTemplateAreas();
1995 0 : MOZ_ASSERT(!areas->mTemplates.IsEmpty(),
1996 : "Unexpected empty array in GridTemplateAreasValue");
1997 0 : nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[0], aResult);
1998 0 : for (uint32_t i = 1; i < areas->mTemplates.Length(); i++) {
1999 0 : aResult.Append(char16_t(' '));
2000 0 : nsStyleUtil::AppendEscapedCSSString(areas->mTemplates[i], aResult);
2001 : }
2002 0 : } else if (eCSSUnit_FontFamilyList == unit) {
2003 0 : nsStyleUtil::AppendEscapedCSSFontFamilyList(*mValue.mFontFamilyList,
2004 0 : aResult);
2005 0 : } else if (eCSSUnit_AtomIdent == unit) {
2006 0 : nsDependentAtomString buffer(GetAtomValue());
2007 0 : nsStyleUtil::AppendEscapedCSSIdent(buffer, aResult);
2008 : }
2009 :
2010 0 : switch (unit) {
2011 0 : case eCSSUnit_Null: break;
2012 0 : case eCSSUnit_Auto: aResult.AppendLiteral("auto"); break;
2013 0 : case eCSSUnit_Inherit: aResult.AppendLiteral("inherit"); break;
2014 0 : case eCSSUnit_Initial: aResult.AppendLiteral("initial"); break;
2015 0 : case eCSSUnit_Unset: aResult.AppendLiteral("unset"); break;
2016 0 : case eCSSUnit_None: aResult.AppendLiteral("none"); break;
2017 0 : case eCSSUnit_Normal: aResult.AppendLiteral("normal"); break;
2018 0 : case eCSSUnit_System_Font: aResult.AppendLiteral("-moz-use-system-font"); break;
2019 0 : case eCSSUnit_All: aResult.AppendLiteral("all"); break;
2020 : case eCSSUnit_Dummy:
2021 : case eCSSUnit_DummyInherit:
2022 0 : MOZ_ASSERT(false, "should never serialize");
2023 : break;
2024 :
2025 0 : case eCSSUnit_FontFamilyList: break;
2026 0 : case eCSSUnit_String: break;
2027 0 : case eCSSUnit_Ident: break;
2028 0 : case eCSSUnit_AtomIdent: break;
2029 0 : case eCSSUnit_URL: break;
2030 0 : case eCSSUnit_Image: break;
2031 0 : case eCSSUnit_Element: break;
2032 0 : case eCSSUnit_Array: break;
2033 : case eCSSUnit_Attr:
2034 : case eCSSUnit_Cubic_Bezier:
2035 : case eCSSUnit_Steps:
2036 : case eCSSUnit_Symbols:
2037 : case eCSSUnit_Counter:
2038 0 : case eCSSUnit_Counters: aResult.Append(char16_t(')')); break;
2039 0 : case eCSSUnit_Local_Font: break;
2040 0 : case eCSSUnit_Font_Format: break;
2041 0 : case eCSSUnit_Function: break;
2042 0 : case eCSSUnit_Calc: break;
2043 0 : case eCSSUnit_Calc_Plus: break;
2044 0 : case eCSSUnit_Calc_Minus: break;
2045 0 : case eCSSUnit_Calc_Times_L: break;
2046 0 : case eCSSUnit_Calc_Times_R: break;
2047 0 : case eCSSUnit_Calc_Divided: break;
2048 0 : case eCSSUnit_Integer: break;
2049 0 : case eCSSUnit_Enumerated: break;
2050 0 : case eCSSUnit_EnumColor: break;
2051 0 : case eCSSUnit_RGBColor: break;
2052 0 : case eCSSUnit_RGBAColor: break;
2053 0 : case eCSSUnit_HexColor: break;
2054 0 : case eCSSUnit_ShortHexColor: break;
2055 0 : case eCSSUnit_HexColorAlpha: break;
2056 0 : case eCSSUnit_ShortHexColorAlpha: break;
2057 0 : case eCSSUnit_PercentageRGBColor: break;
2058 0 : case eCSSUnit_PercentageRGBAColor: break;
2059 0 : case eCSSUnit_HSLColor: break;
2060 0 : case eCSSUnit_HSLAColor: break;
2061 0 : case eCSSUnit_ComplexColor: break;
2062 0 : case eCSSUnit_Percent: aResult.Append(char16_t('%')); break;
2063 0 : case eCSSUnit_Number: break;
2064 0 : case eCSSUnit_Gradient: break;
2065 0 : case eCSSUnit_TokenStream: break;
2066 0 : case eCSSUnit_Pair: break;
2067 0 : case eCSSUnit_Triplet: break;
2068 0 : case eCSSUnit_Rect: break;
2069 0 : case eCSSUnit_List: break;
2070 0 : case eCSSUnit_ListDep: break;
2071 0 : case eCSSUnit_SharedList: break;
2072 0 : case eCSSUnit_PairList: break;
2073 0 : case eCSSUnit_PairListDep: break;
2074 0 : case eCSSUnit_GridTemplateAreas: break;
2075 :
2076 0 : case eCSSUnit_Inch: aResult.AppendLiteral("in"); break;
2077 0 : case eCSSUnit_Millimeter: aResult.AppendLiteral("mm"); break;
2078 0 : case eCSSUnit_PhysicalMillimeter: aResult.AppendLiteral("mozmm"); break;
2079 0 : case eCSSUnit_Centimeter: aResult.AppendLiteral("cm"); break;
2080 0 : case eCSSUnit_Point: aResult.AppendLiteral("pt"); break;
2081 0 : case eCSSUnit_Pica: aResult.AppendLiteral("pc"); break;
2082 0 : case eCSSUnit_Quarter: aResult.AppendLiteral("q"); break;
2083 :
2084 0 : case eCSSUnit_ViewportWidth: aResult.AppendLiteral("vw"); break;
2085 0 : case eCSSUnit_ViewportHeight: aResult.AppendLiteral("vh"); break;
2086 0 : case eCSSUnit_ViewportMin: aResult.AppendLiteral("vmin"); break;
2087 0 : case eCSSUnit_ViewportMax: aResult.AppendLiteral("vmax"); break;
2088 :
2089 0 : case eCSSUnit_EM: aResult.AppendLiteral("em"); break;
2090 0 : case eCSSUnit_XHeight: aResult.AppendLiteral("ex"); break;
2091 0 : case eCSSUnit_Char: aResult.AppendLiteral("ch"); break;
2092 0 : case eCSSUnit_RootEM: aResult.AppendLiteral("rem"); break;
2093 :
2094 0 : case eCSSUnit_Pixel: aResult.AppendLiteral("px"); break;
2095 :
2096 0 : case eCSSUnit_Degree: aResult.AppendLiteral("deg"); break;
2097 0 : case eCSSUnit_Grad: aResult.AppendLiteral("grad"); break;
2098 0 : case eCSSUnit_Radian: aResult.AppendLiteral("rad"); break;
2099 0 : case eCSSUnit_Turn: aResult.AppendLiteral("turn"); break;
2100 :
2101 0 : case eCSSUnit_Hertz: aResult.AppendLiteral("Hz"); break;
2102 0 : case eCSSUnit_Kilohertz: aResult.AppendLiteral("kHz"); break;
2103 :
2104 0 : case eCSSUnit_Seconds: aResult.Append(char16_t('s')); break;
2105 0 : case eCSSUnit_Milliseconds: aResult.AppendLiteral("ms"); break;
2106 :
2107 0 : case eCSSUnit_FlexFraction: aResult.AppendLiteral("fr"); break;
2108 : }
2109 : }
2110 :
2111 : size_t
2112 55 : nsCSSValue::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2113 : {
2114 55 : size_t n = 0;
2115 :
2116 55 : switch (GetUnit()) {
2117 : // No value: nothing extra to measure.
2118 : case eCSSUnit_Null:
2119 : case eCSSUnit_Auto:
2120 : case eCSSUnit_Inherit:
2121 : case eCSSUnit_Initial:
2122 : case eCSSUnit_Unset:
2123 : case eCSSUnit_None:
2124 : case eCSSUnit_Normal:
2125 : case eCSSUnit_System_Font:
2126 : case eCSSUnit_All:
2127 : case eCSSUnit_Dummy:
2128 : case eCSSUnit_DummyInherit:
2129 14 : break;
2130 :
2131 : // String
2132 : case eCSSUnit_String:
2133 : case eCSSUnit_Ident:
2134 : case eCSSUnit_Attr:
2135 : case eCSSUnit_Local_Font:
2136 : case eCSSUnit_Font_Format:
2137 : case eCSSUnit_Element:
2138 2 : n += mValue.mString->SizeOfIncludingThisIfUnshared(aMallocSizeOf);
2139 2 : break;
2140 :
2141 : // Array
2142 : case eCSSUnit_Array:
2143 : case eCSSUnit_Counter:
2144 : case eCSSUnit_Counters:
2145 : case eCSSUnit_Cubic_Bezier:
2146 : case eCSSUnit_Steps:
2147 : case eCSSUnit_Symbols:
2148 : case eCSSUnit_Function:
2149 : case eCSSUnit_Calc:
2150 : case eCSSUnit_Calc_Plus:
2151 : case eCSSUnit_Calc_Minus:
2152 : case eCSSUnit_Calc_Times_L:
2153 : case eCSSUnit_Calc_Times_R:
2154 : case eCSSUnit_Calc_Divided:
2155 0 : break;
2156 :
2157 : // URL
2158 : case eCSSUnit_URL:
2159 0 : n += mValue.mURL->SizeOfIncludingThis(aMallocSizeOf);
2160 0 : break;
2161 :
2162 : // Image
2163 : case eCSSUnit_Image:
2164 : // Not yet measured. Measurement may be added later if DMD finds it
2165 : // worthwhile.
2166 0 : break;
2167 :
2168 : // Gradient
2169 : case eCSSUnit_Gradient:
2170 2 : n += mValue.mGradient->SizeOfIncludingThis(aMallocSizeOf);
2171 2 : break;
2172 :
2173 : // TokenStream
2174 : case eCSSUnit_TokenStream:
2175 0 : n += mValue.mTokenStream->SizeOfIncludingThis(aMallocSizeOf);
2176 0 : break;
2177 :
2178 : // Pair
2179 : case eCSSUnit_Pair:
2180 0 : n += mValue.mPair->SizeOfIncludingThis(aMallocSizeOf);
2181 0 : break;
2182 :
2183 : // Triplet
2184 : case eCSSUnit_Triplet:
2185 0 : n += mValue.mTriplet->SizeOfIncludingThis(aMallocSizeOf);
2186 0 : break;
2187 :
2188 : // Rect
2189 : case eCSSUnit_Rect:
2190 0 : n += mValue.mRect->SizeOfIncludingThis(aMallocSizeOf);
2191 0 : break;
2192 :
2193 : // List
2194 : case eCSSUnit_List:
2195 2 : n += mValue.mList->SizeOfIncludingThis(aMallocSizeOf);
2196 2 : break;
2197 :
2198 : // ListDep: not measured because it's non-owning.
2199 : case eCSSUnit_ListDep:
2200 0 : break;
2201 :
2202 : // SharedList
2203 : case eCSSUnit_SharedList:
2204 : // Makes more sense not to measure, since it most cases the list
2205 : // will be shared.
2206 0 : break;
2207 :
2208 : // PairList
2209 : case eCSSUnit_PairList:
2210 2 : n += mValue.mPairList->SizeOfIncludingThis(aMallocSizeOf);
2211 2 : break;
2212 :
2213 : // PairListDep: not measured because it's non-owning.
2214 : case eCSSUnit_PairListDep:
2215 0 : break;
2216 :
2217 : // GridTemplateAreas
2218 : case eCSSUnit_GridTemplateAreas:
2219 0 : n += mValue.mGridTemplateAreas->SizeOfIncludingThis(aMallocSizeOf);
2220 0 : break;
2221 :
2222 : case eCSSUnit_FontFamilyList:
2223 0 : n += mValue.mFontFamilyList->SizeOfIncludingThis(aMallocSizeOf);
2224 0 : break;
2225 :
2226 : // Atom is always shared, and thus should not be counted.
2227 : case eCSSUnit_AtomIdent:
2228 0 : break;
2229 :
2230 : // Int: nothing extra to measure.
2231 : case eCSSUnit_Integer:
2232 : case eCSSUnit_Enumerated:
2233 : case eCSSUnit_EnumColor:
2234 8 : break;
2235 :
2236 : // Integer Color: nothing extra to measure.
2237 : case eCSSUnit_RGBColor:
2238 : case eCSSUnit_RGBAColor:
2239 : case eCSSUnit_HexColor:
2240 : case eCSSUnit_ShortHexColor:
2241 : case eCSSUnit_HexColorAlpha:
2242 : case eCSSUnit_ShortHexColorAlpha:
2243 8 : break;
2244 :
2245 : // Float Color
2246 : case eCSSUnit_PercentageRGBColor:
2247 : case eCSSUnit_PercentageRGBAColor:
2248 : case eCSSUnit_HSLColor:
2249 : case eCSSUnit_HSLAColor:
2250 4 : n += mValue.mFloatColor->SizeOfIncludingThis(aMallocSizeOf);
2251 4 : break;
2252 :
2253 : // Complex Color
2254 : case eCSSUnit_ComplexColor:
2255 0 : n += mValue.mComplexColor->SizeOfIncludingThis(aMallocSizeOf);
2256 0 : break;
2257 :
2258 : // Float: nothing extra to measure.
2259 : case eCSSUnit_Percent:
2260 : case eCSSUnit_Number:
2261 : case eCSSUnit_PhysicalMillimeter:
2262 : case eCSSUnit_ViewportWidth:
2263 : case eCSSUnit_ViewportHeight:
2264 : case eCSSUnit_ViewportMin:
2265 : case eCSSUnit_ViewportMax:
2266 : case eCSSUnit_EM:
2267 : case eCSSUnit_XHeight:
2268 : case eCSSUnit_Char:
2269 : case eCSSUnit_RootEM:
2270 : case eCSSUnit_Point:
2271 : case eCSSUnit_Inch:
2272 : case eCSSUnit_Millimeter:
2273 : case eCSSUnit_Centimeter:
2274 : case eCSSUnit_Pica:
2275 : case eCSSUnit_Pixel:
2276 : case eCSSUnit_Quarter:
2277 : case eCSSUnit_Degree:
2278 : case eCSSUnit_Grad:
2279 : case eCSSUnit_Turn:
2280 : case eCSSUnit_Radian:
2281 : case eCSSUnit_Hertz:
2282 : case eCSSUnit_Kilohertz:
2283 : case eCSSUnit_Seconds:
2284 : case eCSSUnit_Milliseconds:
2285 : case eCSSUnit_FlexFraction:
2286 13 : break;
2287 :
2288 : default:
2289 0 : MOZ_ASSERT(false, "bad nsCSSUnit");
2290 : break;
2291 : }
2292 :
2293 55 : return n;
2294 : }
2295 :
2296 : // --- nsCSSValueList -----------------
2297 :
2298 1182 : nsCSSValueList::~nsCSSValueList()
2299 : {
2300 591 : MOZ_COUNT_DTOR(nsCSSValueList);
2301 596 : NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, this, mNext);
2302 591 : }
2303 :
2304 : nsCSSValueList*
2305 0 : nsCSSValueList::Clone() const
2306 : {
2307 0 : nsCSSValueList* result = new nsCSSValueList(*this);
2308 0 : nsCSSValueList* dest = result;
2309 0 : const nsCSSValueList* src = this->mNext;
2310 0 : while (src) {
2311 0 : dest->mNext = new nsCSSValueList(*src);
2312 0 : dest = dest->mNext;
2313 0 : src = src->mNext;
2314 : }
2315 :
2316 0 : MOZ_ASSERT(result, "shouldn't return null; supposed to be infallible");
2317 0 : return result;
2318 : }
2319 :
2320 : void
2321 0 : nsCSSValueList::CloneInto(nsCSSValueList* aList) const
2322 : {
2323 0 : NS_ASSERTION(!aList->mNext, "Must be an empty list!");
2324 0 : aList->mValue = mValue;
2325 0 : aList->mNext = mNext ? mNext->Clone() : nullptr;
2326 0 : }
2327 :
2328 : static void
2329 0 : AppendValueListToString(const nsCSSValueList* val,
2330 : nsCSSPropertyID aProperty, nsAString& aResult,
2331 : nsCSSValue::Serialization aSerialization)
2332 : {
2333 : for (;;) {
2334 0 : val->mValue.AppendToString(aProperty, aResult, aSerialization);
2335 0 : val = val->mNext;
2336 0 : if (!val)
2337 0 : break;
2338 :
2339 0 : if (nsCSSProps::PropHasFlags(aProperty,
2340 : CSS_PROPERTY_VALUE_LIST_USES_COMMAS))
2341 0 : aResult.Append(char16_t(','));
2342 0 : aResult.Append(char16_t(' '));
2343 : }
2344 0 : }
2345 :
2346 : static void
2347 0 : AppendGridTemplateToString(const nsCSSValueList* val,
2348 : nsCSSPropertyID aProperty, nsAString& aResult,
2349 : nsCSSValue::Serialization aSerialization)
2350 : {
2351 : // This is called for the "list" that's the top-level value of the property.
2352 0 : bool isSubgrid = false;
2353 : for (;;) {
2354 0 : bool addSpaceSeparator = true;
2355 0 : nsCSSUnit unit = val->mValue.GetUnit();
2356 :
2357 0 : if (unit == eCSSUnit_Enumerated &&
2358 0 : val->mValue.GetIntValue() == NS_STYLE_GRID_TEMPLATE_SUBGRID) {
2359 0 : MOZ_ASSERT(!isSubgrid, "saw subgrid once already");
2360 0 : isSubgrid = true;
2361 0 : aResult.AppendLiteral("subgrid");
2362 :
2363 0 : } else if (unit == eCSSUnit_Pair) {
2364 : // This is a repeat 'auto-fill' / 'auto-fit'.
2365 0 : const nsCSSValuePair& pair = val->mValue.GetPairValue();
2366 0 : switch (pair.mXValue.GetIntValue()) {
2367 : case NS_STYLE_GRID_REPEAT_AUTO_FILL:
2368 0 : aResult.AppendLiteral("repeat(auto-fill, ");
2369 0 : break;
2370 : case NS_STYLE_GRID_REPEAT_AUTO_FIT:
2371 0 : aResult.AppendLiteral("repeat(auto-fit, ");
2372 0 : break;
2373 : default:
2374 0 : MOZ_ASSERT_UNREACHABLE("unexpected enum value");
2375 : }
2376 0 : const nsCSSValueList* repeatList = pair.mYValue.GetListValue();
2377 0 : if (repeatList->mValue.GetUnit() != eCSSUnit_Null) {
2378 0 : aResult.Append('[');
2379 0 : AppendValueListToString(repeatList->mValue.GetListValue(), aProperty,
2380 0 : aResult, aSerialization);
2381 0 : aResult.Append(']');
2382 0 : if (!isSubgrid) {
2383 0 : aResult.Append(' ');
2384 : }
2385 0 : } else if (isSubgrid) {
2386 0 : aResult.AppendLiteral("[]");
2387 : }
2388 0 : if (!isSubgrid) {
2389 0 : repeatList = repeatList->mNext;
2390 0 : repeatList->mValue.AppendToString(aProperty, aResult, aSerialization);
2391 0 : repeatList = repeatList->mNext;
2392 0 : if (repeatList->mValue.GetUnit() != eCSSUnit_Null) {
2393 0 : aResult.AppendLiteral(" [");
2394 0 : AppendValueListToString(repeatList->mValue.GetListValue(), aProperty,
2395 0 : aResult, aSerialization);
2396 0 : aResult.Append(']');
2397 : }
2398 : }
2399 0 : aResult.Append(')');
2400 :
2401 0 : } else if (unit == eCSSUnit_Null) {
2402 : // Empty or omitted <line-names>.
2403 0 : if (isSubgrid) {
2404 0 : aResult.AppendLiteral("[]");
2405 : } else {
2406 : // Serializes to nothing.
2407 0 : addSpaceSeparator = false; // Avoid a double space.
2408 : }
2409 :
2410 0 : } else if (unit == eCSSUnit_List || unit == eCSSUnit_ListDep) {
2411 : // Non-empty <line-names>
2412 0 : aResult.Append('[');
2413 0 : AppendValueListToString(val->mValue.GetListValue(), aProperty,
2414 0 : aResult, aSerialization);
2415 0 : aResult.Append(']');
2416 :
2417 : } else {
2418 : // <track-size>
2419 0 : val->mValue.AppendToString(aProperty, aResult, aSerialization);
2420 0 : if (!isSubgrid &&
2421 0 : val->mNext &&
2422 0 : val->mNext->mValue.GetUnit() == eCSSUnit_Null &&
2423 0 : !val->mNext->mNext) {
2424 : // Break out of the loop early to avoid a trailing space.
2425 0 : break;
2426 : }
2427 : }
2428 :
2429 0 : val = val->mNext;
2430 0 : if (!val) {
2431 0 : break;
2432 : }
2433 :
2434 0 : if (addSpaceSeparator) {
2435 0 : aResult.Append(char16_t(' '));
2436 : }
2437 0 : }
2438 0 : }
2439 :
2440 : void
2441 0 : nsCSSValueList::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
2442 : nsCSSValue::Serialization aSerialization) const
2443 : {
2444 0 : if (aProperty == eCSSProperty_grid_template_columns ||
2445 : aProperty == eCSSProperty_grid_template_rows) {
2446 0 : AppendGridTemplateToString(this, aProperty, aResult, aSerialization);
2447 : } else {
2448 0 : AppendValueListToString(this, aProperty, aResult, aSerialization);
2449 : }
2450 0 : }
2451 :
2452 : /* static */ bool
2453 47 : nsCSSValueList::Equal(const nsCSSValueList* aList1,
2454 : const nsCSSValueList* aList2)
2455 : {
2456 47 : if (aList1 == aList2) {
2457 42 : return true;
2458 : }
2459 :
2460 5 : const nsCSSValueList *p1 = aList1, *p2 = aList2;
2461 7 : for ( ; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
2462 5 : if (p1->mValue != p2->mValue)
2463 4 : return false;
2464 : }
2465 1 : return !p1 && !p2; // true if same length, false otherwise
2466 : }
2467 :
2468 : size_t
2469 0 : nsCSSValueList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2470 : {
2471 0 : size_t n = 0;
2472 0 : const nsCSSValueList* v = this;
2473 0 : while (v) {
2474 0 : n += aMallocSizeOf(v);
2475 0 : n += v->mValue.SizeOfExcludingThis(aMallocSizeOf);
2476 0 : v = v->mNext;
2477 : }
2478 0 : return n;
2479 : }
2480 :
2481 : size_t
2482 2 : nsCSSValueList_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2483 : {
2484 : // Only measure it if it's unshared, to avoid double-counting.
2485 2 : size_t n = 0;
2486 2 : if (mRefCnt <= 1) {
2487 2 : n += aMallocSizeOf(this);
2488 2 : n += mValue.SizeOfExcludingThis(aMallocSizeOf);
2489 2 : n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
2490 : }
2491 2 : return n;
2492 : }
2493 :
2494 : // --- nsCSSValueSharedList -----------------
2495 :
2496 0 : nsCSSValueSharedList::~nsCSSValueSharedList()
2497 : {
2498 0 : if (mHead) {
2499 0 : NS_CSS_DELETE_LIST_MEMBER(nsCSSValueList, mHead, mNext);
2500 0 : delete mHead;
2501 : }
2502 0 : }
2503 :
2504 : void
2505 0 : nsCSSValueSharedList::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
2506 : nsCSSValue::Serialization aSerialization) const
2507 : {
2508 0 : if (mHead) {
2509 0 : mHead->AppendToString(aProperty, aResult, aSerialization);
2510 : }
2511 0 : }
2512 :
2513 : bool
2514 8 : nsCSSValueSharedList::operator==(const nsCSSValueSharedList& aOther) const
2515 : {
2516 8 : return nsCSSValueList::Equal(mHead, aOther.mHead);
2517 : }
2518 :
2519 : size_t
2520 0 : nsCSSValueSharedList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2521 : {
2522 : // Only measure it if it's unshared, to avoid double-counting.
2523 0 : size_t n = 0;
2524 0 : if (mRefCnt <= 1) {
2525 0 : n += aMallocSizeOf(this);
2526 0 : n += mHead->SizeOfIncludingThis(aMallocSizeOf);
2527 : }
2528 0 : return n;
2529 : }
2530 :
2531 : // --- nsCSSRect -----------------
2532 :
2533 2701 : nsCSSRect::nsCSSRect(void)
2534 : {
2535 2701 : MOZ_COUNT_CTOR(nsCSSRect);
2536 2701 : }
2537 :
2538 0 : nsCSSRect::nsCSSRect(const nsCSSRect& aCopy)
2539 : : mTop(aCopy.mTop),
2540 : mRight(aCopy.mRight),
2541 : mBottom(aCopy.mBottom),
2542 0 : mLeft(aCopy.mLeft)
2543 : {
2544 0 : MOZ_COUNT_CTOR(nsCSSRect);
2545 0 : }
2546 :
2547 4334 : nsCSSRect::~nsCSSRect()
2548 : {
2549 2167 : MOZ_COUNT_DTOR(nsCSSRect);
2550 2167 : }
2551 :
2552 : void
2553 0 : nsCSSRect::AppendToString(nsCSSPropertyID aProperty, nsAString& aResult,
2554 : nsCSSValue::Serialization aSerialization) const
2555 : {
2556 0 : MOZ_ASSERT(mTop.GetUnit() != eCSSUnit_Null &&
2557 : mTop.GetUnit() != eCSSUnit_Inherit &&
2558 : mTop.GetUnit() != eCSSUnit_Initial &&
2559 : mTop.GetUnit() != eCSSUnit_Unset,
2560 : "parser should have used a bare value");
2561 :
2562 0 : if (eCSSProperty_border_image_slice == aProperty ||
2563 0 : eCSSProperty_border_image_width == aProperty ||
2564 : eCSSProperty_border_image_outset == aProperty) {
2565 0 : nsCSSPropertyID props[] = { aProperty, aProperty, aProperty, aProperty };
2566 0 : const nsCSSValue* values[] = { &mTop, &mRight, &mBottom, &mLeft };
2567 : nsCSSValue::AppendSidesShorthandToString(props, values,
2568 0 : aResult, aSerialization);
2569 0 : } else if (eCSSProperty_DOM == aProperty) {
2570 0 : NS_NAMED_LITERAL_STRING(space, " ");
2571 :
2572 0 : mTop.AppendToString(aProperty, aResult, aSerialization);
2573 0 : aResult.Append(space);
2574 0 : mRight.AppendToString(aProperty, aResult, aSerialization);
2575 0 : aResult.Append(space);
2576 0 : mBottom.AppendToString(aProperty, aResult, aSerialization);
2577 0 : aResult.Append(space);
2578 0 : mLeft.AppendToString(aProperty, aResult, aSerialization);
2579 : } else {
2580 0 : NS_NAMED_LITERAL_STRING(comma, ", ");
2581 :
2582 0 : aResult.AppendLiteral("rect(");
2583 0 : mTop.AppendToString(aProperty, aResult, aSerialization);
2584 0 : aResult.Append(comma);
2585 0 : mRight.AppendToString(aProperty, aResult, aSerialization);
2586 0 : aResult.Append(comma);
2587 0 : mBottom.AppendToString(aProperty, aResult, aSerialization);
2588 0 : aResult.Append(comma);
2589 0 : mLeft.AppendToString(aProperty, aResult, aSerialization);
2590 0 : aResult.Append(char16_t(')'));
2591 : }
2592 0 : }
2593 :
2594 723 : void nsCSSRect::SetAllSidesTo(const nsCSSValue& aValue)
2595 : {
2596 723 : mTop = aValue;
2597 723 : mRight = aValue;
2598 723 : mBottom = aValue;
2599 723 : mLeft = aValue;
2600 723 : }
2601 :
2602 : size_t
2603 0 : nsCSSRect_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2604 : {
2605 : // Only measure it if it's unshared, to avoid double-counting.
2606 0 : size_t n = 0;
2607 0 : if (mRefCnt <= 1) {
2608 0 : n += aMallocSizeOf(this);
2609 0 : n += mTop .SizeOfExcludingThis(aMallocSizeOf);
2610 0 : n += mRight .SizeOfExcludingThis(aMallocSizeOf);
2611 0 : n += mBottom.SizeOfExcludingThis(aMallocSizeOf);
2612 0 : n += mLeft .SizeOfExcludingThis(aMallocSizeOf);
2613 : }
2614 0 : return n;
2615 : }
2616 :
2617 : static_assert(eSideTop == 0 && eSideRight == 1 &&
2618 : eSideBottom == 2 && eSideLeft == 3,
2619 : "box side constants not top/right/bottom/left == 0/1/2/3");
2620 :
2621 : /* static */ const nsCSSRect::side_type nsCSSRect::sides[4] = {
2622 : &nsCSSRect::mTop,
2623 : &nsCSSRect::mRight,
2624 : &nsCSSRect::mBottom,
2625 : &nsCSSRect::mLeft,
2626 : };
2627 :
2628 : // --- nsCSSValuePair -----------------
2629 :
2630 : void
2631 0 : nsCSSValuePair::AppendToString(nsCSSPropertyID aProperty,
2632 : nsAString& aResult,
2633 : nsCSSValue::Serialization aSerialization) const
2634 : {
2635 0 : mXValue.AppendToString(aProperty, aResult, aSerialization);
2636 0 : if (mYValue.GetUnit() != eCSSUnit_Null) {
2637 0 : aResult.Append(char16_t(' '));
2638 0 : mYValue.AppendToString(aProperty, aResult, aSerialization);
2639 : }
2640 0 : }
2641 :
2642 : size_t
2643 2 : nsCSSValuePair::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2644 : {
2645 2 : size_t n = 0;
2646 2 : n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
2647 2 : n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
2648 2 : return n;
2649 : }
2650 :
2651 : size_t
2652 0 : nsCSSValuePair_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2653 : {
2654 : // Only measure it if it's unshared, to avoid double-counting.
2655 0 : size_t n = 0;
2656 0 : if (mRefCnt <= 1) {
2657 0 : n += aMallocSizeOf(this);
2658 0 : n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
2659 0 : n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
2660 : }
2661 0 : return n;
2662 : }
2663 :
2664 : // --- nsCSSValueTriplet -----------------
2665 :
2666 : void
2667 0 : nsCSSValueTriplet::AppendToString(nsCSSPropertyID aProperty,
2668 : nsAString& aResult,
2669 : nsCSSValue::Serialization aSerialization) const
2670 : {
2671 0 : mXValue.AppendToString(aProperty, aResult, aSerialization);
2672 0 : if (mYValue.GetUnit() != eCSSUnit_Null) {
2673 0 : aResult.Append(char16_t(' '));
2674 0 : mYValue.AppendToString(aProperty, aResult, aSerialization);
2675 0 : if (mZValue.GetUnit() != eCSSUnit_Null) {
2676 0 : aResult.Append(char16_t(' '));
2677 0 : mZValue.AppendToString(aProperty, aResult, aSerialization);
2678 : }
2679 : }
2680 0 : }
2681 :
2682 : size_t
2683 0 : nsCSSValueTriplet_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2684 : {
2685 : // Only measure it if it's unshared, to avoid double-counting.
2686 0 : size_t n = 0;
2687 0 : if (mRefCnt <= 1) {
2688 0 : n += aMallocSizeOf(this);
2689 0 : n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
2690 0 : n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
2691 0 : n += mZValue.SizeOfExcludingThis(aMallocSizeOf);
2692 : }
2693 0 : return n;
2694 : }
2695 :
2696 : // --- nsCSSValuePairList -----------------
2697 :
2698 62 : nsCSSValuePairList::~nsCSSValuePairList()
2699 : {
2700 31 : MOZ_COUNT_DTOR(nsCSSValuePairList);
2701 36 : NS_CSS_DELETE_LIST_MEMBER(nsCSSValuePairList, this, mNext);
2702 31 : }
2703 :
2704 : nsCSSValuePairList*
2705 0 : nsCSSValuePairList::Clone() const
2706 : {
2707 0 : nsCSSValuePairList* result = new nsCSSValuePairList(*this);
2708 0 : nsCSSValuePairList* dest = result;
2709 0 : const nsCSSValuePairList* src = this->mNext;
2710 0 : while (src) {
2711 0 : dest->mNext = new nsCSSValuePairList(*src);
2712 0 : dest = dest->mNext;
2713 0 : src = src->mNext;
2714 : }
2715 :
2716 0 : MOZ_ASSERT(result, "shouldn't return null; supposed to be infallible");
2717 0 : return result;
2718 : }
2719 :
2720 : void
2721 0 : nsCSSValuePairList::AppendToString(nsCSSPropertyID aProperty,
2722 : nsAString& aResult,
2723 : nsCSSValue::Serialization aSerialization) const
2724 : {
2725 0 : const nsCSSValuePairList* item = this;
2726 0 : for (;;) {
2727 0 : MOZ_ASSERT(item->mXValue.GetUnit() != eCSSUnit_Null,
2728 : "unexpected null unit");
2729 0 : item->mXValue.AppendToString(aProperty, aResult, aSerialization);
2730 0 : if (item->mXValue.GetUnit() != eCSSUnit_Inherit &&
2731 0 : item->mXValue.GetUnit() != eCSSUnit_Initial &&
2732 0 : item->mXValue.GetUnit() != eCSSUnit_Unset &&
2733 0 : item->mYValue.GetUnit() != eCSSUnit_Null) {
2734 0 : aResult.Append(char16_t(' '));
2735 0 : item->mYValue.AppendToString(aProperty, aResult, aSerialization);
2736 : }
2737 0 : item = item->mNext;
2738 0 : if (!item)
2739 0 : break;
2740 :
2741 0 : if (nsCSSProps::PropHasFlags(aProperty,
2742 0 : CSS_PROPERTY_VALUE_LIST_USES_COMMAS) ||
2743 0 : aProperty == eCSSProperty_clip_path ||
2744 : aProperty == eCSSProperty_shape_outside)
2745 0 : aResult.Append(char16_t(','));
2746 0 : aResult.Append(char16_t(' '));
2747 : }
2748 0 : }
2749 :
2750 : /* static */ bool
2751 3 : nsCSSValuePairList::Equal(const nsCSSValuePairList* aList1,
2752 : const nsCSSValuePairList* aList2)
2753 : {
2754 3 : if (aList1 == aList2) {
2755 0 : return true;
2756 : }
2757 :
2758 3 : const nsCSSValuePairList *p1 = aList1, *p2 = aList2;
2759 3 : for ( ; p1 && p2; p1 = p1->mNext, p2 = p2->mNext) {
2760 3 : if (p1->mXValue != p2->mXValue ||
2761 0 : p1->mYValue != p2->mYValue)
2762 3 : return false;
2763 : }
2764 0 : return !p1 && !p2; // true if same length, false otherwise
2765 : }
2766 :
2767 : size_t
2768 0 : nsCSSValuePairList::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2769 : {
2770 0 : size_t n = 0;
2771 0 : const nsCSSValuePairList* v = this;
2772 0 : while (v) {
2773 0 : n += aMallocSizeOf(v);
2774 0 : n += v->mXValue.SizeOfExcludingThis(aMallocSizeOf);
2775 0 : n += v->mYValue.SizeOfExcludingThis(aMallocSizeOf);
2776 0 : v = v->mNext;
2777 : }
2778 0 : return n;
2779 : }
2780 :
2781 : size_t
2782 2 : nsCSSValuePairList_heap::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2783 : {
2784 : // Only measure it if it's unshared, to avoid double-counting.
2785 2 : size_t n = 0;
2786 2 : if (mRefCnt <= 1) {
2787 2 : n += aMallocSizeOf(this);
2788 2 : n += mXValue.SizeOfExcludingThis(aMallocSizeOf);
2789 2 : n += mYValue.SizeOfExcludingThis(aMallocSizeOf);
2790 2 : n += mNext ? mNext->SizeOfIncludingThis(aMallocSizeOf) : 0;
2791 : }
2792 2 : return n;
2793 : }
2794 :
2795 : size_t
2796 0 : nsCSSValue::Array::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2797 : {
2798 0 : size_t n = aMallocSizeOf(this);
2799 0 : for (size_t i = 0; i < mCount; i++) {
2800 0 : n += mArray[i].SizeOfExcludingThis(aMallocSizeOf);
2801 : }
2802 0 : return n;
2803 : }
2804 :
2805 40 : css::URLValueData::URLValueData(already_AddRefed<PtrHolder<nsIURI>> aURI,
2806 : const nsAString& aString,
2807 40 : already_AddRefed<URLExtraData> aExtraData)
2808 40 : : mURI(Move(aURI))
2809 : , mString(aString)
2810 40 : , mExtraData(Move(aExtraData))
2811 120 : , mURIResolved(true)
2812 : {
2813 40 : MOZ_ASSERT(mExtraData);
2814 40 : MOZ_ASSERT(mExtraData->GetPrincipal());
2815 40 : }
2816 :
2817 667 : css::URLValueData::URLValueData(const nsAString& aString,
2818 667 : already_AddRefed<URLExtraData> aExtraData)
2819 : : mString(aString)
2820 667 : , mExtraData(Move(aExtraData))
2821 1334 : , mURIResolved(false)
2822 : {
2823 667 : MOZ_ASSERT(mExtraData);
2824 667 : MOZ_ASSERT(mExtraData->GetPrincipal());
2825 667 : }
2826 :
2827 : bool
2828 0 : css::URLValueData::Equals(const URLValueData& aOther) const
2829 : {
2830 0 : MOZ_ASSERT(NS_IsMainThread());
2831 :
2832 : bool eq;
2833 0 : const URLExtraData* self = mExtraData;
2834 0 : const URLExtraData* other = aOther.mExtraData;
2835 0 : return mString == aOther.mString &&
2836 0 : (GetURI() == aOther.GetURI() || // handles null == null
2837 0 : (mURI && aOther.mURI &&
2838 0 : NS_SUCCEEDED(mURI->Equals(aOther.mURI, &eq)) &&
2839 0 : eq)) &&
2840 0 : (self->BaseURI() == other->BaseURI() ||
2841 0 : (NS_SUCCEEDED(self->BaseURI()->Equals(other->BaseURI(), &eq)) &&
2842 0 : eq)) &&
2843 0 : (self->GetPrincipal() == other->GetPrincipal() ||
2844 0 : self->GetPrincipal()->Equals(other->GetPrincipal())) &&
2845 0 : IsLocalRef() == aOther.IsLocalRef();
2846 : }
2847 :
2848 : bool
2849 16 : css::URLValueData::DefinitelyEqualURIs(const URLValueData& aOther) const
2850 : {
2851 31 : return mExtraData->BaseURI() == aOther.mExtraData->BaseURI() &&
2852 31 : mString == aOther.mString;
2853 : }
2854 :
2855 : bool
2856 5 : css::URLValueData::DefinitelyEqualURIsAndPrincipal(
2857 : const URLValueData& aOther) const
2858 : {
2859 10 : return mExtraData->GetPrincipal() == aOther.mExtraData->GetPrincipal() &&
2860 10 : DefinitelyEqualURIs(aOther);
2861 : }
2862 :
2863 : nsIURI*
2864 1514 : css::URLValueData::GetURI() const
2865 : {
2866 1514 : MOZ_ASSERT(NS_IsMainThread());
2867 :
2868 1514 : if (!mURIResolved) {
2869 105 : MOZ_ASSERT(!mURI);
2870 210 : nsCOMPtr<nsIURI> newURI;
2871 315 : NS_NewURI(getter_AddRefs(newURI),
2872 210 : NS_ConvertUTF16toUTF8(mString),
2873 105 : nullptr, mExtraData->BaseURI());
2874 210 : mURI = new PtrHolder<nsIURI>("URLValueData::mURI", newURI.forget());
2875 105 : mURIResolved = true;
2876 : }
2877 :
2878 1514 : return mURI;
2879 : }
2880 :
2881 : bool
2882 18 : css::URLValueData::IsLocalRef() const
2883 : {
2884 18 : if (mIsLocalRef.isNothing()) {
2885 : // IsLocalRefURL is O(N), use it only when IsLocalRef is called.
2886 3 : mIsLocalRef.emplace(nsContentUtils::IsLocalRefURL(mString));
2887 : }
2888 :
2889 18 : return mIsLocalRef.value();
2890 : }
2891 :
2892 : bool
2893 0 : css::URLValueData::HasRef() const
2894 : {
2895 0 : if (IsLocalRef()) {
2896 0 : return true;
2897 : }
2898 :
2899 0 : nsIURI* uri = GetURI();
2900 0 : if (!uri) {
2901 0 : return false;
2902 : }
2903 :
2904 0 : nsAutoCString ref;
2905 0 : nsresult rv = uri->GetRef(ref);
2906 0 : if (NS_SUCCEEDED(rv) && !ref.IsEmpty()) {
2907 0 : return true;
2908 : }
2909 :
2910 0 : return false;
2911 : }
2912 :
2913 : bool
2914 2 : css::URLValueData::MightHaveRef() const
2915 : {
2916 2 : if (mMightHaveRef.isNothing()) {
2917 : // ::MightHaveRef is O(N), use it only use it only when MightHaveRef is
2918 : // called.
2919 1 : mMightHaveRef.emplace(::MightHaveRef(mString));
2920 : }
2921 :
2922 2 : return mMightHaveRef.value();
2923 : }
2924 :
2925 : already_AddRefed<nsIURI>
2926 8 : css::URLValueData::ResolveLocalRef(nsIURI* aURI) const
2927 : {
2928 16 : nsCOMPtr<nsIURI> result = GetURI();
2929 :
2930 8 : if (result && IsLocalRef()) {
2931 16 : nsCString ref;
2932 8 : mURI->GetRef(ref);
2933 :
2934 8 : aURI->Clone(getter_AddRefs(result));
2935 8 : result->SetRef(ref);
2936 : }
2937 :
2938 16 : return result.forget();
2939 : }
2940 :
2941 : already_AddRefed<nsIURI>
2942 0 : css::URLValueData::ResolveLocalRef(nsIContent* aContent) const
2943 : {
2944 0 : nsCOMPtr<nsIURI> url = aContent->GetBaseURI();
2945 0 : return ResolveLocalRef(url);
2946 : }
2947 :
2948 : void
2949 0 : css::URLValueData::GetSourceString(nsString& aRef) const
2950 : {
2951 0 : nsIURI* uri = GetURI();
2952 0 : if (!uri) {
2953 0 : aRef.Truncate();
2954 0 : return;
2955 : }
2956 :
2957 0 : nsCString cref;
2958 0 : if (IsLocalRef()) {
2959 : // XXXheycam It's possible we can just return mString in this case, since
2960 : // it should be the "#fragment" string the URLValueData was created with.
2961 0 : uri->GetRef(cref);
2962 0 : cref.Insert('#', 0);
2963 : } else {
2964 : // It's not entirely clear how to best handle failure here. Ensuring the
2965 : // string is empty seems safest.
2966 0 : nsresult rv = uri->GetSpec(cref);
2967 0 : if (NS_FAILED(rv)) {
2968 0 : cref.Truncate();
2969 : }
2970 : }
2971 :
2972 0 : aRef = NS_ConvertUTF8toUTF16(cref);
2973 : }
2974 :
2975 : bool
2976 0 : css::URLValueData::EqualsExceptRef(nsIURI* aURI) const
2977 : {
2978 0 : nsIURI* uri = GetURI();
2979 0 : if (!uri) {
2980 0 : return false;
2981 : }
2982 :
2983 0 : bool ret = false;
2984 0 : uri->EqualsExceptRef(aURI, &ret);
2985 0 : return ret;
2986 : }
2987 :
2988 : size_t
2989 0 : css::URLValueData::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
2990 : {
2991 0 : size_t n = 0;
2992 0 : n += mString.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
2993 :
2994 : // Measurement of the following members may be added later if DMD finds it
2995 : // is worthwhile:
2996 : // - mURI
2997 : // - mExtraData
2998 0 : return n;
2999 : }
3000 :
3001 667 : URLValue::URLValue(const nsAString& aString, nsIURI* aBaseURI, nsIURI* aReferrer,
3002 667 : nsIPrincipal* aOriginPrincipal)
3003 1334 : : URLValueData(aString, do_AddRef(new URLExtraData(aBaseURI, aReferrer,
3004 2001 : aOriginPrincipal)))
3005 : {
3006 667 : MOZ_ASSERT(NS_IsMainThread());
3007 667 : }
3008 :
3009 0 : URLValue::URLValue(nsIURI* aURI, const nsAString& aString, nsIURI* aBaseURI,
3010 0 : nsIURI* aReferrer, nsIPrincipal* aOriginPrincipal)
3011 0 : : URLValueData(do_AddRef(new PtrHolder<nsIURI>("URLValueData::mURI", aURI)),
3012 : aString,
3013 0 : do_AddRef(new URLExtraData(aBaseURI, aReferrer,
3014 0 : aOriginPrincipal)))
3015 : {
3016 0 : MOZ_ASSERT(NS_IsMainThread());
3017 0 : }
3018 :
3019 : size_t
3020 0 : css::URLValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
3021 : {
3022 : // Only measure it if it's unshared, to avoid double-counting.
3023 0 : size_t n = 0;
3024 0 : if (mRefCnt <= 1) {
3025 0 : n += aMallocSizeOf(this);
3026 0 : n += URLValueData::SizeOfExcludingThis(aMallocSizeOf);
3027 : }
3028 0 : return n;
3029 : }
3030 :
3031 40 : css::ImageValue::ImageValue(nsIURI* aURI, const nsAString& aString,
3032 : already_AddRefed<URLExtraData> aExtraData,
3033 40 : nsIDocument* aDocument)
3034 80 : : URLValueData(do_AddRef(new PtrHolder<nsIURI>("URLValueData::mURI", aURI)),
3035 120 : aString, Move(aExtraData))
3036 : {
3037 40 : Initialize(aDocument);
3038 40 : }
3039 :
3040 0 : css::ImageValue::ImageValue(const nsAString& aString,
3041 0 : already_AddRefed<URLExtraData> aExtraData)
3042 0 : : URLValueData(aString, Move(aExtraData))
3043 : {
3044 0 : }
3045 :
3046 : void
3047 40 : css::ImageValue::Initialize(nsIDocument* aDocument)
3048 : {
3049 40 : MOZ_ASSERT(NS_IsMainThread());
3050 :
3051 : // NB: If aDocument is not the original document, we may not be able to load
3052 : // images from aDocument. Instead we do the image load from the original doc
3053 : // and clone it to aDocument.
3054 40 : nsIDocument* loadingDoc = aDocument->GetOriginalDocument();
3055 40 : if (!loadingDoc) {
3056 40 : loadingDoc = aDocument;
3057 : }
3058 :
3059 40 : if (!mLoadedImage) {
3060 40 : loadingDoc->StyleImageLoader()->LoadImage(GetURI(),
3061 : mExtraData->GetPrincipal(),
3062 40 : mExtraData->GetReferrer(), this);
3063 :
3064 40 : mLoadedImage = true;
3065 : }
3066 :
3067 40 : aDocument->StyleImageLoader()->MaybeRegisterCSSImage(this);
3068 40 : }
3069 :
3070 0 : css::ImageValue::~ImageValue()
3071 : {
3072 0 : MOZ_ASSERT(NS_IsMainThread() || mRequests.Count() == 0,
3073 : "Destructor should run on main thread, or on non-main thread "
3074 : "when mRequest is empty!");
3075 :
3076 0 : for (auto iter = mRequests.Iter(); !iter.Done(); iter.Next()) {
3077 0 : nsIDocument* doc = iter.Key();
3078 0 : RefPtr<imgRequestProxy>& proxy = iter.Data();
3079 :
3080 0 : if (doc) {
3081 0 : doc->StyleImageLoader()->DeregisterCSSImage(this);
3082 : }
3083 :
3084 0 : if (proxy) {
3085 0 : proxy->CancelAndForgetObserver(NS_BINDING_ABORTED);
3086 : }
3087 :
3088 0 : iter.Remove();
3089 : }
3090 0 : }
3091 :
3092 : size_t
3093 0 : css::ComplexColorValue::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
3094 : {
3095 : // Only measure it if it's unshared, to avoid double-counting.
3096 0 : size_t n = 0;
3097 0 : if (mRefCnt <= 1) {
3098 0 : n += aMallocSizeOf(this);
3099 : }
3100 0 : return n;
3101 : }
3102 :
3103 141 : nsCSSValueGradientStop::nsCSSValueGradientStop()
3104 : : mLocation(eCSSUnit_None),
3105 : mColor(eCSSUnit_Null),
3106 141 : mIsInterpolationHint(false)
3107 : {
3108 141 : MOZ_COUNT_CTOR(nsCSSValueGradientStop);
3109 141 : }
3110 :
3111 0 : nsCSSValueGradientStop::nsCSSValueGradientStop(const nsCSSValueGradientStop& aOther)
3112 : : mLocation(aOther.mLocation),
3113 : mColor(aOther.mColor),
3114 0 : mIsInterpolationHint(aOther.mIsInterpolationHint)
3115 : {
3116 0 : MOZ_COUNT_CTOR(nsCSSValueGradientStop);
3117 0 : }
3118 :
3119 38 : nsCSSValueGradientStop::~nsCSSValueGradientStop()
3120 : {
3121 19 : MOZ_COUNT_DTOR(nsCSSValueGradientStop);
3122 19 : }
3123 :
3124 : size_t
3125 6 : nsCSSValueGradientStop::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
3126 : {
3127 6 : size_t n = 0;
3128 6 : n += mLocation.SizeOfExcludingThis(aMallocSizeOf);
3129 6 : n += mColor .SizeOfExcludingThis(aMallocSizeOf);
3130 6 : return n;
3131 : }
3132 :
3133 51 : nsCSSValueGradient::nsCSSValueGradient(bool aIsRadial,
3134 51 : bool aIsRepeating)
3135 : : mIsRadial(aIsRadial),
3136 : mIsRepeating(aIsRepeating),
3137 : mIsLegacySyntax(false),
3138 : mIsMozLegacySyntax(false),
3139 : mIsExplicitSize(false),
3140 : mBgPos(eCSSUnit_None),
3141 51 : mAngle(eCSSUnit_None)
3142 : {
3143 51 : mRadialValues[0].SetNoneValue();
3144 51 : mRadialValues[1].SetNoneValue();
3145 51 : }
3146 :
3147 : size_t
3148 2 : nsCSSValueGradient::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
3149 : {
3150 : // Only measure it if it's unshared, to avoid double-counting.
3151 2 : size_t n = 0;
3152 2 : if (mRefCnt <= 1) {
3153 2 : n += aMallocSizeOf(this);
3154 2 : n += mBgPos.SizeOfExcludingThis(aMallocSizeOf);
3155 2 : n += mAngle.SizeOfExcludingThis(aMallocSizeOf);
3156 2 : n += mRadialValues[0].SizeOfExcludingThis(aMallocSizeOf);
3157 2 : n += mRadialValues[1].SizeOfExcludingThis(aMallocSizeOf);
3158 2 : n += mStops.ShallowSizeOfExcludingThis(aMallocSizeOf);
3159 8 : for (uint32_t i = 0; i < mStops.Length(); i++) {
3160 6 : n += mStops[i].SizeOfExcludingThis(aMallocSizeOf);
3161 : }
3162 : }
3163 2 : return n;
3164 : }
3165 :
3166 : // --- nsCSSValueTokenStream ------------
3167 :
3168 606 : nsCSSValueTokenStream::nsCSSValueTokenStream()
3169 : : mPropertyID(eCSSProperty_UNKNOWN)
3170 : , mShorthandPropertyID(eCSSProperty_UNKNOWN)
3171 606 : , mLevel(SheetType::Count)
3172 606 : {}
3173 :
3174 7 : nsCSSValueTokenStream::~nsCSSValueTokenStream()
3175 7 : {}
3176 :
3177 : size_t
3178 0 : nsCSSValueTokenStream::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
3179 : {
3180 : // Only measure it if it's unshared, to avoid double-counting.
3181 0 : size_t n = 0;
3182 0 : if (mRefCnt <= 1) {
3183 0 : n += aMallocSizeOf(this);
3184 0 : n += mTokenStream.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
3185 : }
3186 0 : return n;
3187 : }
3188 :
3189 : // --- nsCSSValueFloatColor -------------
3190 :
3191 : bool
3192 0 : nsCSSValueFloatColor::operator==(nsCSSValueFloatColor& aOther) const
3193 : {
3194 0 : return mComponent1 == aOther.mComponent1 &&
3195 0 : mComponent2 == aOther.mComponent2 &&
3196 0 : mComponent3 == aOther.mComponent3 &&
3197 0 : mAlpha == aOther.mAlpha;
3198 : }
3199 :
3200 : nscolor
3201 59 : nsCSSValueFloatColor::GetColorValue(nsCSSUnit aUnit) const
3202 : {
3203 59 : MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
3204 :
3205 : // We should clamp each component value since eCSSUnit_PercentageRGBColor
3206 : // and eCSSUnit_PercentageRGBAColor may store values greater than 1.0.
3207 59 : if (aUnit == eCSSUnit_PercentageRGBColor ||
3208 : aUnit == eCSSUnit_PercentageRGBAColor) {
3209 0 : return NS_RGBA(
3210 : // We need to clamp before multiplying by 255.0f to avoid overflow.
3211 : NSToIntRound(mozilla::clamped(mComponent1, 0.0f, 1.0f) * 255.0f),
3212 : NSToIntRound(mozilla::clamped(mComponent2, 0.0f, 1.0f) * 255.0f),
3213 : NSToIntRound(mozilla::clamped(mComponent3, 0.0f, 1.0f) * 255.0f),
3214 : NSToIntRound(mozilla::clamped(mAlpha, 0.0f, 1.0f) * 255.0f));
3215 : }
3216 :
3217 : // HSL color
3218 59 : MOZ_ASSERT(aUnit == eCSSUnit_HSLColor ||
3219 : aUnit == eCSSUnit_HSLAColor);
3220 59 : nscolor hsl = NS_HSL2RGB(mComponent1, mComponent2, mComponent3);
3221 59 : return NS_RGBA(NS_GET_R(hsl),
3222 : NS_GET_G(hsl),
3223 : NS_GET_B(hsl),
3224 : NSToIntRound(mAlpha * 255.0f));
3225 : }
3226 :
3227 : bool
3228 0 : nsCSSValueFloatColor::IsNonTransparentColor() const
3229 : {
3230 0 : return mAlpha > 0.0f;
3231 : }
3232 :
3233 : void
3234 0 : nsCSSValueFloatColor::AppendToString(nsCSSUnit aUnit, nsAString& aResult) const
3235 : {
3236 : // Similar to the rgb()/rgba() case in nsCSSValue::AppendToString. We omit the
3237 : // alpha component if it's equal to 1.0f (full opaque). Also, we try to
3238 : // preserve the author-specified function name, unless it's rgba()/hsla() and
3239 : // we're omitting the alpha component - then we use rgb()/hsl().
3240 0 : MOZ_ASSERT(nsCSSValue::IsFloatColorUnit(aUnit), "unexpected unit");
3241 :
3242 0 : bool showAlpha = (mAlpha != 1.0f);
3243 0 : bool isHSL = (aUnit == eCSSUnit_HSLColor ||
3244 0 : aUnit == eCSSUnit_HSLAColor);
3245 :
3246 0 : if (isHSL) {
3247 0 : aResult.AppendLiteral("hsl");
3248 : } else {
3249 0 : aResult.AppendLiteral("rgb");
3250 : }
3251 0 : if (showAlpha && (aUnit == eCSSUnit_HSLAColor || aUnit == eCSSUnit_PercentageRGBAColor)) {
3252 0 : aResult.AppendLiteral("a(");
3253 : } else {
3254 0 : aResult.Append('(');
3255 : }
3256 0 : if (isHSL) {
3257 0 : aResult.AppendFloat(mComponent1 * 360.0f);
3258 0 : aResult.AppendLiteral(", ");
3259 : } else {
3260 0 : aResult.AppendFloat(mComponent1 * 100.0f);
3261 0 : aResult.AppendLiteral("%, ");
3262 : }
3263 0 : aResult.AppendFloat(mComponent2 * 100.0f);
3264 0 : aResult.AppendLiteral("%, ");
3265 0 : aResult.AppendFloat(mComponent3 * 100.0f);
3266 0 : if (showAlpha) {
3267 0 : aResult.AppendLiteral("%, ");
3268 0 : aResult.AppendFloat(mAlpha);
3269 0 : aResult.Append(')');
3270 : } else {
3271 0 : aResult.AppendLiteral("%)");
3272 : }
3273 0 : }
3274 :
3275 : size_t
3276 4 : nsCSSValueFloatColor::SizeOfIncludingThis(
3277 : mozilla::MallocSizeOf aMallocSizeOf) const
3278 : {
3279 : // Only measure it if it's unshared, to avoid double-counting.
3280 4 : size_t n = 0;
3281 4 : if (mRefCnt <= 1) {
3282 4 : n += aMallocSizeOf(this);
3283 : }
3284 4 : return n;
3285 : }
3286 :
3287 : // --- nsCSSCornerSizes -----------------
3288 :
3289 0 : nsCSSCornerSizes::nsCSSCornerSizes(void)
3290 : {
3291 0 : MOZ_COUNT_CTOR(nsCSSCornerSizes);
3292 0 : }
3293 :
3294 0 : nsCSSCornerSizes::nsCSSCornerSizes(const nsCSSCornerSizes& aCopy)
3295 : : mTopLeft(aCopy.mTopLeft),
3296 : mTopRight(aCopy.mTopRight),
3297 : mBottomRight(aCopy.mBottomRight),
3298 0 : mBottomLeft(aCopy.mBottomLeft)
3299 : {
3300 0 : MOZ_COUNT_CTOR(nsCSSCornerSizes);
3301 0 : }
3302 :
3303 0 : nsCSSCornerSizes::~nsCSSCornerSizes()
3304 : {
3305 0 : MOZ_COUNT_DTOR(nsCSSCornerSizes);
3306 0 : }
3307 :
3308 : void
3309 0 : nsCSSCornerSizes::Reset()
3310 : {
3311 0 : NS_FOR_CSS_FULL_CORNERS(corner) {
3312 0 : this->GetCorner(corner).Reset();
3313 : }
3314 0 : }
3315 :
3316 : static_assert(eCornerTopLeft == 0 && eCornerTopRight == 1 &&
3317 : eCornerBottomRight == 2 && eCornerBottomLeft == 3,
3318 : "box corner constants not tl/tr/br/bl == 0/1/2/3");
3319 :
3320 : /* static */ const nsCSSCornerSizes::corner_type
3321 : nsCSSCornerSizes::corners[4] = {
3322 : &nsCSSCornerSizes::mTopLeft,
3323 : &nsCSSCornerSizes::mTopRight,
3324 : &nsCSSCornerSizes::mBottomRight,
3325 : &nsCSSCornerSizes::mBottomLeft,
3326 : };
3327 :
3328 : size_t
3329 0 : mozilla::css::GridTemplateAreasValue::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
3330 : {
3331 : // Only measure it if it's unshared, to avoid double-counting.
3332 0 : size_t n = 0;
3333 0 : if (mRefCnt <= 1) {
3334 0 : n += aMallocSizeOf(this);
3335 0 : n += mNamedAreas.ShallowSizeOfExcludingThis(aMallocSizeOf);
3336 0 : n += mTemplates.ShallowSizeOfExcludingThis(aMallocSizeOf);
3337 : }
3338 0 : return n;
3339 : }
|