AccAttributes.cpp (13549B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #include "AccAttributes.h" 7 #include "StyleInfo.h" 8 #include "mozilla/ToString.h" 9 #include "nsAtom.h" 10 11 namespace mozilla::a11y { 12 13 bool AccAttributes::GetAttribute(nsAtom* aAttrName, 14 nsAString& aAttrValue) const { 15 if (auto value = mData.Lookup(aAttrName)) { 16 StringFromValueAndName(aAttrName, *value, aAttrValue); 17 return true; 18 } 19 20 return false; 21 } 22 23 void AccAttributes::StringFromValueAndName(nsAtom* aAttrName, 24 const AttrValueType& aValue, 25 nsAString& aValueString) { 26 aValueString.Truncate(); 27 28 aValue.match( 29 [&aValueString](const bool& val) { 30 aValueString.Assign(val ? u"true" : u"false"); 31 }, 32 [&aValueString](const float& val) { 33 aValueString.AppendFloat(val * 100); 34 aValueString.Append(u"%"); 35 }, 36 [&aValueString](const double& val) { aValueString.AppendFloat(val); }, 37 [&aValueString](const int32_t& val) { aValueString.AppendInt(val); }, 38 [&aValueString](const RefPtr<nsAtom>& val) { 39 val->ToString(aValueString); 40 }, 41 [&aValueString](const nsTArray<int32_t>& val) { 42 if (const size_t len = val.Length()) { 43 for (size_t i = 0; i < len - 1; i++) { 44 aValueString.AppendInt(val[i]); 45 aValueString.Append(u", "); 46 } 47 aValueString.AppendInt(val[len - 1]); 48 } else { 49 // The array is empty 50 NS_WARNING( 51 "Hmm, should we have used a DeleteEntry() for this instead?"); 52 aValueString.Append(u"[ ]"); 53 } 54 }, 55 [&aValueString](const CSSCoord& val) { 56 aValueString.AppendFloat(val); 57 aValueString.Append(u"px"); 58 }, 59 [&aValueString](const FontSize& val) { 60 aValueString.AppendInt(val.mValue); 61 aValueString.Append(u"pt"); 62 }, 63 [&aValueString](const Color& val) { 64 StyleInfo::FormatColor(val.mValue, aValueString); 65 }, 66 [&aValueString](const DeleteEntry& val) { 67 aValueString.Append(u"-delete-entry-"); 68 }, 69 [&aValueString](const UniquePtr<nsString>& val) { 70 aValueString.Assign(*val); 71 }, 72 [&aValueString](const RefPtr<AccAttributes>& val) { 73 if (val) { 74 aValueString.AppendPrintf("AccAttributes: %s", 75 ToString(*val).c_str()); 76 } else { 77 aValueString.AssignASCII("<null>"); 78 } 79 }, 80 [&aValueString](const uint64_t& val) { aValueString.AppendInt(val); }, 81 [&aValueString](const UniquePtr<AccGroupInfo>& val) { 82 aValueString.Assign(u"AccGroupInfo{...}"); 83 }, 84 [&aValueString](const UniquePtr<gfx::Matrix4x4>& val) { 85 aValueString.AppendPrintf("Matrix4x4=%s", ToString(*val).c_str()); 86 }, 87 [&aValueString](const UniquePtr<nsRect>& val) { 88 aValueString.AppendPrintf("nsRect=%s", ToString(*val).c_str()); 89 }, 90 [&aValueString](const nsTArray<uint64_t>& val) { 91 if (const size_t len = val.Length()) { 92 for (size_t i = 0; i < len - 1; i++) { 93 aValueString.AppendInt(val[i]); 94 aValueString.Append(u", "); 95 } 96 aValueString.AppendInt(val[len - 1]); 97 } else { 98 // The array is empty 99 NS_WARNING( 100 "Hmm, should we have used a DeleteEntry() for this instead?"); 101 aValueString.Append(u"[ ]"); 102 } 103 }, 104 [&aValueString](const nsTArray<TextOffsetAttribute>& val) { 105 if (const size_t len = val.Length()) { 106 for (size_t i = 0; i < len - 1; i++) { 107 aValueString.AppendPrintf("(%d, %d, ", val[i].mStartOffset, 108 val[i].mEndOffset); 109 aValueString.Append(nsAtomString(val[i].mAttribute)); 110 aValueString.Append(u"), "); 111 } 112 aValueString.AppendPrintf("(%d, %d, ", val[len - 1].mStartOffset, 113 val[len - 1].mEndOffset); 114 aValueString.Append(nsAtomString(val[len - 1].mAttribute)); 115 aValueString += ')'; 116 } else { 117 // The array is empty 118 NS_WARNING( 119 "Hmm, should we have used a DeleteEntry() for this instead?"); 120 aValueString.Append(u"[ ]"); 121 } 122 }, 123 [&aValueString](const WritingMode& val) { 124 aValueString.AppendPrintf("WritingModes: %x", val.GetBits()); 125 }, 126 [&aValueString](const nsTArray<RefPtr<nsAtom>>& val) { 127 if (const size_t len = val.Length()) { 128 for (size_t i = 0; i < len - 1; i++) { 129 aValueString.Append(val[i]->GetUTF16String()); 130 aValueString.Append(u" "); 131 } 132 aValueString.Append(val[len - 1]->GetUTF16String()); 133 } else { 134 // The array is empty 135 NS_WARNING( 136 "Hmm, should we have used a DeleteEntry() for this instead?"); 137 aValueString.Append(u""); 138 } 139 }); 140 } 141 142 void AccAttributes::Update(AccAttributes* aOther) { 143 for (auto iter = aOther->mData.Iter(); !iter.Done(); iter.Next()) { 144 if (iter.Data().is<DeleteEntry>()) { 145 mData.Remove(iter.Key()); 146 } else { 147 mData.InsertOrUpdate(iter.Key(), std::move(iter.Data())); 148 } 149 iter.Remove(); 150 } 151 } 152 153 void AccAttributes::RemoveIdentical(const AccAttributes* aOther) { 154 for (auto iter = mData.Iter(); !iter.Done(); iter.Next()) { 155 if (const auto otherEntry = aOther->mData.Lookup(iter.Key())) { 156 if (iter.Data().is<UniquePtr<nsString>>()) { 157 // Because we store nsString in a UniquePtr, we must handle it specially 158 // so we compare the string and not the pointer. 159 if (!otherEntry->is<UniquePtr<nsString>>()) { 160 continue; 161 } 162 const auto& thisStr = iter.Data().as<UniquePtr<nsString>>(); 163 const auto& otherStr = otherEntry->as<UniquePtr<nsString>>(); 164 if (*thisStr != *otherStr) { 165 continue; 166 } 167 } else if (iter.Data() != otherEntry.Data()) { 168 continue; 169 } 170 171 iter.Remove(); 172 } 173 } 174 } 175 176 bool AccAttributes::Equal(const AccAttributes* aOther) const { 177 if (Count() != aOther->Count()) { 178 return false; 179 } 180 for (auto iter = mData.ConstIter(); !iter.Done(); iter.Next()) { 181 const auto otherEntry = aOther->mData.Lookup(iter.Key()); 182 if (!otherEntry) { 183 return false; 184 } 185 if (iter.Data().is<UniquePtr<nsString>>()) { 186 // Because we store nsString in a UniquePtr, we must handle it specially 187 // so we compare the string and not the pointer. 188 if (!otherEntry->is<UniquePtr<nsString>>()) { 189 return false; 190 } 191 const auto& thisStr = iter.Data().as<UniquePtr<nsString>>(); 192 const auto& otherStr = otherEntry->as<UniquePtr<nsString>>(); 193 if (*thisStr != *otherStr) { 194 return false; 195 } 196 } else if (iter.Data() != otherEntry.Data()) { 197 return false; 198 } 199 } 200 return true; 201 } 202 203 void AccAttributes::CopyTo(AccAttributes* aDest, bool aOnlyMissing) const { 204 for (auto iter = mData.ConstIter(); !iter.Done(); iter.Next()) { 205 if (aOnlyMissing && aDest->HasAttribute(iter.Key())) { 206 continue; 207 } 208 209 iter.Data().match( 210 [&iter, &aDest](const bool& val) { 211 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 212 }, 213 [&iter, &aDest](const float& val) { 214 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 215 }, 216 [&iter, &aDest](const double& val) { 217 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 218 }, 219 [&iter, &aDest](const int32_t& val) { 220 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 221 }, 222 [&iter, &aDest](const RefPtr<nsAtom>& val) { 223 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 224 }, 225 [](const nsTArray<int32_t>& val) { 226 // We don't copy arrays. 227 MOZ_ASSERT_UNREACHABLE( 228 "Trying to copy an AccAttributes containing an array"); 229 }, 230 [&iter, &aDest](const CSSCoord& val) { 231 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 232 }, 233 [&iter, &aDest](const FontSize& val) { 234 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 235 }, 236 [&iter, &aDest](const Color& val) { 237 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 238 }, 239 [](const DeleteEntry& val) { 240 // We don't copy DeleteEntry. 241 MOZ_ASSERT_UNREACHABLE( 242 "Trying to copy an AccAttributes containing a DeleteEntry"); 243 }, 244 [&iter, &aDest](const UniquePtr<nsString>& val) { 245 aDest->SetAttributeStringCopy(iter.Key(), *val); 246 }, 247 [](const RefPtr<AccAttributes>& val) { 248 // We don't copy nested AccAttributes. 249 MOZ_ASSERT_UNREACHABLE( 250 "Trying to copy an AccAttributes containing an AccAttributes"); 251 }, 252 [&iter, &aDest](const uint64_t& val) { 253 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 254 }, 255 [](const UniquePtr<AccGroupInfo>& val) { 256 MOZ_ASSERT_UNREACHABLE( 257 "Trying to copy an AccAttributes containing an AccGroupInfo"); 258 }, 259 [](const UniquePtr<gfx::Matrix4x4>& val) { 260 MOZ_ASSERT_UNREACHABLE( 261 "Trying to copy an AccAttributes containing a matrix"); 262 }, 263 [](const UniquePtr<nsRect>& val) { 264 MOZ_ASSERT_UNREACHABLE( 265 "Trying to copy an AccAttributes containing a nsrect"); 266 }, 267 [](const nsTArray<uint64_t>& val) { 268 // We don't copy arrays. 269 MOZ_ASSERT_UNREACHABLE( 270 "Trying to copy an AccAttributes containing an array"); 271 }, 272 [](const nsTArray<TextOffsetAttribute>& val) { 273 // We don't copy arrays. 274 MOZ_ASSERT_UNREACHABLE( 275 "Trying to copy an AccAttributes containing an array"); 276 }, 277 [&iter, &aDest](const WritingMode& val) { 278 aDest->mData.InsertOrUpdate(iter.Key(), AsVariant(val)); 279 }, 280 [](const nsTArray<RefPtr<nsAtom>>& val) { 281 // We don't copy arrays. 282 MOZ_ASSERT_UNREACHABLE( 283 "Trying to copy an AccAttributes containing an array"); 284 }); 285 } 286 } 287 288 #ifdef A11Y_LOG 289 void AccAttributes::DebugPrint(const char* aPrefix, 290 const AccAttributes& aAttributes) { 291 printf("%s %s\n", aPrefix, ToString(aAttributes).c_str()); 292 } 293 #endif 294 295 size_t AccAttributes::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) { 296 size_t size = 297 aMallocSizeOf(this) + mData.ShallowSizeOfExcludingThis(aMallocSizeOf); 298 299 for (auto iter : *this) { 300 size += iter.SizeOfExcludingThis(aMallocSizeOf); 301 } 302 303 return size; 304 } 305 306 size_t AccAttributes::Entry::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) { 307 size_t size = 0; 308 309 // We don't count the size of Name() since it's counted by the atoms table 310 // memory reporter. 311 312 if (mValue->is<nsTArray<int32_t>>()) { 313 size += mValue->as<nsTArray<int32_t>>().ShallowSizeOfExcludingThis( 314 aMallocSizeOf); 315 } else if (mValue->is<UniquePtr<nsString>>()) { 316 // String data will never be shared. 317 size += mValue->as<UniquePtr<nsString>>()->SizeOfIncludingThisIfUnshared( 318 aMallocSizeOf); 319 } else if (mValue->is<RefPtr<AccAttributes>>()) { 320 size += 321 mValue->as<RefPtr<AccAttributes>>()->SizeOfIncludingThis(aMallocSizeOf); 322 } else if (mValue->is<UniquePtr<AccGroupInfo>>()) { 323 size += mValue->as<UniquePtr<AccGroupInfo>>()->SizeOfIncludingThis( 324 aMallocSizeOf); 325 } else if (mValue->is<UniquePtr<gfx::Matrix4x4>>()) { 326 size += aMallocSizeOf(mValue->as<UniquePtr<gfx::Matrix4x4>>().get()); 327 } else if (mValue->is<UniquePtr<nsRect>>()) { 328 size += aMallocSizeOf(mValue->as<UniquePtr<nsRect>>().get()); 329 } else if (mValue->is<nsTArray<uint64_t>>()) { 330 size += mValue->as<nsTArray<uint64_t>>().ShallowSizeOfExcludingThis( 331 aMallocSizeOf); 332 } else if (mValue->is<nsTArray<RefPtr<nsAtom>>>()) { 333 size += mValue->as<nsTArray<RefPtr<nsAtom>>>().ShallowSizeOfExcludingThis( 334 aMallocSizeOf); 335 } else { 336 // This type is stored directly and already counted or is an atom and 337 // stored and counted in the atoms table. 338 // Assert that we have exhausted all the remaining variant types. 339 MOZ_ASSERT(mValue->is<RefPtr<nsAtom>>() || mValue->is<bool>() || 340 mValue->is<float>() || mValue->is<double>() || 341 mValue->is<int32_t>() || mValue->is<uint64_t>() || 342 mValue->is<CSSCoord>() || mValue->is<FontSize>() || 343 mValue->is<Color>() || mValue->is<DeleteEntry>()); 344 } 345 346 return size; 347 } 348 349 std::ostream& operator<<(std::ostream& aStream, 350 const AccAttributes& aAttributes) { 351 if (aAttributes.Count() == 0) { 352 aStream << "{ empty }"; 353 return aStream; 354 } 355 aStream << "{\n"; 356 nsAutoStringN<2> separator{}; 357 nsAutoString scratch; 358 for (const AccAttributes::Entry entry : aAttributes) { 359 aStream << separator << " "; 360 entry.NameAsString(scratch); 361 aStream << scratch << ": "; 362 entry.ValueAsString(scratch); 363 aStream << scratch; 364 separator.AssignASCII(",\n"); 365 } 366 aStream << "\n}"; 367 return aStream; 368 } 369 370 } // namespace mozilla::a11y