mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1173958: convert FixedTableLayoutStrategy to logical coordinates, r=jfkthame (cf2c57043)
- Bug 1173958: whitespace and bracing changes to make FixedTableLayoutStrategy conform to local style, r=jfkthame (0ae378556)
- Bug 1177606 - Correct the row positioning within rowGroups in vertical-rl tables when distributing extra width. r=dholbert (1dffbe5a9)
- Bug 1173958 followup - A few of the tests have a pixel of fuzz on B2G. no_r=orange (314a9208f)
- Bug 1178059: fix a pair of failing reftests from bug 1173958 by forcing a div to align like a td, r=jfkthame (ec2284038)
- Bug 1165168 - Tests from Grard Talbot for border-spacing in vertical writing-modes. r=smontagu (2c3d82d75)
- Bug 1165172 - Tests from Grard Talbot for table row progression in vertical writing-modes. r=smontagu (965828bbe)
- Bug 1165172 followup - Mark tests as fuzzy on OS X in addition to Windows. (9f23dfb3d)
- Bug 1177076 patch 2.1 - Annotate vertical-table-specified-width-2.html because it will assert in FinishReflowChild() due to unconstrained containerWidth. r=dholbert (c43e77d31)
- Bug 1177076 patch 3 - Change the initial value of 'caption-side' from 'top' (physical) to 'block-start' (logical). r=heycam (336bb6726)
- Bug 1177076 - patch 4 - Reftests for logical and physical caption-side placement. r=dholbert (3323b59ed)
- Bug 1177076 followup - Some of the tests are a bit fuzzy on Android. (8fbec9908)
- Bug 1174631 (part 1) - Replace nsRuleNode's uses of PL_DHashTableEnumerate() with PLDHashTable::{,Removing}Iterator. r=dholbert. (265e5c39c)
- Bug 1174631 (part 2) - Replace nsCSSRuleProcessor's uses of PL_DHashTableEnumerate() with PLDHashTable::Iterator. r=dholbert. (583aa6dec)
- Bug 1174631 (part 3) - Replace SpanningCellSorter's uses of PL_DHashTableEnumerate() with PLDHashTable::Iterator. r=dholbert. (dffd16064)
- Bug 1174631 (part 4) - Replace nsFrameManager's uses of PL_DHashTableEnumerate() with PLDHashTable::Iterator. r=dholbert. (5eb697aec)
- Bug 1176159 (part 1) - Remove pref_SaveTypes. r=bsmedberg. (ad62e83d8)
- Bug 1176159 (part 2) - Remove uses of PL_DHashTableEnumerate() from libpref. r=bsmedberg. (dcc05f19a)
- Bug 1175771 (part 1) - Fix indentation in nsHostResolver::FlushCache(). r=michal. (fcfb05c57)
- Bug 1175771 (part 2) - Remove PL_DHashTableEnumerate() use from nsHostResolver. r=michal. (d79e95969)
- Bug 1175771 (part 3) - Replace nsCacheEntryHashable::VisitEntries() with iterators. r=michal. (f79745d9b)
- Bug 1175807 - Remove PL_DHashTableEnumerate() uses from nsNSSShutdown. r=honzab. (b88e91643)
- Bug 1179071 - Merge RemovingIterator into Iterator. r=froydnj. (fb22f5c91)
- Bug 1153426 - Don't crash when doing an off-main-thread animation of a transform to or from the 'none' value. r=birtles (23f9940e3)
This commit is contained in:
@@ -1974,7 +1974,7 @@ nsJSNPRuntime::OnPluginDestroy(NPP npp)
|
||||
}
|
||||
|
||||
if (sNPObjWrappers) {
|
||||
for (auto i = sNPObjWrappers->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = sNPObjWrappers->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<NPObjWrapperHashEntry*>(i.Get());
|
||||
|
||||
if (entry->mNpp == npp) {
|
||||
|
||||
@@ -775,7 +775,7 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp* fop,
|
||||
// At this point there may be JSObjects using them that have
|
||||
// been removed from the other maps.
|
||||
if (!nsXPConnect::XPConnect()->IsShuttingDown()) {
|
||||
for (auto i = self->mNativeScriptableSharedMap->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = self->mNativeScriptableSharedMap->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<XPCNativeScriptableSharedMap::Entry*>(i.Get());
|
||||
XPCNativeScriptableShared* shared = entry->key;
|
||||
if (shared->IsMarked()) {
|
||||
@@ -788,14 +788,14 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp* fop,
|
||||
}
|
||||
|
||||
if (!isCompartmentGC) {
|
||||
for (auto i = self->mClassInfo2NativeSetMap->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = self->mClassInfo2NativeSetMap->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<ClassInfo2NativeSetMap::Entry*>(i.Get());
|
||||
if (!entry->value->IsMarked())
|
||||
i.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = self->mNativeSetMap->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = self->mNativeSetMap->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<NativeSetMap::Entry*>(i.Get());
|
||||
XPCNativeSet* set = entry->key_value;
|
||||
if (set->IsMarked()) {
|
||||
@@ -806,7 +806,7 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp* fop,
|
||||
}
|
||||
}
|
||||
|
||||
for (auto i = self->mIID2NativeInterfaceMap->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = self->mIID2NativeInterfaceMap->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<IID2NativeInterfaceMap::Entry*>(i.Get());
|
||||
XPCNativeInterface* iface = entry->value;
|
||||
if (iface->IsMarked()) {
|
||||
@@ -871,7 +871,7 @@ XPCJSRuntime::FinalizeCallback(JSFreeOp* fop,
|
||||
// referencing the protos in the dying list are themselves dead.
|
||||
// So, we can safely delete all the protos in the list.
|
||||
|
||||
for (auto i = self->mDyingWrappedNativeProtoMap->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = self->mDyingWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<XPCWrappedNativeProtoMap::Entry*>(i.Get());
|
||||
delete static_cast<const XPCWrappedNativeProto*>(entry->key);
|
||||
i.Remove();
|
||||
@@ -3536,7 +3536,7 @@ XPCJSRuntime::DebugDump(int16_t depth)
|
||||
// iterate sets...
|
||||
if (depth && mNativeSetMap->Count()) {
|
||||
XPC_LOG_INDENT();
|
||||
for (auto i = mNativeSetMap->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = mNativeSetMap->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<NativeSetMap::Entry*>(i.Get());
|
||||
entry->key_value->DebugDump(depth);
|
||||
}
|
||||
|
||||
@@ -150,8 +150,6 @@ public:
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
|
||||
PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
|
||||
PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
||||
~Native2WrappedNativeMap();
|
||||
@@ -263,7 +261,7 @@ public:
|
||||
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
|
||||
PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); }
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
||||
@@ -319,7 +317,7 @@ public:
|
||||
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
|
||||
PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); }
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
// ClassInfo2NativeSetMap holds pointers to *some* XPCNativeSets.
|
||||
// So we don't want to count those XPCNativeSets, because they are better
|
||||
@@ -377,7 +375,7 @@ public:
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
|
||||
PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
|
||||
PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); }
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
||||
@@ -448,7 +446,7 @@ public:
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
|
||||
PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
|
||||
PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); }
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf);
|
||||
|
||||
@@ -545,7 +543,7 @@ public:
|
||||
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
|
||||
PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); }
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
~XPCNativeScriptableSharedMap();
|
||||
private:
|
||||
@@ -586,7 +584,7 @@ public:
|
||||
inline uint32_t Count() { return mTable->EntryCount(); }
|
||||
|
||||
PLDHashTable::Iterator Iter() const { return PLDHashTable::Iterator(mTable); }
|
||||
PLDHashTable::RemovingIterator RemovingIter() { return PLDHashTable::RemovingIterator(mTable); }
|
||||
PLDHashTable::Iterator Iter() { return PLDHashTable::Iterator(mTable); }
|
||||
|
||||
~XPCWrappedNativeProtoMap();
|
||||
private:
|
||||
|
||||
@@ -649,12 +649,12 @@ XPCWrappedNativeScope::SystemIsBeingShutDown()
|
||||
|
||||
// Walk the protos first. Wrapper shutdown can leave dangling
|
||||
// proto pointers in the proto map.
|
||||
for (auto i = cur->mWrappedNativeProtoMap->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = cur->mWrappedNativeProtoMap->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<ClassInfo2WrappedNativeProtoMap::Entry*>(i.Get());
|
||||
entry->value->SystemIsBeingShutDown();
|
||||
i.Remove();
|
||||
}
|
||||
for (auto i = cur->mWrappedNativeMap->RemovingIter(); !i.Done(); i.Next()) {
|
||||
for (auto i = cur->mWrappedNativeMap->Iter(); !i.Done(); i.Next()) {
|
||||
auto entry = static_cast<Native2WrappedNativeMap::Entry*>(i.Get());
|
||||
XPCWrappedNative* wrapper = entry->value;
|
||||
if (wrapper->IsValid()) {
|
||||
|
||||
@@ -203,19 +203,13 @@ nsFrameManager::UnregisterPlaceholderFrame(nsPlaceholderFrame* aPlaceholderFrame
|
||||
aPlaceholderFrame->GetOutOfFlowFrame());
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
UnregisterPlaceholders(PLDHashTable* table, PLDHashEntryHdr* hdr,
|
||||
uint32_t number, void* arg)
|
||||
{
|
||||
PlaceholderMapEntry* entry = static_cast<PlaceholderMapEntry*>(hdr);
|
||||
entry->placeholderFrame->SetOutOfFlowFrame(nullptr);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsFrameManager::ClearPlaceholderFrameMap()
|
||||
{
|
||||
PL_DHashTableEnumerate(&mPlaceholderMap, UnregisterPlaceholders, nullptr);
|
||||
for (auto iter = mPlaceholderMap.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<PlaceholderMapEntry*>(iter.Get());
|
||||
entry->placeholderFrame->SetOutOfFlowFrame(nullptr);
|
||||
}
|
||||
mPlaceholderMap.Clear();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
div.stripe
|
||||
{
|
||||
width: 20px;
|
||||
line-height: 20px;
|
||||
height: 200px;
|
||||
}
|
||||
div.blue {background-color: blue; }
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>CSS Reftest Reference</title>
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" /> <!-- 2013-07-27 -->
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<meta name="flags" content="image" />
|
||||
<style type="text/css"><![CDATA[
|
||||
div
|
||||
{
|
||||
background-color: black;
|
||||
color: yellow;
|
||||
font: 1.25em/1 Ahem;
|
||||
width: 21em;
|
||||
}
|
||||
|
||||
img {vertical-align: top;}
|
||||
]]></style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- body of reference case rewritten by Jonathan Kew to use Ahem glyphs instead of images,
|
||||
to reduce antialiasing fuzz in comparison with testcases -->
|
||||
<div>
|
||||
XXXX XXXX XXXX XXXX
|
||||
X X X X X X
|
||||
X X X X X X
|
||||
XXXX XXXX XXXX XXXX
|
||||
X X X X X
|
||||
X X X X X
|
||||
X X X XXXX XXXX
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -7,19 +7,19 @@
|
||||
== vertical-table-colspan-1.html vertical-table-colspan-1-ref.html
|
||||
== vertical-table-colspan-2.html vertical-table-colspan-2-ref.html
|
||||
== vertical-table-specified-width-1.html vertical-table-specified-width-1-ref.html
|
||||
== vertical-table-specified-width-2.html vertical-table-specified-width-2-ref.html
|
||||
asserts(1) == vertical-table-specified-width-2.html vertical-table-specified-width-2-ref.html # bug 1179741
|
||||
fuzzy-if(cocoaWidget,141,24) == vertical-border-collapse-1.html vertical-border-collapse-1-ref.html
|
||||
fuzzy-if(cocoaWidget,141,24) == vertical-border-collapse-2.html vertical-border-collapse-2-ref.html
|
||||
|
||||
== fixed-table-layout-002-vlr.html fixed-table-layout-002-ref.html
|
||||
== fixed-table-layout-003-vlr.html fixed-table-layout-002-ref.html
|
||||
fuzzy-if(B2G,5,1) == fixed-table-layout-002-vlr.html fixed-table-layout-002-ref.html
|
||||
fuzzy-if(B2G,5,1) == fixed-table-layout-003-vlr.html fixed-table-layout-002-ref.html
|
||||
== fixed-table-layout-004-vlr.html fixed-table-layout-004-ref.html
|
||||
== fixed-table-layout-005-vlr.html fixed-table-layout-005-ref.html
|
||||
== fixed-table-layout-006-vlr.html fixed-table-layout-006-ref.html
|
||||
== fixed-table-layout-007-vlr.html fixed-table-layout-007-ref.html
|
||||
fuzzy-if(B2G,5,1) == fixed-table-layout-007-vlr.html fixed-table-layout-007-ref.html
|
||||
== fixed-table-layout-009-vlr.html fixed-table-layout-009-ref.html
|
||||
random == fixed-table-layout-010-vlr.html fixed-table-layout-010-ref.html # bug 1178059
|
||||
== fixed-table-layout-012-vlr.html fixed-table-layout-012-ref.html
|
||||
fuzzy-if(Android,255,400) == fixed-table-layout-010-vlr.html fixed-table-layout-010-ref.html
|
||||
fuzzy-if(B2G,5,1) == fixed-table-layout-012-vlr.html fixed-table-layout-012-ref.html
|
||||
== fixed-table-layout-013-vlr.html fixed-table-layout-002-ref.html
|
||||
== fixed-table-layout-014-vlr.html fixed-table-layout-002-ref.html
|
||||
== fixed-table-layout-015-vlr.html fixed-table-layout-002-ref.html
|
||||
@@ -37,15 +37,15 @@ random == fixed-table-layout-010-vlr.html fixed-table-layout-010-ref.html # bug
|
||||
== fixed-table-layout-030-vlr.html fixed-table-layout-025-ref.html
|
||||
== fixed-table-layout-031-vlr.html fixed-table-layout-025-ref.html
|
||||
|
||||
== fixed-table-layout-002-vrl.html fixed-table-layout-002-ref.html
|
||||
== fixed-table-layout-003-vrl.html fixed-table-layout-002-ref.html
|
||||
fuzzy-if(B2G,5,1) == fixed-table-layout-002-vrl.html fixed-table-layout-002-ref.html
|
||||
fuzzy-if(B2G,5,1) == fixed-table-layout-003-vrl.html fixed-table-layout-002-ref.html
|
||||
== fixed-table-layout-004-vrl.html fixed-table-layout-004-ref.html
|
||||
== fixed-table-layout-005-vrl.html fixed-table-layout-005-ref.html
|
||||
== fixed-table-layout-006-vrl.html fixed-table-layout-006-ref.html
|
||||
== fixed-table-layout-007-vrl.html fixed-table-layout-007-ref.html
|
||||
fuzzy-if(B2G,5,1) == fixed-table-layout-007-vrl.html fixed-table-layout-007-ref.html
|
||||
== fixed-table-layout-009-vrl.html fixed-table-layout-009-ref.html
|
||||
random == fixed-table-layout-010-vrl.html fixed-table-layout-010-ref.html # bug 1178059
|
||||
== fixed-table-layout-012-vrl.html fixed-table-layout-012-ref.html
|
||||
fuzzy-if(Android,255,400) == fixed-table-layout-010-vrl.html fixed-table-layout-010-ref.html
|
||||
fuzzy-if(B2G,5,1) == fixed-table-layout-012-vrl.html fixed-table-layout-012-ref.html
|
||||
== fixed-table-layout-013-vrl.html fixed-table-layout-002-ref.html
|
||||
== fixed-table-layout-014-vrl.html fixed-table-layout-002-ref.html
|
||||
== fixed-table-layout-015-vrl.html fixed-table-layout-002-ref.html
|
||||
@@ -62,3 +62,23 @@ random == fixed-table-layout-010-vrl.html fixed-table-layout-010-ref.html # bug
|
||||
== fixed-table-layout-029-vrl.html fixed-table-layout-025-ref.html
|
||||
== fixed-table-layout-030-vrl.html fixed-table-layout-025-ref.html
|
||||
== fixed-table-layout-031-vrl.html fixed-table-layout-025-ref.html
|
||||
|
||||
HTTP(../..) == s72-border-spacing-002.xht s72-border-spacing-002-ref.xht
|
||||
HTTP(../..) == s72-border-spacing-003.xht s72-border-spacing-002-ref.xht
|
||||
HTTP(../..) == s72-border-spacing-004.xht s72-border-spacing-002-ref.xht
|
||||
HTTP(../..) == s72-border-spacing-005.xht s72-border-spacing-002-ref.xht
|
||||
fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-002.xht multicol-count-002-ref.xht
|
||||
fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-003.xht multicol-count-002-ref.xht
|
||||
fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-004.xht multicol-count-002-ref.xht
|
||||
fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-005.xht multicol-count-002-ref.xht
|
||||
fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-006.xht multicol-count-002-ref.xht
|
||||
fuzzy-if(winWidget,48,600) fuzzy-if(cocoaWidget,19,97) HTTP(../..) == wm-row-progression-007.xht multicol-count-002-ref.xht
|
||||
|
||||
fuzzy-if(Android,255,38) == table-caption-block-start-1.html table-caption-block-start-1-ref.html
|
||||
fuzzy-if(Android,255,38) == table-caption-block-end-1.html table-caption-block-end-1-ref.html
|
||||
== table-caption-inline-start-1.html table-caption-inline-start-1-ref.html
|
||||
== table-caption-inline-end-1.html table-caption-inline-end-1-ref.html
|
||||
fuzzy-if(Android,255,38) == table-caption-top-1.html table-caption-top-1-ref.html
|
||||
fuzzy-if(Android,255,38) == table-caption-bottom-1.html table-caption-bottom-1-ref.html
|
||||
== table-caption-left-1.html table-caption-left-1-ref.html
|
||||
== table-caption-right-1.html table-caption-right-1-ref.html
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Reftest Reference</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
|
||||
<meta name="flags" content="image" />
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
|
||||
|
||||
<div><img src="support/swatch-green.png" width="100" height="200" alt="Image download support must be enabled" /></div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: border-spacing - first value is specified and non-zero in 'vertical-rl' table</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#dimension-mapping" title="7.2 Dimension Mapping" />
|
||||
<link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#separated-borders" title="17.6.1 The separated borders model" />
|
||||
<link rel="match" href="s72-border-spacing-002-ref.xht" />
|
||||
|
||||
<!--
|
||||
To be replaced with
|
||||
<link rel="match" href="border-spacing-wm-002-ref.xht" />
|
||||
-->
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that first value of 'border-spacing' represents, from top to bottom, a) spacing between logical table right padding (physical table top padding) and rightmost cells and b) inter-column spacing and c) spacing between leftmost cells and logical table left padding (physical table bottom padding)." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
table
|
||||
{
|
||||
border-spacing: 0.5em 0em; /* computes to logical horizontal border-spacing: 10px */
|
||||
font: 1.25em/1 Ahem; /* computes to 20px/20px */
|
||||
padding: 1.25em 0em; /* computes to padding-top: 25px and padding-bottom: 25px */
|
||||
-ah-writing-mode: vertical-rl;
|
||||
-webkit-writing-mode: vertical-rl;
|
||||
writing-mode: tb-rl; /* IE11 */
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
height: 0.5em;
|
||||
padding: 0em;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
0px width of nth row 20px TOP
|
||||
| |
|
||||
=================================== 0x (0em) |||
|
||||
| table padding-top 25px (1.25em) | |||
|
||||
| with red background=color | \ ||| /
|
||||
| with red background=color | \ /
|
||||
| with red background=color | \ /
|
||||
| with red background=color | v
|
||||
=================================== 25px (1.25em)
|
||||
|logical righ border-spacing: 10px|
|
||||
| with red background=color |
|
||||
=================================== 35px (1.75em)
|
||||
| height of 1st td 10px (0.5em) | |||
|
||||
| with red background=color | |||
|
||||
=================================== 45px (2.25em) \ ||| /
|
||||
|inter-column spacing 10px (0.5em)| \ /
|
||||
| with red background=color | \ /
|
||||
=================================== 55px (2.75em) v
|
||||
| height of 2nd td 10px (0.5em) |
|
||||
| with red background=color |
|
||||
=================================== 65px (3.25em)
|
||||
|logical left border-spacing: 10px| |||
|
||||
| with red background=color | |||
|
||||
=================================== 75px (3.75em) \ ||| /
|
||||
|tble padding-bottom 25px (1.25em)| \ /
|
||||
| with red background=color | \ /
|
||||
| with red background=color | v
|
||||
| with red background=color |
|
||||
| with red background=color |
|
||||
=================================== 100px (5em) BOTTOM
|
||||
|
||||
*/
|
||||
|
||||
div#reference-overlapping-green
|
||||
{
|
||||
background-color: green;
|
||||
height: 6.25em;
|
||||
position: absolute;
|
||||
width: 6.25em;
|
||||
}
|
||||
|
||||
div#reference-overlapped-red
|
||||
{
|
||||
background-color: red;
|
||||
height: 6.25em;
|
||||
position: absolute;
|
||||
width: 6.25em;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
table#test-overlapped-red
|
||||
{
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
table#test-overlapping-green
|
||||
{
|
||||
background-color: green;
|
||||
}
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="reference-overlapping-green"></div>
|
||||
|
||||
<table id="test-overlapped-red">
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div id="reference-overlapped-red"></div>
|
||||
|
||||
<table id="test-overlapping-green">
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,144 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: border-spacing - first value is specified and non-zero in 'vertical-lr' table</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#dimension-mapping" title="7.2 Dimension Mapping" />
|
||||
<link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#separated-borders" title="17.6.1 The separated borders model" />
|
||||
<link rel="match" href="s72-border-spacing-002-ref.xht" />
|
||||
|
||||
<!--
|
||||
To be replaced with
|
||||
<link rel="match" href="border-spacing-wm-002-ref.xht" />
|
||||
-->
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that first value of 'border-spacing' represents, from top to bottom, a) spacing between logical table left padding (physical table top padding) and leftmost cells and b) inter-column spacing and c) spacing between rightmost cells and logical table right padding (physical table bottom padding)." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
table
|
||||
{
|
||||
border-spacing: 0.5em 0em; /* computes to logical horizontal border-spacing: 10px */
|
||||
font: 1.25em/1 Ahem; /* computes to 20px/20px */
|
||||
padding: 1.25em 0em; /* computes to padding-top: 25px and padding-bottom: 25px */
|
||||
-ah-writing-mode: vertical-lr;
|
||||
-webkit-writing-mode: vertical-lr;
|
||||
writing-mode: tb-lr; /* IE11 */
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
height: 0.5em;
|
||||
padding: 0em;
|
||||
width: 1em;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
0px width of nth row 20px TOP
|
||||
| |
|
||||
=================================== 0x (0em) |||
|
||||
| table padding-top 25px (1.25em) | |||
|
||||
| with red background=color | \ ||| /
|
||||
| with red background=color | \ /
|
||||
| with red background=color | \ /
|
||||
| with red background=color | v
|
||||
=================================== 25px (1.25em)
|
||||
|logical left border-spacing: 10px|
|
||||
| with red background=color |
|
||||
=================================== 35px (1.75em)
|
||||
| height of 1st td 10px (0.5em) | |||
|
||||
| with red background=color | |||
|
||||
=================================== 45px (2.25em) \ ||| /
|
||||
|inter-column spacing 10px (0.5em)| \ /
|
||||
| with red background=color | \ /
|
||||
=================================== 55px (2.75em) v
|
||||
| height of 2nd td 10px (0.5em) |
|
||||
| with red background=color |
|
||||
=================================== 65px (3.25em)
|
||||
|logical righ border-spacing: 10px| |||
|
||||
| with red background=color | |||
|
||||
=================================== 75px (3.75em) \ ||| /
|
||||
|tble padding-bottom 25px (1.25em)| \ /
|
||||
| with red background=color | \ /
|
||||
| with red background=color | v
|
||||
| with red background=color |
|
||||
| with red background=color |
|
||||
=================================== 100px (5em) BOTTOM
|
||||
|
||||
*/
|
||||
|
||||
div#reference-overlapping-green
|
||||
{
|
||||
background-color: green;
|
||||
height: 6.25em;
|
||||
position: absolute;
|
||||
width: 6.25em;
|
||||
}
|
||||
|
||||
div#reference-overlapped-red
|
||||
{
|
||||
background-color: red;
|
||||
height: 6.25em;
|
||||
position: absolute;
|
||||
width: 6.25em;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
table#test-overlapped-red
|
||||
{
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
table#test-overlapping-green
|
||||
{
|
||||
background-color: green;
|
||||
}
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="reference-overlapping-green"></div>
|
||||
|
||||
<table id="test-overlapped-red">
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div id="reference-overlapped-red"></div>
|
||||
|
||||
<table id="test-overlapping-green">
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,124 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: border-spacing - second value is specified and non-zero in 'vertical-rl' table</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#dimension-mapping" title="7.2 Dimension Mapping" />
|
||||
<link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#separated-borders" title="17.6.1 The separated borders model" />
|
||||
<link rel="match" href="s72-border-spacing-002-ref.xht" />
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that second value of 'border-spacing' represents, from right to left, a) spacing between logical table top padding (physical table right padding) and topmost cells and b) inter-row spacing and c) between bottommost cells and logical table bottom padding (physical table left padding)." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
table
|
||||
{
|
||||
border-spacing: 0em 0.5em; /* computes to logical vertical border-spacing: 10px */
|
||||
font: 1.25em/1 Ahem; /* computes to 20px/20px */
|
||||
padding: 0em 1.25em; /* computes to padding-left: 25px and padding-right: 25px */
|
||||
-ah-writing-mode: vertical-rl;
|
||||
-webkit-writing-mode: vertical-rl;
|
||||
writing-mode: tb-rl; /* IE11 */
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
height: 1em;
|
||||
padding: 0em;
|
||||
width: 0.5em;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
0px 25px 35px 45px 55px 65px 75px 100px
|
||||
| padding-left | left | 2nd | middle | 1st | right | padding-right|
|
||||
| of table | vert. | right | vert. | right | vert. | of table |
|
||||
| | border | most | border | most | border | |
|
||||
| | spacing| row | spacing| row | spacing| |
|
||||
20| | | | | | | |
|
||||
px| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
40| | | | | | | |
|
||||
px| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
60| | | | | | | |
|
||||
px| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
80| | | | | | | |
|
||||
px| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
00| | | | | | | |
|
||||
px| | | | | | | |
|
||||
|
||||
*/
|
||||
|
||||
div#reference-overlapping-green
|
||||
{
|
||||
background-color: green;
|
||||
height: 6.25em;
|
||||
position: absolute;
|
||||
width: 6.25em;
|
||||
}
|
||||
|
||||
div#reference-overlapped-red
|
||||
{
|
||||
background-color: red;
|
||||
height: 6.25em;
|
||||
position: absolute;
|
||||
width: 6.25em;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
table#test-overlapped-red
|
||||
{
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
table#test-overlapping-green
|
||||
{
|
||||
background-color: green;
|
||||
}
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="reference-overlapping-green"></div>
|
||||
|
||||
<table id="test-overlapped-red">
|
||||
|
||||
<tr><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div id="reference-overlapped-red"></div>
|
||||
|
||||
<table id="test-overlapping-green">
|
||||
|
||||
<tr><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,124 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: border-spacing - second value is specified and non-zero in 'vertical-lr' table</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#dimension-mapping" title="7.2 Dimension Mapping" />
|
||||
<link rel="help" href="http://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#separated-borders" title="17.6.1 The separated borders model" />
|
||||
<link rel="match" href="s72-border-spacing-002-ref.xht" />
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that second value of 'border-spacing' represents, from left to right, a) spacing between logical table top padding (physical table left padding) and topmost cells and b) inter-row spacing and c) spacing between bottommost cells and logical table bottom padding (physical table right padding)." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
table
|
||||
{
|
||||
border-spacing: 0em 0.5em; /* computes to logical vertical border-spacing: 10px */
|
||||
font: 1.25em/1 Ahem; /* computes to 20px/20px */
|
||||
padding: 0em 1.25em; /* computes to padding-left: 25px and padding-right: 25px */
|
||||
-ah-writing-mode: vertical-lr;
|
||||
-webkit-writing-mode: vertical-lr;
|
||||
writing-mode: tb-lr; /* IE11 */
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
height: 1em;
|
||||
padding: 0em;
|
||||
width: 0.5em;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
0px 25px 35px 45px 55px 65px 75px 100px
|
||||
| padding-left | left | 2nd | middle | 1st | right | padding-right|
|
||||
| of table | vert. | row | vert. | right | vert. | of table |
|
||||
| | border | | border | most | border | |
|
||||
| | spacing| | spacing| row | spacing| |
|
||||
20| | | | | | | |
|
||||
px| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
40| | | | | | | |
|
||||
px| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
60| | | | | | | |
|
||||
px| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
80| | | | | | | |
|
||||
px| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
| | | | | | | |
|
||||
00| | | | | | | |
|
||||
px| | | | | | | |
|
||||
|
||||
*/
|
||||
|
||||
div#reference-overlapping-green
|
||||
{
|
||||
background-color: green;
|
||||
height: 6.25em;
|
||||
position: absolute;
|
||||
width: 6.25em;
|
||||
}
|
||||
|
||||
div#reference-overlapped-red
|
||||
{
|
||||
background-color: red;
|
||||
height: 6.25em;
|
||||
position: absolute;
|
||||
width: 6.25em;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
table#test-overlapped-red
|
||||
{
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
table#test-overlapping-green
|
||||
{
|
||||
background-color: green;
|
||||
}
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<p>Test passes if there is a filled green rectangle and <strong>no red</strong>.</p>
|
||||
|
||||
<div id="reference-overlapping-green"></div>
|
||||
|
||||
<table id="test-overlapped-red">
|
||||
|
||||
<tr><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div id="reference-overlapped-red"></div>
|
||||
|
||||
<table id="test-overlapping-green">
|
||||
|
||||
<tr><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
|
||||
<tr><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,4 @@
|
||||
@font-face {
|
||||
font-family: Ahem;
|
||||
src: url("../../../fonts/Ahem.ttf");
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 84 B |
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
body > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.t {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
}
|
||||
.c {
|
||||
background: cyan;
|
||||
text-align: center;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="h">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="width: 200px">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="h">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="width: 200px">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="vlr">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="height: 100px">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="vrl">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="height: 100px">table caption</div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
caption-side: block-end;
|
||||
}
|
||||
td {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
padding: 0;
|
||||
}
|
||||
caption {
|
||||
background: cyan;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="h ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="h rtl">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vlr ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vrl ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,53 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
body > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.t {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
}
|
||||
.c {
|
||||
background: cyan;
|
||||
text-align: center;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="h">
|
||||
<div class="c" style="width: 200px">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="h">
|
||||
<div class="c" style="width: 200px">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="vlr">
|
||||
<div class="c" style="height: 100px">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="vrl">
|
||||
<div class="c" style="height: 100px">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
caption-side: block-start;
|
||||
}
|
||||
td {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
padding: 0;
|
||||
}
|
||||
caption {
|
||||
background: cyan;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="h ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="h rtl">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vlr ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vrl ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 0px sans-serif;
|
||||
}
|
||||
body > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.t {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
}
|
||||
.c {
|
||||
background: cyan;
|
||||
text-align: center;
|
||||
min-block-size: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="h">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="width: 200px">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="h">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="width: 200px">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="vlr">
|
||||
<div class="t" style="display: inline-block"></div>
|
||||
<div class="c" style="display: inline-block; inline-size: -moz-min-content; vertical-align: bottom">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="vrl">
|
||||
<div class="t" style="display: inline-block"></div>
|
||||
<div class="c" style="display: inline-block; inline-size: -moz-min-content; vertical-align: top">table caption</div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
caption-side: bottom;
|
||||
}
|
||||
td {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
padding: 0;
|
||||
}
|
||||
caption {
|
||||
background: cyan;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="h ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="h rtl">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vlr ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vrl ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 0px sans-serif;
|
||||
}
|
||||
body > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.t {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
display: inline-block;
|
||||
}
|
||||
.c {
|
||||
background: cyan;
|
||||
text-align: center;
|
||||
min-block-size: 20px;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="h">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="inline-size: -moz-min-content">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="h">
|
||||
<div class="c" style="inline-size: -moz-min-content">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="vlr">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="inline-size: -moz-min-content; vertical-align: bottom">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="vrl">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="inline-size: -moz-min-content">table caption</div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
caption-side: inline-end;
|
||||
}
|
||||
td {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
padding: 0;
|
||||
}
|
||||
caption {
|
||||
background: cyan;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="h ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="h rtl">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vlr ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vrl ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,57 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 0px sans-serif;
|
||||
}
|
||||
body > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.t {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
display: inline-block;
|
||||
}
|
||||
.c {
|
||||
background: cyan;
|
||||
text-align: center;
|
||||
min-block-size: 20px;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="h">
|
||||
<div class="c" style="inline-size: -moz-min-content">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="h">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="inline-size: -moz-min-content">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="vlr">
|
||||
<div class="c" style="inline-size: -moz-min-content; vertical-align: bottom">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="vrl">
|
||||
<div class="c" style="inline-size: -moz-min-content">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
caption-side: inline-start;
|
||||
}
|
||||
td {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
padding: 0;
|
||||
}
|
||||
caption {
|
||||
background: cyan;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="h ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="h rtl">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vlr ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vrl ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 0px sans-serif;
|
||||
}
|
||||
body > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.t {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
}
|
||||
.c {
|
||||
background: cyan;
|
||||
text-align: center;
|
||||
min-block-size: 20px;
|
||||
font-size: 12px;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="h">
|
||||
<div class="c" style="display: inline-block; inline-size: -moz-min-content">table caption</div>
|
||||
<div class="t" style="display: inline-block"></div>
|
||||
</div>
|
||||
|
||||
<div class="h">
|
||||
<div class="c" style="display: inline-block; inline-size: -moz-min-content">table caption</div>
|
||||
<div class="t" style="display: inline-block"></div>
|
||||
</div>
|
||||
|
||||
<div class="vlr">
|
||||
<div class="c" style="height: 100px">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="vrl">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="height: 100px">table caption</div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
caption-side: left;
|
||||
}
|
||||
td {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
padding: 0;
|
||||
}
|
||||
caption {
|
||||
background: cyan;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="h ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="h rtl">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vlr ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vrl ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,55 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 0px sans-serif;
|
||||
}
|
||||
body > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.t {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
}
|
||||
.c {
|
||||
background: cyan;
|
||||
text-align: center;
|
||||
min-block-size: 20px;
|
||||
font-size: 12px;
|
||||
vertical-align: top;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="h">
|
||||
<div class="t" style="display: inline-block"></div>
|
||||
<div class="c" style="display: inline-block; inline-size: -moz-min-content">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="h">
|
||||
<div class="t" style="display: inline-block"></div>
|
||||
<div class="c" style="display: inline-block; inline-size: -moz-min-content">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="vlr">
|
||||
<div class="t"></div>
|
||||
<div class="c" style="height: 100px">table caption</div>
|
||||
</div>
|
||||
|
||||
<div class="vrl">
|
||||
<div class="c" style="height: 100px">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
caption-side: right;
|
||||
}
|
||||
td {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
padding: 0;
|
||||
}
|
||||
caption {
|
||||
background: cyan;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="h ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="h rtl">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vlr ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vrl ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 0px sans-serif;
|
||||
}
|
||||
body > div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.t {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
}
|
||||
.c {
|
||||
background: cyan;
|
||||
text-align: center;
|
||||
min-block-size: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="h">
|
||||
<div class="c" style="width: 200px">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="h">
|
||||
<div class="c" style="width: 200px">table caption</div>
|
||||
<div class="t"></div>
|
||||
</div>
|
||||
|
||||
<div class="vlr">
|
||||
<div class="c" style="display: inline-block; inline-size: -moz-min-content; vertical-align: bottom">table caption</div>
|
||||
<div class="t" style="display: inline-block"></div>
|
||||
</div>
|
||||
|
||||
<div class="vrl">
|
||||
<div class="c" style="display: inline-block; inline-size: -moz-min-content; vertical-align: top">table caption</div>
|
||||
<div class="t" style="display: inline-block"></div>
|
||||
</div>
|
||||
@@ -0,0 +1,61 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<style>
|
||||
html {
|
||||
font: 12px sans-serif;
|
||||
}
|
||||
.h {
|
||||
writing-mode: horizontal-tb;
|
||||
}
|
||||
.vlr {
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
.vrl {
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
.ltr {
|
||||
direction: ltr;
|
||||
}
|
||||
.rtl {
|
||||
direction: rtl;
|
||||
}
|
||||
table {
|
||||
border-spacing: 0;
|
||||
margin-bottom: 10px;
|
||||
caption-side: top;
|
||||
}
|
||||
td {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
background: silver;
|
||||
padding: 0;
|
||||
}
|
||||
caption {
|
||||
background: cyan;
|
||||
min-block-size: 20px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<table class="h ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="h rtl">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vlr ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
|
||||
<table class="vrl ltr">
|
||||
<caption>table caption</caption>
|
||||
<tr><td></td></tr>
|
||||
</table>
|
||||
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: vertical-rl - table rows progression</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
|
||||
<link rel="match" href="multicol-count-002-ref.xht" />
|
||||
|
||||
<!--
|
||||
to be replaced with
|
||||
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
|
||||
-->
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that rows of a table element with in a 'vertical-rl' writing mode are laid out one after the other, leftwardedly, with the first beginning at the rightmost side of the table box; table rows are ordered from right to left meaning that the 1st row is the rightmost one and then the 2nd row is juxtaposed to its left-hand side, the 3rd row is juxtaposed to the 2nd row on its left-hand side, etc..." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
body
|
||||
{
|
||||
color: yellow;
|
||||
font: 1.25em/1 Ahem;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
background-color: black;
|
||||
border-spacing: 0em;
|
||||
border: black solid 1em;
|
||||
height: 7em;
|
||||
-ah-writing-mode: vertical-rl;
|
||||
-webkit-writing-mode: vertical-rl;
|
||||
writing-mode: tb-rl; /* IE11 */
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
padding-bottom: 0em;
|
||||
padding-left: 1em;
|
||||
padding-right: 0em;
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
td.left-most-cell { padding-left: 0em; }
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table>
|
||||
|
||||
<!-- The right-most "S" -->
|
||||
<tr><td>A B C DDD</td><td>EE F G H</td><td>JJ K L M</td></tr>
|
||||
|
||||
<!-- The left-most "S" -->
|
||||
<tr><td>N O Q RRR</td><td>SS T U V</td><td>WW X Y Z</td></tr>
|
||||
|
||||
<!-- The "A" -->
|
||||
<tr><td>aaa b c ddd</td><td>ee f g hh</td><td>jj kk</td></tr>
|
||||
|
||||
<!-- The "P" -->
|
||||
<tr><td class="left-most-cell">mmm n o qqq</td><td class="left-most-cell">r s t uu</td><td class="left-most-cell"> vv</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: vertical-lr - line boxes progression</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
|
||||
<link rel="match" href="multicol-count-002-ref.xht" />
|
||||
|
||||
<!--
|
||||
to be replaced with
|
||||
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
|
||||
-->
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that rows of a table element with in a 'vertical-lr' writing mode are laid out one after the other, rightwardedly, with the first beginning at the leftmost side of the table box; table rows are ordered from left to right meaning that the 1st row is the leftmost one and then the 2nd row is juxtaposed to its right-hand side, the 3rd row is juxtaposed to the 2nd row on its right-hand side, etc..." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
body
|
||||
{
|
||||
color: yellow;
|
||||
font: 1.25em/1 Ahem;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
background-color: black;
|
||||
border-spacing: 0em;
|
||||
border: black solid 1em;
|
||||
height: 7em;
|
||||
-ah-writing-mode: vertical-lr;
|
||||
-webkit-writing-mode: vertical-lr;
|
||||
writing-mode: tb-lr; /* IE11 */
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
padding-bottom: 0em;
|
||||
padding-left: 1em;
|
||||
padding-right: 0em;
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
td.left-most-cell { padding-left: 0em; }
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table>
|
||||
|
||||
<!-- The "P" -->
|
||||
<tr><td class="left-most-cell">AAA B C DDD</td><td class="left-most-cell">EE F G H</td><td class="left-most-cell">JJ </td></tr>
|
||||
|
||||
<!-- The "A" -->
|
||||
<tr><td>KKK L M NNN</td><td>OO Q R SS</td><td>TT UU</td></tr>
|
||||
|
||||
<!-- The left-most "S" -->
|
||||
<tr><td>VVV W X Y </td><td>a b c dd</td><td> e f g hh</td></tr>
|
||||
|
||||
<!-- The right-most "S" -->
|
||||
<tr><td>jjj k m n </td><td>q r s tt</td><td> u v w xx</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: vertical-rl - table rows progression and colspan</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
|
||||
<link rel="match" href="multicol-count-002-ref.xht" />
|
||||
|
||||
<!--
|
||||
to be replaced with
|
||||
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
|
||||
-->
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that colspanned cells in a table are handled according to a top-to-bottom inline flow direction." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
body
|
||||
{
|
||||
color: yellow;
|
||||
font: 1.25em/1 Ahem;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
background-color: black;
|
||||
border-spacing: 0em;
|
||||
border: black solid 1em;
|
||||
height: 7em;
|
||||
-ah-writing-mode: vertical-rl;
|
||||
-webkit-writing-mode: vertical-rl;
|
||||
writing-mode: tb-rl; /* IE11 */
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
padding-bottom: 0em;
|
||||
padding-left: 1em;
|
||||
padding-right: 0em;
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
td.left-most-cell { padding-left: 0em; }
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table>
|
||||
|
||||
<!-- The right-most "S" -->
|
||||
<tr><td>A B C DDD</td><td>EE F G H</td><td>JJ K L M</td></tr>
|
||||
|
||||
<!-- The left-most "S" -->
|
||||
<tr><td colspan="2">N OO Q R S T UUUU</td><td>WW X Y Z</td></tr>
|
||||
|
||||
<!-- The "A" -->
|
||||
<tr><td>aaa b c ddd</td><td colspan="2">eeff g h jjjj</td></tr>
|
||||
|
||||
<!-- The "P" -->
|
||||
<tr><td class="left-most-cell">mmm n o qqq</td><td class="left-most-cell">r s t uu</td><td class="left-most-cell"> vv</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: vertical-lr - table rows progression and colspan</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
|
||||
<link rel="match" href="multicol-count-002-ref.xht" />
|
||||
|
||||
<!--
|
||||
to be replaced with
|
||||
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
|
||||
-->
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that colspanned cells in a table are handled according to a top-to-bottom inline flow direction." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
body
|
||||
{
|
||||
color: yellow;
|
||||
font: 1.25em/1 Ahem;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
background-color: black;
|
||||
border-spacing: 0em;
|
||||
border: black solid 1em;
|
||||
height: 7em;
|
||||
-ah-writing-mode: vertical-lr;
|
||||
-webkit-writing-mode: vertical-lr;
|
||||
writing-mode: tb-lr; /* IE11 */
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
padding-bottom: 0em;
|
||||
padding-left: 1em;
|
||||
padding-right: 0em;
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
td.left-most-cell { padding-left: 0em; }
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table>
|
||||
|
||||
<!-- The "P" -->
|
||||
<tr><td class="left-most-cell">AAA B C DDD</td><td class="left-most-cell">EE F G H</td><td class="left-most-cell">JJ </td></tr>
|
||||
|
||||
<!-- The "A" -->
|
||||
<tr><td colspan="2">KKKOO L Q M R NNNSS</td><td>TT UU</td></tr>
|
||||
|
||||
<!-- The left-most "S" -->
|
||||
<tr><td>VVV W X Y </td><td colspan="2">a b c d e f gggg</td></tr>
|
||||
|
||||
<!-- The right-most "S" -->
|
||||
<tr><td>jjj k m n </td><td>q r s tt</td><td> u v w xx</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: vertical-rl - table rows progression and rowspan</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
|
||||
<link rel="match" href="multicol-count-002-ref.xht" />
|
||||
|
||||
<!--
|
||||
to be replaced with
|
||||
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
|
||||
-->
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that rowspanned cells in a table are handled according to a right-to-left direction." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
body
|
||||
{
|
||||
color: yellow;
|
||||
font: 1.25em/1 Ahem;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
background-color: black;
|
||||
border-spacing: 0em;
|
||||
border: black solid 1em;
|
||||
height: 7em;
|
||||
-ah-writing-mode: vertical-rl;
|
||||
-webkit-writing-mode: vertical-rl;
|
||||
writing-mode: tb-rl; /* IE11 */
|
||||
writing-mode: vertical-rl;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
padding-bottom: 0em;
|
||||
padding-left: 1em;
|
||||
padding-right: 0em;
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
td.left-most-cell { padding-left: 0em; }
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table>
|
||||
|
||||
<!-- The right-most "S" -->
|
||||
<tr><td>A B C DDD</td><td>EE F G H</td><td rowspan="2">JJ K L M WW X Y Z</td></tr>
|
||||
|
||||
<!-- The left-most "S" -->
|
||||
<tr><td>N O Q RRR</td><td>SS T U V</td></tr>
|
||||
|
||||
<!-- The "A" -->
|
||||
<tr><td>aaa b c ddd</td><td rowspan="2" class="left-most-cell">ee f g hh r s t uu</td><td>jj kk</td></tr>
|
||||
|
||||
<!-- The "P" -->
|
||||
<tr><td class="left-most-cell">mmm n o qqq</td><td class="left-most-cell"> vv</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,73 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
|
||||
<head>
|
||||
|
||||
<title>CSS Writing Modes Test: vertical-lr - table rows progression and rowspan</title>
|
||||
|
||||
<link rel="author" title="Gérard Talbot" href="http://www.gtalbot.org/BrowserBugsSection/css21testsuite/" />
|
||||
<link rel="help" href="http://www.w3.org/TR/css-writing-modes-3/#writing-mode" title="3.1 Block Flow Direction: the writing-mode property" />
|
||||
<link rel="match" href="multicol-count-002-ref.xht" />
|
||||
|
||||
<!--
|
||||
to be replaced with
|
||||
<link rel="match" href="../css-multicol-1/multicol-count-002-ref.xht" />
|
||||
-->
|
||||
|
||||
<meta content="ahem" name="flags" />
|
||||
<meta content="This test checks that rowspanned cells in a table are handled according to a left-to-right direction." name="assert" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="support/ahem.css" />
|
||||
|
||||
<style type="text/css"><![CDATA[
|
||||
body
|
||||
{
|
||||
color: yellow;
|
||||
font: 1.25em/1 Ahem;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
background-color: black;
|
||||
border-spacing: 0em;
|
||||
border: black solid 1em;
|
||||
height: 7em;
|
||||
-ah-writing-mode: vertical-lr;
|
||||
-webkit-writing-mode: vertical-lr;
|
||||
writing-mode: tb-lr; /* IE11 */
|
||||
writing-mode: vertical-lr;
|
||||
}
|
||||
|
||||
td
|
||||
{
|
||||
padding-bottom: 0em;
|
||||
padding-left: 1em;
|
||||
padding-right: 0em;
|
||||
padding-top: 0em;
|
||||
}
|
||||
|
||||
td.left-most-cell { padding-left: 0em; }
|
||||
]]></style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<table>
|
||||
|
||||
<!-- The "P" -->
|
||||
<tr><td class="left-most-cell">AAA B C DDD</td><td class="left-most-cell">EE F G H</td><td class="left-most-cell" rowspan="2">JJ TT UU</td></tr>
|
||||
|
||||
<!-- The "A" -->
|
||||
<tr><td>KKK L M NNN</td><td>OO Q R SS</td></tr>
|
||||
|
||||
<!-- The left-most "S" -->
|
||||
<tr><td>VVV W X Y </td><td rowspan="2">a b c dd q r s tt</td><td> e f g hh</td></tr>
|
||||
|
||||
<!-- The right-most "S" -->
|
||||
<tr><td>jjj k m n </td><td> u v w xx</td></tr>
|
||||
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -3435,30 +3435,6 @@ static int CompareWeightData(const void* aArg1, const void* aArg2,
|
||||
return arg1->mWeight - arg2->mWeight; // put lower weight first
|
||||
}
|
||||
|
||||
|
||||
struct FillWeightArrayData {
|
||||
explicit FillWeightArrayData(PerWeightData* aArrayData) :
|
||||
mIndex(0),
|
||||
mWeightArray(aArrayData)
|
||||
{
|
||||
}
|
||||
int32_t mIndex;
|
||||
PerWeightData* mWeightArray;
|
||||
};
|
||||
|
||||
|
||||
static PLDHashOperator
|
||||
FillWeightArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
uint32_t number, void *arg)
|
||||
{
|
||||
FillWeightArrayData* data = static_cast<FillWeightArrayData*>(arg);
|
||||
const RuleByWeightEntry *entry = (const RuleByWeightEntry *)hdr;
|
||||
|
||||
data->mWeightArray[data->mIndex++] = entry->data;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
RuleCascadeData*
|
||||
nsCSSRuleProcessor::GetRuleCascade(nsPresContext* aPresContext)
|
||||
{
|
||||
@@ -3525,8 +3501,11 @@ nsCSSRuleProcessor::RefreshRuleCascade(nsPresContext* aPresContext)
|
||||
// Sort the hash table of per-weight linked lists by weight.
|
||||
uint32_t weightCount = data.mRulesByWeight.EntryCount();
|
||||
nsAutoArrayPtr<PerWeightData> weightArray(new PerWeightData[weightCount]);
|
||||
FillWeightArrayData fwData(weightArray);
|
||||
PL_DHashTableEnumerate(&data.mRulesByWeight, FillWeightArray, &fwData);
|
||||
int32_t j = 0;
|
||||
for (auto iter = data.mRulesByWeight.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<const RuleByWeightEntry*>(iter.Get());
|
||||
weightArray[j++] = entry->data;
|
||||
}
|
||||
NS_QuickSort(weightArray, weightCount, sizeof(PerWeightData),
|
||||
CompareWeightData, nullptr);
|
||||
|
||||
|
||||
+19
-34
@@ -1405,17 +1405,6 @@ nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW
|
||||
return aPresContext->PresShell()->AllocateByObjectID(nsPresArena::nsRuleNode_id, sz);
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
nsRuleNode::EnqueueRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
uint32_t number, void *arg)
|
||||
{
|
||||
ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(hdr);
|
||||
nsRuleNode ***destroyQueueTail = static_cast<nsRuleNode***>(arg);
|
||||
**destroyQueueTail = entry->mRuleNode;
|
||||
*destroyQueueTail = &entry->mRuleNode->mNextSibling;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// Overridden to prevent the global delete from being called, since the memory
|
||||
// came out of an nsIArena instead of the global delete operator's heap.
|
||||
void
|
||||
@@ -1431,8 +1420,11 @@ nsRuleNode::DestroyInternal(nsRuleNode ***aDestroyQueueTail)
|
||||
|
||||
if (ChildrenAreHashed()) {
|
||||
PLDHashTable *children = ChildrenHash();
|
||||
PL_DHashTableEnumerate(children, EnqueueRuleNodeChildren,
|
||||
&destroyQueueTail);
|
||||
for (auto iter = children->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<ChildrenHashEntry*>(iter.Get());
|
||||
*destroyQueueTail = entry->mRuleNode;
|
||||
destroyQueueTail = &entry->mRuleNode->mNextSibling;
|
||||
}
|
||||
*destroyQueueTail = nullptr; // ensure null-termination
|
||||
delete children;
|
||||
} else if (HaveChildren()) {
|
||||
@@ -8023,7 +8015,7 @@ nsRuleNode::ComputeTableBorderData(void* aStartStruct,
|
||||
table->mCaptionSide, conditions,
|
||||
SETDSC_ENUMERATED | SETDSC_UNSET_INHERIT,
|
||||
parentTable->mCaptionSide,
|
||||
NS_STYLE_CAPTION_SIDE_TOP, 0, 0, 0, 0);
|
||||
NS_STYLE_CAPTION_SIDE_BSTART, 0, 0, 0, 0);
|
||||
|
||||
// empty-cells: enum, inherit, initial
|
||||
SetDiscrete(*aRuleData->ValueForEmptyCells(),
|
||||
@@ -9397,25 +9389,6 @@ nsRuleNode::DestroyIfNotMarked()
|
||||
return false;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsRuleNode::SweepHashEntry(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
uint32_t number, void *arg)
|
||||
{
|
||||
ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(hdr);
|
||||
nsRuleNode* node = entry->mRuleNode;
|
||||
if (node->DestroyIfNotMarked()) {
|
||||
return PL_DHASH_REMOVE; // implies NEXT, unless |ed with STOP
|
||||
}
|
||||
if (node->HaveChildren()) {
|
||||
// When children are hashed mNextSibling is not normally used but we use it
|
||||
// here to build a list of children that needs to be swept.
|
||||
nsRuleNode** headQ = static_cast<nsRuleNode**>(arg);
|
||||
node->mNextSibling = *headQ;
|
||||
*headQ = node;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsRuleNode::SweepChildren(nsTArray<nsRuleNode*>& aSweepQueue)
|
||||
{
|
||||
@@ -9428,7 +9401,19 @@ nsRuleNode::SweepChildren(nsTArray<nsRuleNode*>& aSweepQueue)
|
||||
if (ChildrenAreHashed()) {
|
||||
PLDHashTable* children = ChildrenHash();
|
||||
uint32_t oldChildCount = children->EntryCount();
|
||||
PL_DHashTableEnumerate(children, SweepHashEntry, &survivorsWithChildren);
|
||||
for (auto iter = children->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<ChildrenHashEntry*>(iter.Get());
|
||||
nsRuleNode* node = entry->mRuleNode;
|
||||
if (node->DestroyIfNotMarked()) {
|
||||
iter.Remove();
|
||||
} else if (node->HaveChildren()) {
|
||||
// When children are hashed mNextSibling is not normally used but we
|
||||
// use it here to build a list of children that needs to be swept.
|
||||
nsRuleNode** headQ = &survivorsWithChildren;
|
||||
node->mNextSibling = *headQ;
|
||||
*headQ = node;
|
||||
}
|
||||
}
|
||||
childrenDestroyed = oldChildCount - children->EntryCount();
|
||||
if (childrenDestroyed == oldChildCount) {
|
||||
delete children;
|
||||
|
||||
@@ -1706,7 +1706,7 @@ nsStyleTableBorder::nsStyleTableBorder()
|
||||
mBorderCollapse = NS_STYLE_BORDER_SEPARATE;
|
||||
|
||||
mEmptyCells = NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
|
||||
mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP;
|
||||
mCaptionSide = NS_STYLE_CAPTION_SIDE_BSTART;
|
||||
mBorderSpacingCol = 0;
|
||||
mBorderSpacingRow = 0;
|
||||
}
|
||||
|
||||
@@ -726,8 +726,13 @@ ReadTransforms(const nsCSSValueList* aList,
|
||||
|
||||
for (const nsCSSValueList* curr = aList; curr != nullptr; curr = curr->mNext) {
|
||||
const nsCSSValue &currElem = curr->mValue;
|
||||
NS_ASSERTION(currElem.GetUnit() == eCSSUnit_Function,
|
||||
"Stream should consist solely of functions!");
|
||||
if (currElem.GetUnit() != eCSSUnit_Function) {
|
||||
NS_ASSERTION(currElem.GetUnit() == eCSSUnit_None &&
|
||||
!aList->mNext,
|
||||
"stream should either be a list of functions or a "
|
||||
"lone None");
|
||||
continue;
|
||||
}
|
||||
NS_ASSERTION(currElem.GetArrayValue()->Count() >= 1,
|
||||
"Incoming function is too short!");
|
||||
|
||||
|
||||
@@ -2361,8 +2361,8 @@ var gCSSProperties = {
|
||||
domProp: "captionSide",
|
||||
inherited: true,
|
||||
type: CSS_TYPE_LONGHAND,
|
||||
initial_values: [ "top" ],
|
||||
other_values: [ "block-start", "block-end", "inline-start", "inline-end", "block-start-outside", "block-end-outside", "bottom", "left", "right", "top-outside", "bottom-outside" ],
|
||||
initial_values: [ "block-start" ],
|
||||
other_values: [ "block-end", "inline-start", "inline-end", "block-start-outside", "block-end-outside", "top", "bottom", "left", "right", "top-outside", "bottom-outside" ],
|
||||
invalid_values: []
|
||||
},
|
||||
"clear": {
|
||||
|
||||
@@ -159,6 +159,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=964646
|
||||
0% { opacity: 0.2 }
|
||||
100% { opacity: 0.8 }
|
||||
}
|
||||
|
||||
@keyframes transformnone {
|
||||
0%, 100% { transform: translateX(50px) }
|
||||
25%, 75% { transform: none }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -2194,6 +2199,17 @@ addAsyncAnimTest(function *() {
|
||||
omta_is("opacity", 0.875, RunningOn.Compositor,
|
||||
"anim2 at 900ms");
|
||||
done_div();
|
||||
|
||||
// Test that an interpolation that produces transform: none doesn't
|
||||
// crash.
|
||||
new_div("animation: transformnone 1s linear");
|
||||
yield waitForPaintsFlushed();
|
||||
omta_is("transform", { tx: 50 }, RunningOn.Compositor,
|
||||
"transformnone animation at 0ms");
|
||||
advance_clock(500);
|
||||
omta_is("transform", { tx: 0 }, RunningOn.Compositor,
|
||||
"transformnone animation at 500ms, interpolating none values");
|
||||
done_div();
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
// vim:cindent:ts=4:et:sw=4:
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:cindent:ts=2:et:sw=2:
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Algorithms that determine column and table widths used for CSS2's
|
||||
* 'table-layout: fixed'.
|
||||
* Algorithms that determine column and table inline sizes used for
|
||||
* CSS2's 'table-layout: fixed'.
|
||||
*/
|
||||
|
||||
#include "FixedTableLayoutStrategy.h"
|
||||
@@ -19,7 +19,7 @@ FixedTableLayoutStrategy::FixedTableLayoutStrategy(nsTableFrame *aTableFrame)
|
||||
: nsITableLayoutStrategy(nsITableLayoutStrategy::Fixed)
|
||||
, mTableFrame(aTableFrame)
|
||||
{
|
||||
MarkIntrinsicISizesDirty();
|
||||
MarkIntrinsicISizesDirty();
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
@@ -30,398 +30,404 @@ FixedTableLayoutStrategy::~FixedTableLayoutStrategy()
|
||||
/* virtual */ nscoord
|
||||
FixedTableLayoutStrategy::GetMinISize(nsRenderingContext* aRenderingContext)
|
||||
{
|
||||
DISPLAY_MIN_WIDTH(mTableFrame, mMinWidth);
|
||||
if (mMinWidth != NS_INTRINSIC_WIDTH_UNKNOWN)
|
||||
return mMinWidth;
|
||||
DISPLAY_MIN_WIDTH(mTableFrame, mMinISize);
|
||||
if (mMinISize != NS_INTRINSIC_WIDTH_UNKNOWN) {
|
||||
return mMinISize;
|
||||
}
|
||||
|
||||
// It's theoretically possible to do something much better here that
|
||||
// depends only on the columns and the first row (where we look at
|
||||
// intrinsic widths inside the first row and then reverse the
|
||||
// algorithm to find the narrowest width that would hold all of
|
||||
// those intrinsic widths), but it wouldn't be compatible with other
|
||||
// browsers, or with the use of GetMinISize by
|
||||
// nsTableFrame::ComputeSize to determine the width of a fixed
|
||||
// layout table, since CSS2.1 says:
|
||||
// The width of the table is then the greater of the value of the
|
||||
// 'width' property for the table element and the sum of the
|
||||
// column widths (plus cell spacing or borders).
|
||||
// It's theoretically possible to do something much better here that
|
||||
// depends only on the columns and the first row (where we look at
|
||||
// intrinsic inline sizes inside the first row and then reverse the
|
||||
// algorithm to find the narrowest inline size that would hold all of
|
||||
// those intrinsic inline sizes), but it wouldn't be compatible with
|
||||
// other browsers, or with the use of GetMinISize by
|
||||
// nsTableFrame::ComputeSize to determine the inline size of a fixed
|
||||
// layout table, since CSS2.1 says:
|
||||
// The width of the table is then the greater of the value of the
|
||||
// 'width' property for the table element and the sum of the column
|
||||
// widths (plus cell spacing or borders).
|
||||
|
||||
// XXX Should we really ignore 'min-width' and 'max-width'?
|
||||
// XXX Should we really ignore widths on column groups?
|
||||
// XXX Should we really ignore 'min-width' and 'max-width'?
|
||||
// XXX Should we really ignore widths on column groups?
|
||||
|
||||
nsTableCellMap *cellMap = mTableFrame->GetCellMap();
|
||||
int32_t colCount = cellMap->GetColCount();
|
||||
nsTableCellMap *cellMap = mTableFrame->GetCellMap();
|
||||
int32_t colCount = cellMap->GetColCount();
|
||||
|
||||
nscoord result = 0;
|
||||
nscoord result = 0;
|
||||
|
||||
if (colCount > 0) {
|
||||
result += mTableFrame->GetColSpacing(-1, colCount);
|
||||
if (colCount > 0) {
|
||||
result += mTableFrame->GetColSpacing(-1, colCount);
|
||||
}
|
||||
|
||||
WritingMode wm = mTableFrame->GetWritingMode();
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
nscoord spacing = mTableFrame->GetColSpacing(col);
|
||||
const nsStyleCoord *styleISize = &colFrame->StylePosition()->ISize(wm);
|
||||
if (styleISize->ConvertsToLength()) {
|
||||
result += nsLayoutUtils::ComputeISizeValue(aRenderingContext,
|
||||
colFrame, 0, 0, 0,
|
||||
*styleISize);
|
||||
} else if (styleISize->GetUnit() == eStyleUnit_Percent) {
|
||||
// do nothing
|
||||
} else {
|
||||
NS_ASSERTION(styleISize->GetUnit() == eStyleUnit_Auto ||
|
||||
styleISize->GetUnit() == eStyleUnit_Enumerated ||
|
||||
(styleISize->IsCalcUnit() && styleISize->CalcHasPercent()),
|
||||
"bad inline size");
|
||||
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
nscoord spacing = mTableFrame->GetColSpacing(col);
|
||||
const nsStyleCoord *styleWidth =
|
||||
&colFrame->StylePosition()->mWidth;
|
||||
if (styleWidth->ConvertsToLength()) {
|
||||
result += nsLayoutUtils::ComputeWidthValue(aRenderingContext,
|
||||
colFrame, 0, 0, 0, *styleWidth);
|
||||
} else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
|
||||
// do nothing
|
||||
} else {
|
||||
NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
|
||||
styleWidth->GetUnit() == eStyleUnit_Enumerated ||
|
||||
(styleWidth->IsCalcUnit() && styleWidth->CalcHasPercent()),
|
||||
"bad width");
|
||||
|
||||
// The 'table-layout: fixed' algorithm considers only cells
|
||||
// in the first row.
|
||||
bool originates;
|
||||
int32_t colSpan;
|
||||
nsTableCellFrame *cellFrame =
|
||||
cellMap->GetCellInfoAt(0, col, &originates, &colSpan);
|
||||
if (cellFrame) {
|
||||
styleWidth = &cellFrame->StylePosition()->mWidth;
|
||||
if (styleWidth->ConvertsToLength() ||
|
||||
(styleWidth->GetUnit() == eStyleUnit_Enumerated &&
|
||||
(styleWidth->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
|
||||
styleWidth->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) {
|
||||
nscoord cellWidth = nsLayoutUtils::IntrinsicForContainer(
|
||||
aRenderingContext, cellFrame, nsLayoutUtils::MIN_ISIZE);
|
||||
if (colSpan > 1) {
|
||||
// If a column-spanning cell is in the first
|
||||
// row, split up the space evenly. (XXX This
|
||||
// isn't quite right if some of the columns it's
|
||||
// in have specified widths. Should we care?)
|
||||
cellWidth = ((cellWidth + spacing) / colSpan) - spacing;
|
||||
}
|
||||
result += cellWidth;
|
||||
} else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
|
||||
if (colSpan > 1) {
|
||||
// XXX Can this force columns to negative
|
||||
// widths?
|
||||
result -= spacing * (colSpan - 1);
|
||||
}
|
||||
}
|
||||
// else, for 'auto', '-moz-available', '-moz-fit-content',
|
||||
// and 'calc()' with percentages, do nothing
|
||||
}
|
||||
// The 'table-layout: fixed' algorithm considers only cells in the
|
||||
// first row.
|
||||
bool originates;
|
||||
int32_t colSpan;
|
||||
nsTableCellFrame *cellFrame = cellMap->GetCellInfoAt(0, col, &originates,
|
||||
&colSpan);
|
||||
if (cellFrame) {
|
||||
styleISize = &cellFrame->StylePosition()->ISize(wm);
|
||||
if (styleISize->ConvertsToLength() ||
|
||||
(styleISize->GetUnit() == eStyleUnit_Enumerated &&
|
||||
(styleISize->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
|
||||
styleISize->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) {
|
||||
nscoord cellISize =
|
||||
nsLayoutUtils::IntrinsicForContainer(aRenderingContext, cellFrame,
|
||||
nsLayoutUtils::MIN_ISIZE);
|
||||
if (colSpan > 1) {
|
||||
// If a column-spanning cell is in the first row, split up
|
||||
// the space evenly. (XXX This isn't quite right if some of
|
||||
// the columns it's in have specified inline sizes. Should
|
||||
// we care?)
|
||||
cellISize = ((cellISize + spacing) / colSpan) - spacing;
|
||||
}
|
||||
result += cellISize;
|
||||
} else if (styleISize->GetUnit() == eStyleUnit_Percent) {
|
||||
if (colSpan > 1) {
|
||||
// XXX Can this force columns to negative inline sizes?
|
||||
result -= spacing * (colSpan - 1);
|
||||
}
|
||||
}
|
||||
// else, for 'auto', '-moz-available', '-moz-fit-content',
|
||||
// and 'calc()' with percentages, do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (mMinWidth = result);
|
||||
return (mMinISize = result);
|
||||
}
|
||||
|
||||
/* virtual */ nscoord
|
||||
FixedTableLayoutStrategy::GetPrefISize(nsRenderingContext* aRenderingContext,
|
||||
bool aComputingSize)
|
||||
{
|
||||
// It's theoretically possible to do something much better here that
|
||||
// depends only on the columns and the first row (where we look at
|
||||
// intrinsic widths inside the first row and then reverse the
|
||||
// algorithm to find the narrowest width that would hold all of
|
||||
// those intrinsic widths), but it wouldn't be compatible with other
|
||||
// browsers.
|
||||
nscoord result = nscoord_MAX;
|
||||
DISPLAY_PREF_WIDTH(mTableFrame, result);
|
||||
return result;
|
||||
// It's theoretically possible to do something much better here that
|
||||
// depends only on the columns and the first row (where we look at
|
||||
// intrinsic inline sizes inside the first row and then reverse the
|
||||
// algorithm to find the narrowest inline size that would hold all of
|
||||
// those intrinsic inline sizes), but it wouldn't be compatible with
|
||||
// other browsers.
|
||||
nscoord result = nscoord_MAX;
|
||||
DISPLAY_PREF_WIDTH(mTableFrame, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
FixedTableLayoutStrategy::MarkIntrinsicISizesDirty()
|
||||
{
|
||||
mMinWidth = NS_INTRINSIC_WIDTH_UNKNOWN;
|
||||
mLastCalcWidth = nscoord_MIN;
|
||||
mMinISize = NS_INTRINSIC_WIDTH_UNKNOWN;
|
||||
mLastCalcISize = nscoord_MIN;
|
||||
}
|
||||
|
||||
static inline nscoord
|
||||
AllocateUnassigned(nscoord aUnassignedSpace, float aShare)
|
||||
{
|
||||
if (aShare == 1.0f) {
|
||||
// This happens when the numbers we're dividing to get aShare
|
||||
// are equal. We want to return unassignedSpace exactly, even
|
||||
// if it can't be precisely round-tripped through float.
|
||||
return aUnassignedSpace;
|
||||
}
|
||||
return NSToCoordRound(float(aUnassignedSpace) * aShare);
|
||||
if (aShare == 1.0f) {
|
||||
// This happens when the numbers we're dividing to get aShare are
|
||||
// equal. We want to return unassignedSpace exactly, even if it
|
||||
// can't be precisely round-tripped through float.
|
||||
return aUnassignedSpace;
|
||||
}
|
||||
return NSToCoordRound(float(aUnassignedSpace) * aShare);
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
FixedTableLayoutStrategy::ComputeColumnISizes(const nsHTMLReflowState& aReflowState)
|
||||
{
|
||||
nscoord tableWidth = aReflowState.ComputedWidth();
|
||||
nscoord tableISize = aReflowState.ComputedISize();
|
||||
|
||||
if (mLastCalcWidth == tableWidth)
|
||||
return;
|
||||
mLastCalcWidth = tableWidth;
|
||||
if (mLastCalcISize == tableISize) {
|
||||
return;
|
||||
}
|
||||
mLastCalcISize = tableISize;
|
||||
|
||||
nsTableCellMap *cellMap = mTableFrame->GetCellMap();
|
||||
int32_t colCount = cellMap->GetColCount();
|
||||
nsTableCellMap *cellMap = mTableFrame->GetCellMap();
|
||||
int32_t colCount = cellMap->GetColCount();
|
||||
|
||||
if (colCount == 0) {
|
||||
// No Columns - nothing to compute
|
||||
return;
|
||||
if (colCount == 0) {
|
||||
// No Columns - nothing to compute
|
||||
return;
|
||||
}
|
||||
|
||||
// border-spacing isn't part of the basis for percentages.
|
||||
tableISize -= mTableFrame->GetColSpacing(-1, colCount);
|
||||
|
||||
// store the old column inline sizes. We might call SetFinalISize
|
||||
// multiple times on the columns, due to this we can't compare at the
|
||||
// last call that the inline size has changed with respect to the last
|
||||
// call to ComputeColumnISizes. In order to overcome this we store the
|
||||
// old values in this array. A single call to SetFinalISize would make
|
||||
// it possible to call GetFinalISize before and to compare when
|
||||
// setting the final inline size.
|
||||
nsTArray<nscoord> oldColISizes;
|
||||
|
||||
// XXX This ignores the 'min-width' and 'max-width' properties
|
||||
// throughout. Then again, that's what the CSS spec says to do.
|
||||
|
||||
// XXX Should we really ignore widths on column groups?
|
||||
|
||||
uint32_t unassignedCount = 0;
|
||||
nscoord unassignedSpace = tableISize;
|
||||
const nscoord unassignedMarker = nscoord_MIN;
|
||||
|
||||
// We use the PrefPercent on the columns to store the percentages
|
||||
// used to compute column inline sizes in case we need to shrink or
|
||||
// expand the columns.
|
||||
float pctTotal = 0.0f;
|
||||
|
||||
// Accumulate the total specified (non-percent) on the columns for
|
||||
// distributing excess inline size to the columns.
|
||||
nscoord specTotal = 0;
|
||||
|
||||
WritingMode wm = mTableFrame->GetWritingMode();
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
oldColISizes.AppendElement(0);
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
oldColISizes.AppendElement(colFrame->GetFinalISize());
|
||||
colFrame->ResetPrefPercent();
|
||||
const nsStyleCoord *styleISize = &colFrame->StylePosition()->ISize(wm);
|
||||
nscoord colISize;
|
||||
if (styleISize->ConvertsToLength()) {
|
||||
colISize = nsLayoutUtils::ComputeISizeValue(aReflowState.rendContext,
|
||||
colFrame, 0, 0, 0,
|
||||
*styleISize);
|
||||
specTotal += colISize;
|
||||
} else if (styleISize->GetUnit() == eStyleUnit_Percent) {
|
||||
float pct = styleISize->GetPercentValue();
|
||||
colISize = NSToCoordFloor(pct * float(tableISize));
|
||||
colFrame->AddPrefPercent(pct);
|
||||
pctTotal += pct;
|
||||
} else {
|
||||
NS_ASSERTION(styleISize->GetUnit() == eStyleUnit_Auto ||
|
||||
styleISize->GetUnit() == eStyleUnit_Enumerated ||
|
||||
(styleISize->IsCalcUnit() && styleISize->CalcHasPercent()),
|
||||
"bad inline size");
|
||||
|
||||
// The 'table-layout: fixed' algorithm considers only cells in the
|
||||
// first row.
|
||||
bool originates;
|
||||
int32_t colSpan;
|
||||
nsTableCellFrame *cellFrame = cellMap->GetCellInfoAt(0, col, &originates,
|
||||
&colSpan);
|
||||
if (cellFrame) {
|
||||
styleISize = &cellFrame->StylePosition()->ISize(wm);
|
||||
if (styleISize->ConvertsToLength() ||
|
||||
(styleISize->GetUnit() == eStyleUnit_Enumerated &&
|
||||
(styleISize->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
|
||||
styleISize->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) {
|
||||
// XXX This should use real percentage padding
|
||||
// Note that the difference between MIN_ISIZE and PREF_ISIZE
|
||||
// shouldn't matter for any of these values of styleISize; use
|
||||
// MIN_ISIZE for symmetry with GetMinISize above, just in case
|
||||
// there is a difference.
|
||||
colISize =
|
||||
nsLayoutUtils::IntrinsicForContainer(aReflowState.rendContext,
|
||||
cellFrame,
|
||||
nsLayoutUtils::MIN_ISIZE);
|
||||
} else if (styleISize->GetUnit() == eStyleUnit_Percent) {
|
||||
// XXX This should use real percentage padding
|
||||
nsIFrame::IntrinsicISizeOffsetData offsets =
|
||||
cellFrame->IntrinsicISizeOffsets();
|
||||
float pct = styleISize->GetPercentValue();
|
||||
colISize = NSToCoordFloor(pct * float(tableISize));
|
||||
|
||||
nscoord boxSizingAdjust = 0;
|
||||
switch (cellFrame->StylePosition()->mBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_CONTENT:
|
||||
boxSizingAdjust += offsets.hPadding;
|
||||
// Fall through
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
boxSizingAdjust += offsets.hBorder;
|
||||
// Fall through
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
// Don't add anything
|
||||
break;
|
||||
}
|
||||
colISize += boxSizingAdjust;
|
||||
|
||||
pct /= float(colSpan);
|
||||
colFrame->AddPrefPercent(pct);
|
||||
pctTotal += pct;
|
||||
} else {
|
||||
// 'auto', '-moz-available', '-moz-fit-content', and 'calc()'
|
||||
// with percentages
|
||||
colISize = unassignedMarker;
|
||||
}
|
||||
if (colISize != unassignedMarker) {
|
||||
if (colSpan > 1) {
|
||||
// If a column-spanning cell is in the first row, split up
|
||||
// the space evenly. (XXX This isn't quite right if some of
|
||||
// the columns it's in have specified iSizes. Should we
|
||||
// care?)
|
||||
nscoord spacing = mTableFrame->GetColSpacing(col);
|
||||
colISize = ((colISize + spacing) / colSpan) - spacing;
|
||||
if (colISize < 0) {
|
||||
colISize = 0;
|
||||
}
|
||||
}
|
||||
if (styleISize->GetUnit() != eStyleUnit_Percent) {
|
||||
specTotal += colISize;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
colISize = unassignedMarker;
|
||||
}
|
||||
}
|
||||
|
||||
// border-spacing isn't part of the basis for percentages.
|
||||
tableWidth -= mTableFrame->GetColSpacing(-1, colCount);
|
||||
colFrame->SetFinalISize(colISize);
|
||||
|
||||
// store the old column widths. We might call multiple times SetFinalISize
|
||||
// on the columns, due to this we can't compare at the last call that the
|
||||
// width has changed with the respect to the last call to
|
||||
// ComputeColumnISizes. In order to overcome this we store the old values
|
||||
// in this array. A single call to SetFinalISize would make it possible to
|
||||
// call GetFinalISize before and to compare when setting the final width.
|
||||
nsTArray<nscoord> oldColWidths;
|
||||
if (colISize == unassignedMarker) {
|
||||
++unassignedCount;
|
||||
} else {
|
||||
unassignedSpace -= colISize;
|
||||
}
|
||||
}
|
||||
|
||||
// XXX This ignores the 'min-width' and 'max-width' properties
|
||||
// throughout. Then again, that's what the CSS spec says to do.
|
||||
if (unassignedSpace < 0) {
|
||||
if (pctTotal > 0) {
|
||||
// If the columns took up too much space, reduce those that had
|
||||
// percentage inline sizes. The spec doesn't say to do this, but
|
||||
// we've always done it in the past, and so does WinIE6.
|
||||
nscoord pctUsed = NSToCoordFloor(pctTotal * float(tableISize));
|
||||
nscoord reduce = std::min(pctUsed, -unassignedSpace);
|
||||
float reduceRatio = float(reduce) / pctTotal;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
nscoord colISize = colFrame->GetFinalISize();
|
||||
colISize -= NSToCoordFloor(colFrame->GetPrefPercent() * reduceRatio);
|
||||
if (colISize < 0) {
|
||||
colISize = 0;
|
||||
}
|
||||
colFrame->SetFinalISize(colISize);
|
||||
}
|
||||
}
|
||||
unassignedSpace = 0;
|
||||
}
|
||||
|
||||
// XXX Should we really ignore widths on column groups?
|
||||
|
||||
uint32_t unassignedCount = 0;
|
||||
nscoord unassignedSpace = tableWidth;
|
||||
const nscoord unassignedMarker = nscoord_MIN;
|
||||
|
||||
// We use the PrefPercent on the columns to store the percentages
|
||||
// used to compute column widths in case we need to shrink or expand
|
||||
if (unassignedCount > 0) {
|
||||
// The spec says to distribute the remaining space evenly among
|
||||
// the columns.
|
||||
float pctTotal = 0.0f;
|
||||
|
||||
// Accumulate the total specified (non-percent) on the columns for
|
||||
// distributing excess width to the columns.
|
||||
nscoord specTotal = 0;
|
||||
|
||||
nscoord toAssign = unassignedSpace / unassignedCount;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
if (colFrame->GetFinalISize() == unassignedMarker) {
|
||||
colFrame->SetFinalISize(toAssign);
|
||||
}
|
||||
}
|
||||
} else if (unassignedSpace > 0) {
|
||||
// The spec doesn't say how to distribute the unassigned space.
|
||||
if (specTotal > 0) {
|
||||
// Distribute proportionally to non-percentage columns.
|
||||
nscoord specUndist = specTotal;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
oldColWidths.AppendElement(0);
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
oldColWidths.AppendElement(colFrame->GetFinalISize());
|
||||
colFrame->ResetPrefPercent();
|
||||
const nsStyleCoord *styleWidth =
|
||||
&colFrame->StylePosition()->mWidth;
|
||||
nscoord colWidth;
|
||||
if (styleWidth->ConvertsToLength()) {
|
||||
colWidth = nsLayoutUtils::ComputeWidthValue(
|
||||
aReflowState.rendContext,
|
||||
colFrame, 0, 0, 0, *styleWidth);
|
||||
specTotal += colWidth;
|
||||
} else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
|
||||
float pct = styleWidth->GetPercentValue();
|
||||
colWidth = NSToCoordFloor(pct * float(tableWidth));
|
||||
colFrame->AddPrefPercent(pct);
|
||||
pctTotal += pct;
|
||||
} else {
|
||||
NS_ASSERTION(styleWidth->GetUnit() == eStyleUnit_Auto ||
|
||||
styleWidth->GetUnit() == eStyleUnit_Enumerated ||
|
||||
(styleWidth->IsCalcUnit() && styleWidth->CalcHasPercent()),
|
||||
"bad width");
|
||||
|
||||
// The 'table-layout: fixed' algorithm considers only cells
|
||||
// in the first row.
|
||||
bool originates;
|
||||
int32_t colSpan;
|
||||
nsTableCellFrame *cellFrame =
|
||||
cellMap->GetCellInfoAt(0, col, &originates, &colSpan);
|
||||
if (cellFrame) {
|
||||
styleWidth = &cellFrame->StylePosition()->mWidth;
|
||||
if (styleWidth->ConvertsToLength() ||
|
||||
(styleWidth->GetUnit() == eStyleUnit_Enumerated &&
|
||||
(styleWidth->GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT ||
|
||||
styleWidth->GetIntValue() == NS_STYLE_WIDTH_MIN_CONTENT))) {
|
||||
// XXX This should use real percentage padding
|
||||
// Note that the difference between MIN_ISIZE and
|
||||
// PREF_ISIZE shouldn't matter for any of these
|
||||
// values of styleWidth; use MIN_ISIZE for symmetry
|
||||
// with GetMinISize above, just in case there is a
|
||||
// difference.
|
||||
colWidth = nsLayoutUtils::IntrinsicForContainer(
|
||||
aReflowState.rendContext,
|
||||
cellFrame, nsLayoutUtils::MIN_ISIZE);
|
||||
} else if (styleWidth->GetUnit() == eStyleUnit_Percent) {
|
||||
// XXX This should use real percentage padding
|
||||
nsIFrame::IntrinsicISizeOffsetData offsets =
|
||||
cellFrame->IntrinsicISizeOffsets();
|
||||
float pct = styleWidth->GetPercentValue();
|
||||
colWidth = NSToCoordFloor(pct * float(tableWidth));
|
||||
|
||||
nscoord boxSizingAdjust = 0;
|
||||
switch (cellFrame->StylePosition()->mBoxSizing) {
|
||||
case NS_STYLE_BOX_SIZING_CONTENT:
|
||||
boxSizingAdjust += offsets.hPadding;
|
||||
// Fall through
|
||||
case NS_STYLE_BOX_SIZING_PADDING:
|
||||
boxSizingAdjust += offsets.hBorder;
|
||||
// Fall through
|
||||
case NS_STYLE_BOX_SIZING_BORDER:
|
||||
// Don't add anything
|
||||
break;
|
||||
}
|
||||
colWidth += boxSizingAdjust;
|
||||
|
||||
pct /= float(colSpan);
|
||||
colFrame->AddPrefPercent(pct);
|
||||
pctTotal += pct;
|
||||
} else {
|
||||
// 'auto', '-moz-available', '-moz-fit-content', and
|
||||
// 'calc()' with percentages
|
||||
colWidth = unassignedMarker;
|
||||
}
|
||||
if (colWidth != unassignedMarker) {
|
||||
if (colSpan > 1) {
|
||||
// If a column-spanning cell is in the first
|
||||
// row, split up the space evenly. (XXX This
|
||||
// isn't quite right if some of the columns it's
|
||||
// in have specified widths. Should we care?)
|
||||
nscoord spacing = mTableFrame->GetColSpacing(col);
|
||||
colWidth = ((colWidth + spacing) / colSpan) - spacing;
|
||||
if (colWidth < 0)
|
||||
colWidth = 0;
|
||||
}
|
||||
if (styleWidth->GetUnit() != eStyleUnit_Percent) {
|
||||
specTotal += colWidth;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
colWidth = unassignedMarker;
|
||||
}
|
||||
}
|
||||
|
||||
colFrame->SetFinalISize(colWidth);
|
||||
|
||||
if (colWidth == unassignedMarker) {
|
||||
++unassignedCount;
|
||||
} else {
|
||||
unassignedSpace -= colWidth;
|
||||
}
|
||||
}
|
||||
|
||||
if (unassignedSpace < 0) {
|
||||
if (pctTotal > 0) {
|
||||
// If the columns took up too much space, reduce those that
|
||||
// had percentage widths. The spec doesn't say to do this,
|
||||
// but we've always done it in the past, and so does WinIE6.
|
||||
nscoord pctUsed = NSToCoordFloor(pctTotal * float(tableWidth));
|
||||
nscoord reduce = std::min(pctUsed, -unassignedSpace);
|
||||
float reduceRatio = float(reduce) / pctTotal;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
nscoord colWidth = colFrame->GetFinalISize();
|
||||
colWidth -= NSToCoordFloor(colFrame->GetPrefPercent() *
|
||||
reduceRatio);
|
||||
if (colWidth < 0)
|
||||
colWidth = 0;
|
||||
colFrame->SetFinalISize(colWidth);
|
||||
}
|
||||
}
|
||||
unassignedSpace = 0;
|
||||
}
|
||||
|
||||
if (unassignedCount > 0) {
|
||||
// The spec says to distribute the remaining space evenly among
|
||||
// the columns.
|
||||
nscoord toAssign = unassignedSpace / unassignedCount;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
if (colFrame->GetFinalISize() == unassignedMarker)
|
||||
colFrame->SetFinalISize(toAssign);
|
||||
}
|
||||
} else if (unassignedSpace > 0) {
|
||||
// The spec doesn't say how to distribute the unassigned space.
|
||||
if (specTotal > 0) {
|
||||
// Distribute proportionally to non-percentage columns.
|
||||
nscoord specUndist = specTotal;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
if (colFrame->GetPrefPercent() == 0.0f) {
|
||||
NS_ASSERTION(colFrame->GetFinalISize() <= specUndist,
|
||||
"widths don't add up");
|
||||
nscoord toAdd = AllocateUnassigned(unassignedSpace,
|
||||
float(colFrame->GetFinalISize()) / float(specUndist));
|
||||
specUndist -= colFrame->GetFinalISize();
|
||||
colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd);
|
||||
unassignedSpace -= toAdd;
|
||||
if (specUndist <= 0) {
|
||||
NS_ASSERTION(specUndist == 0,
|
||||
"math should be exact");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
|
||||
} else if (pctTotal > 0) {
|
||||
// Distribute proportionally to percentage columns.
|
||||
float pctUndist = pctTotal;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
if (pctUndist < colFrame->GetPrefPercent()) {
|
||||
// This can happen with floating-point math.
|
||||
NS_ASSERTION(colFrame->GetPrefPercent() - pctUndist
|
||||
< 0.0001,
|
||||
"widths don't add up");
|
||||
pctUndist = colFrame->GetPrefPercent();
|
||||
}
|
||||
nscoord toAdd = AllocateUnassigned(unassignedSpace,
|
||||
colFrame->GetPrefPercent() / pctUndist);
|
||||
colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd);
|
||||
unassignedSpace -= toAdd;
|
||||
pctUndist -= colFrame->GetPrefPercent();
|
||||
if (pctUndist <= 0.0f) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
|
||||
} else {
|
||||
// Distribute equally to the zero-width columns.
|
||||
int32_t colsLeft = colCount;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
NS_ASSERTION(colFrame->GetFinalISize() == 0, "yikes");
|
||||
nscoord toAdd = AllocateUnassigned(unassignedSpace,
|
||||
1.0f / float(colsLeft));
|
||||
colFrame->SetFinalISize(toAdd);
|
||||
unassignedSpace -= toAdd;
|
||||
--colsLeft;
|
||||
}
|
||||
NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
|
||||
}
|
||||
}
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
if (oldColWidths.ElementAt(col) != colFrame->GetFinalISize()) {
|
||||
mTableFrame->DidResizeColumns();
|
||||
if (colFrame->GetPrefPercent() == 0.0f) {
|
||||
NS_ASSERTION(colFrame->GetFinalISize() <= specUndist,
|
||||
"inline sizes don't add up");
|
||||
nscoord toAdd = AllocateUnassigned(unassignedSpace,
|
||||
float(colFrame->GetFinalISize()) /
|
||||
float(specUndist));
|
||||
specUndist -= colFrame->GetFinalISize();
|
||||
colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd);
|
||||
unassignedSpace -= toAdd;
|
||||
if (specUndist <= 0) {
|
||||
NS_ASSERTION(specUndist == 0, "math should be exact");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
|
||||
} else if (pctTotal > 0) {
|
||||
// Distribute proportionally to percentage columns.
|
||||
float pctUndist = pctTotal;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
if (pctUndist < colFrame->GetPrefPercent()) {
|
||||
// This can happen with floating-point math.
|
||||
NS_ASSERTION(colFrame->GetPrefPercent() - pctUndist < 0.0001,
|
||||
"inline sizes don't add up");
|
||||
pctUndist = colFrame->GetPrefPercent();
|
||||
}
|
||||
nscoord toAdd = AllocateUnassigned(unassignedSpace,
|
||||
colFrame->GetPrefPercent() /
|
||||
pctUndist);
|
||||
colFrame->SetFinalISize(colFrame->GetFinalISize() + toAdd);
|
||||
unassignedSpace -= toAdd;
|
||||
pctUndist -= colFrame->GetPrefPercent();
|
||||
if (pctUndist <= 0.0f) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
|
||||
} else {
|
||||
// Distribute equally to the zero-iSize columns.
|
||||
int32_t colsRemaining = colCount;
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
NS_ASSERTION(colFrame->GetFinalISize() == 0, "yikes");
|
||||
nscoord toAdd = AllocateUnassigned(unassignedSpace,
|
||||
1.0f / float(colsRemaining));
|
||||
colFrame->SetFinalISize(toAdd);
|
||||
unassignedSpace -= toAdd;
|
||||
--colsRemaining;
|
||||
}
|
||||
NS_ASSERTION(unassignedSpace == 0, "failed to redistribute");
|
||||
}
|
||||
}
|
||||
for (int32_t col = 0; col < colCount; ++col) {
|
||||
nsTableColFrame *colFrame = mTableFrame->GetColFrame(col);
|
||||
if (!colFrame) {
|
||||
NS_ERROR("column frames out of sync with cell map");
|
||||
continue;
|
||||
}
|
||||
if (oldColISizes.ElementAt(col) != colFrame->GetFinalISize()) {
|
||||
mTableFrame->DidResizeColumns();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
// vim:cindent:ts=4:et:sw=4:
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
// vim:cindent:ts=2:et:sw=2:
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
@@ -20,20 +20,21 @@ class nsTableFrame;
|
||||
class FixedTableLayoutStrategy : public nsITableLayoutStrategy
|
||||
{
|
||||
public:
|
||||
explicit FixedTableLayoutStrategy(nsTableFrame *aTableFrame);
|
||||
virtual ~FixedTableLayoutStrategy();
|
||||
explicit FixedTableLayoutStrategy(nsTableFrame *aTableFrame);
|
||||
virtual ~FixedTableLayoutStrategy();
|
||||
|
||||
// nsITableLayoutStrategy implementation
|
||||
virtual nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
|
||||
virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext,
|
||||
bool aComputingSize) override;
|
||||
virtual void MarkIntrinsicISizesDirty() override;
|
||||
virtual void ComputeColumnISizes(const nsHTMLReflowState& aReflowState) override;
|
||||
// nsITableLayoutStrategy implementation
|
||||
virtual nscoord GetMinISize(nsRenderingContext* aRenderingContext) override;
|
||||
virtual nscoord GetPrefISize(nsRenderingContext* aRenderingContext,
|
||||
bool aComputingSize) override;
|
||||
virtual void MarkIntrinsicISizesDirty() override;
|
||||
virtual void ComputeColumnISizes(const nsHTMLReflowState& aReflowState)
|
||||
override;
|
||||
|
||||
private:
|
||||
nsTableFrame *mTableFrame;
|
||||
nscoord mMinWidth;
|
||||
nscoord mLastCalcWidth;
|
||||
nsTableFrame *mTableFrame;
|
||||
nscoord mMinISize;
|
||||
nscoord mLastCalcISize;
|
||||
};
|
||||
|
||||
#endif /* !defined(FixedTableLayoutStrategy_h_) */
|
||||
|
||||
@@ -86,18 +86,6 @@ SpanningCellSorter::AddCell(int32_t aColSpan, int32_t aRow, int32_t aCol)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
SpanningCellSorter::FillSortedArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
uint32_t number, void *arg)
|
||||
{
|
||||
HashTableEntry *entry = static_cast<HashTableEntry*>(hdr);
|
||||
HashTableEntry **sh = static_cast<HashTableEntry**>(arg);
|
||||
|
||||
sh[number] = entry;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */ int
|
||||
SpanningCellSorter::SortArray(const void *a, const void *b, void *closure)
|
||||
{
|
||||
@@ -143,7 +131,10 @@ SpanningCellSorter::GetNext(int32_t *aColSpan)
|
||||
if (mHashTable.EntryCount() > 0) {
|
||||
HashTableEntry **sh =
|
||||
new HashTableEntry*[mHashTable.EntryCount()];
|
||||
PL_DHashTableEnumerate(&mHashTable, FillSortedArray, sh);
|
||||
int32_t j = 0;
|
||||
for (auto iter = mHashTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
sh[j++] = static_cast<HashTableEntry*>(iter.Get());
|
||||
}
|
||||
NS_QuickSort(sh, mHashTable.EntryCount(), sizeof(sh[0]),
|
||||
SortArray, nullptr);
|
||||
mSortedHashTable = sh;
|
||||
|
||||
@@ -3388,6 +3388,13 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState,
|
||||
WritingMode wm = aReflowState.GetWritingMode();
|
||||
LogicalMargin borderPadding = GetChildAreaOffset(wm, &aReflowState);
|
||||
|
||||
nscoord containerWidth = aReflowState.ComputedWidth();
|
||||
if (containerWidth == NS_UNCONSTRAINEDSIZE) {
|
||||
containerWidth = 0;
|
||||
} else {
|
||||
containerWidth += aReflowState.ComputedPhysicalBorderPadding().LeftRight();
|
||||
}
|
||||
|
||||
RowGroupArray rowGroups;
|
||||
OrderRowGroups(rowGroups);
|
||||
|
||||
@@ -3403,13 +3410,13 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState,
|
||||
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
||||
nscoord amountUsedByRG = 0;
|
||||
nscoord bOriginRow = 0;
|
||||
// We pass containerWidth of zero when constructing the LogicalRect here,
|
||||
// and similarly below. This is OK because these rects will be used to make
|
||||
// relative adjustments, not for actual conversion to physical coords.
|
||||
LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), 0);
|
||||
LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), containerWidth);
|
||||
if (!rgFrame->HasStyleBSize()) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
// We don't know the final width of the rowGroupFrame yet, so use zero
|
||||
// as a "fake" containerWidth here; we'll adjust the row positions at
|
||||
// the end, after the rowGroup size is finalized.
|
||||
LogicalRect rowNormalRect(wm, rowFrame->GetNormalRect(), 0);
|
||||
nscoord cellSpacingB = GetRowSpacing(rowFrame->GetRowIndex());
|
||||
if ((amountUsed < aAmount) && rowFrame->HasPctBSize()) {
|
||||
@@ -3547,12 +3554,12 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState,
|
||||
nsTableRowGroupFrame* rgFrame = rowGroups[rgX];
|
||||
nscoord amountUsedByRG = 0;
|
||||
nscoord bOriginRow = 0;
|
||||
LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), 0);
|
||||
LogicalRect rgNormalRect(wm, rgFrame->GetNormalRect(), containerWidth);
|
||||
nsRect rgVisualOverflow = rgFrame->GetVisualOverflowRect();
|
||||
// see if there is an eligible row group or we distribute to all rows
|
||||
if (!firstUnStyledRG || !rgFrame->HasStyleBSize() || !eligibleRows) {
|
||||
nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
while (rowFrame) {
|
||||
for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
rowFrame; rowFrame = rowFrame->GetNextRow()) {
|
||||
nscoord cellSpacingB = GetRowSpacing(rowFrame->GetRowIndex());
|
||||
LogicalRect rowNormalRect(wm, rowFrame->GetNormalRect(), 0);
|
||||
nsRect rowVisualOverflow = rowFrame->GetVisualOverflowRect();
|
||||
@@ -3616,8 +3623,8 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState,
|
||||
bOriginRow += rowNormalRect.BSize(wm) + cellSpacingB;
|
||||
bEndRG += rowNormalRect.BSize(wm) + cellSpacingB;
|
||||
}
|
||||
rowFrame = rowFrame->GetNextRow();
|
||||
}
|
||||
|
||||
if (amountUsed > 0) {
|
||||
if (rgNormalRect.BStart(wm) != bOriginRG) {
|
||||
rgFrame->InvalidateFrameSubtree();
|
||||
@@ -3632,7 +3639,23 @@ nsTableFrame::DistributeBSizeToRows(const nsHTMLReflowState& aReflowState,
|
||||
nsTableFrame::InvalidateTableFrame(rgFrame, origRgNormalRect,
|
||||
rgVisualOverflow, false);
|
||||
}
|
||||
// Make sure child views are properly positioned
|
||||
|
||||
// For vertical-rl mode, we needed to position the rows relative to the
|
||||
// right-hand (block-start) side of the group; but we couldn't do that
|
||||
// above, as we didn't know the rowGroupFrame's final block size yet.
|
||||
// So we used a containerWidth of zero earlier, placing the rows to the
|
||||
// left of the rowGroupFrame's (physical) origin. Now we move them all
|
||||
// rightwards by its final width.
|
||||
if (wm.IsVerticalRL()) {
|
||||
nscoord rgWidth = rgFrame->GetRect().width;
|
||||
for (nsTableRowFrame* rowFrame = rgFrame->GetFirstRow();
|
||||
rowFrame; rowFrame = rowFrame->GetNextRow()) {
|
||||
rowFrame->InvalidateFrameSubtree();
|
||||
rowFrame->MovePositionBy(nsPoint(rgWidth, 0));
|
||||
nsTableFrame::RePositionViews(rowFrame);
|
||||
rowFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (amountUsed > 0 && bOriginRG != rgNormalRect.BStart(wm)) {
|
||||
rgFrame->InvalidateFrameSubtree();
|
||||
@@ -3836,14 +3859,14 @@ nsTableFrame::IsAutoLayout()
|
||||
{
|
||||
if (StyleTable()->mLayoutStrategy == NS_STYLE_TABLE_LAYOUT_AUTO)
|
||||
return true;
|
||||
// a fixed-layout inline-table must have a width
|
||||
// and tables with 'width: -moz-max-content' must be auto-layout
|
||||
// (at least as long as FixedTableLayoutStrategy::GetPrefISize returns
|
||||
// nscoord_MAX)
|
||||
const nsStyleCoord &width = StylePosition()->mWidth;
|
||||
return (width.GetUnit() == eStyleUnit_Auto) ||
|
||||
(width.GetUnit() == eStyleUnit_Enumerated &&
|
||||
width.GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT);
|
||||
// a fixed-layout inline-table must have a inline size
|
||||
// and tables with inline size set to '-moz-max-content' must be
|
||||
// auto-layout (at least as long as
|
||||
// FixedTableLayoutStrategy::GetPrefISize returns nscoord_MAX)
|
||||
const nsStyleCoord &iSize = StylePosition()->ISize(GetWritingMode());
|
||||
return (iSize.GetUnit() == eStyleUnit_Auto) ||
|
||||
(iSize.GetUnit() == eStyleUnit_Enumerated &&
|
||||
iSize.GetIntValue() == NS_STYLE_WIDTH_MAX_CONTENT);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FRAME_DUMP
|
||||
|
||||
@@ -739,7 +739,11 @@ void
|
||||
Preferences::GetPreferences(InfallibleTArray<PrefSetting>* aPrefs)
|
||||
{
|
||||
aPrefs->SetCapacity(gHashTable->Capacity());
|
||||
PL_DHashTableEnumerate(gHashTable, pref_GetPrefs, aPrefs);
|
||||
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<PrefHashEntry*>(iter.Get());
|
||||
dom::PrefSetting *pref = aPrefs->AppendElement();
|
||||
pref_GetPrefFromEntry(entry, pref);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
@@ -961,12 +965,9 @@ Preferences::WritePrefFile(nsIFile* aFile)
|
||||
|
||||
nsAutoArrayPtr<char*> valueArray(new char*[gHashTable->EntryCount()]);
|
||||
memset(valueArray, 0, gHashTable->EntryCount() * sizeof(char*));
|
||||
pref_saveArgs saveArgs;
|
||||
saveArgs.prefArray = valueArray;
|
||||
saveArgs.saveTypes = SAVE_ALL;
|
||||
|
||||
// get the lines that we're supposed to be writing to the file
|
||||
PL_DHashTableEnumerate(gHashTable, pref_savePref, &saveArgs);
|
||||
pref_savePrefs(gHashTable, valueArray);
|
||||
|
||||
/* Sort the preferences to make a readable file on disk */
|
||||
NS_QuickSort(valueArray, gHashTable->EntryCount(), sizeof(char *),
|
||||
|
||||
@@ -42,17 +42,6 @@
|
||||
}
|
||||
#endif
|
||||
|
||||
// Definitions
|
||||
struct EnumerateData {
|
||||
const char *parent;
|
||||
nsTArray<nsCString> *pref_list;
|
||||
};
|
||||
|
||||
// Prototypes
|
||||
static PLDHashOperator
|
||||
pref_enumChild(PLDHashTable *table, PLDHashEntryHdr *heh,
|
||||
uint32_t i, void *arg);
|
||||
|
||||
using mozilla::dom::ContentChild;
|
||||
|
||||
static ContentChild*
|
||||
@@ -531,7 +520,6 @@ NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, uint32_t *aCou
|
||||
char **outArray;
|
||||
int32_t numPrefs;
|
||||
int32_t dwIndex;
|
||||
EnumerateData ed;
|
||||
nsAutoTArray<nsCString, 32> prefArray;
|
||||
|
||||
NS_ENSURE_ARG(aStartingAt);
|
||||
@@ -544,9 +532,14 @@ NS_IMETHODIMP nsPrefBranch::GetChildList(const char *aStartingAt, uint32_t *aCou
|
||||
// this will contain a list of all the pref name strings
|
||||
// allocate on the stack for speed
|
||||
|
||||
ed.parent = getPrefName(aStartingAt);
|
||||
ed.pref_list = &prefArray;
|
||||
PL_DHashTableEnumerate(gHashTable, pref_enumChild, &ed);
|
||||
const char* parent = getPrefName(aStartingAt);
|
||||
size_t parentLen = strlen(parent);
|
||||
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<PrefHashEntry*>(iter.Get());
|
||||
if (strncmp(entry->key, parent, parentLen) == 0) {
|
||||
prefArray.AppendElement(entry->key);
|
||||
}
|
||||
}
|
||||
|
||||
// now that we've built up the list, run the callback on
|
||||
// all the matching elements
|
||||
@@ -759,18 +752,6 @@ const char *nsPrefBranch::getPrefName(const char *aPrefName)
|
||||
return mPrefRoot.get();
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
pref_enumChild(PLDHashTable *table, PLDHashEntryHdr *heh,
|
||||
uint32_t i, void *arg)
|
||||
{
|
||||
PrefHashEntry *he = static_cast<PrefHashEntry*>(heh);
|
||||
EnumerateData *d = reinterpret_cast<EnumerateData *>(arg);
|
||||
if (strncmp(he->key, d->parent, strlen(d->parent)) == 0) {
|
||||
d->pref_list->AppendElement(he->key);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// nsPrefLocalizedString
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+70
-107
@@ -319,79 +319,54 @@ pref_SetPref(const dom::PrefSetting& aPref)
|
||||
return rv;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, uint32_t i, void *arg)
|
||||
void
|
||||
pref_savePrefs(PLDHashTable* aTable, char** aPrefArray)
|
||||
{
|
||||
pref_saveArgs *argData = static_cast<pref_saveArgs *>(arg);
|
||||
PrefHashEntry *pref = static_cast<PrefHashEntry *>(heh);
|
||||
int32_t j = 0;
|
||||
for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto pref = static_cast<PrefHashEntry*>(iter.Get());
|
||||
|
||||
PR_ASSERT(pref);
|
||||
if (!pref)
|
||||
return PL_DHASH_NEXT;
|
||||
nsAutoCString prefValue;
|
||||
nsAutoCString prefPrefix;
|
||||
prefPrefix.AssignLiteral("user_pref(\"");
|
||||
|
||||
nsAutoCString prefValue;
|
||||
nsAutoCString prefPrefix;
|
||||
prefPrefix.AssignLiteral("user_pref(\"");
|
||||
// where we're getting our pref from
|
||||
PrefValue* sourcePref;
|
||||
|
||||
// where we're getting our pref from
|
||||
PrefValue* sourcePref;
|
||||
|
||||
if (PREF_HAS_USER_VALUE(pref) &&
|
||||
(pref_ValueChanged(pref->defaultPref,
|
||||
pref->userPref,
|
||||
(PrefType) PREF_TYPE(pref)) ||
|
||||
!(pref->flags & PREF_HAS_DEFAULT) ||
|
||||
pref->flags & PREF_STICKY_DEFAULT)) {
|
||||
sourcePref = &pref->userPref;
|
||||
} else {
|
||||
if (argData->saveTypes == SAVE_ALL_AND_DEFAULTS) {
|
||||
prefPrefix.AssignLiteral("pref(\"");
|
||||
sourcePref = &pref->defaultPref;
|
||||
}
|
||||
else
|
||||
if (PREF_HAS_USER_VALUE(pref) &&
|
||||
(pref_ValueChanged(pref->defaultPref,
|
||||
pref->userPref,
|
||||
(PrefType) PREF_TYPE(pref)) ||
|
||||
!(pref->flags & PREF_HAS_DEFAULT) ||
|
||||
pref->flags & PREF_STICKY_DEFAULT)) {
|
||||
sourcePref = &pref->userPref;
|
||||
} else {
|
||||
// do not save default prefs that haven't changed
|
||||
return PL_DHASH_NEXT;
|
||||
continue;
|
||||
}
|
||||
|
||||
// strings are in quotes!
|
||||
if (pref->flags & PREF_STRING) {
|
||||
prefValue = '\"';
|
||||
str_escape(sourcePref->stringVal, prefValue);
|
||||
prefValue += '\"';
|
||||
|
||||
} else if (pref->flags & PREF_INT) {
|
||||
prefValue.AppendInt(sourcePref->intVal);
|
||||
|
||||
} else if (pref->flags & PREF_BOOL) {
|
||||
prefValue = (sourcePref->boolVal) ? "true" : "false";
|
||||
}
|
||||
|
||||
nsAutoCString prefName;
|
||||
str_escape(pref->key, prefName);
|
||||
|
||||
aPrefArray[j++] = ToNewCString(prefPrefix +
|
||||
prefName +
|
||||
NS_LITERAL_CSTRING("\", ") +
|
||||
prefValue +
|
||||
NS_LITERAL_CSTRING(");"));
|
||||
}
|
||||
|
||||
// strings are in quotes!
|
||||
if (pref->flags & PREF_STRING) {
|
||||
prefValue = '\"';
|
||||
str_escape(sourcePref->stringVal, prefValue);
|
||||
prefValue += '\"';
|
||||
}
|
||||
|
||||
else if (pref->flags & PREF_INT)
|
||||
prefValue.AppendInt(sourcePref->intVal);
|
||||
|
||||
else if (pref->flags & PREF_BOOL)
|
||||
prefValue = (sourcePref->boolVal) ? "true" : "false";
|
||||
|
||||
nsAutoCString prefName;
|
||||
str_escape(pref->key, prefName);
|
||||
|
||||
argData->prefArray[i] = ToNewCString(prefPrefix +
|
||||
prefName +
|
||||
NS_LITERAL_CSTRING("\", ") +
|
||||
prefValue +
|
||||
NS_LITERAL_CSTRING(");"));
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
pref_GetPrefs(PLDHashTable *table,
|
||||
PLDHashEntryHdr *heh,
|
||||
uint32_t i,
|
||||
void *arg)
|
||||
{
|
||||
if (heh) {
|
||||
PrefHashEntry *entry = static_cast<PrefHashEntry *>(heh);
|
||||
dom::PrefSetting *pref =
|
||||
static_cast<InfallibleTArray<dom::PrefSetting>*>(arg)->AppendElement();
|
||||
|
||||
pref_GetPrefFromEntry(entry, pref);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -555,23 +530,6 @@ nsresult PREF_GetBoolPref(const char *pref_name, bool * return_value, bool get_d
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Delete a branch. Used for deleting mime types */
|
||||
static PLDHashOperator
|
||||
pref_DeleteItem(PLDHashTable *table, PLDHashEntryHdr *heh, uint32_t i, void *arg)
|
||||
{
|
||||
PrefHashEntry* he = static_cast<PrefHashEntry*>(heh);
|
||||
const char *to_delete = (const char *) arg;
|
||||
int len = strlen(to_delete);
|
||||
|
||||
/* note if we're deleting "ldap" then we want to delete "ldap.xxx"
|
||||
and "ldap" (if such a leaf node exists) but not "ldap_1.xxx" */
|
||||
if (to_delete && (PL_strncmp(he->key, to_delete, (uint32_t) len) == 0 ||
|
||||
(len-1 == (int)strlen(he->key) && PL_strncmp(he->key, to_delete, (uint32_t)(len-1)) == 0)))
|
||||
return PL_DHASH_REMOVE;
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PREF_DeleteBranch(const char *branch_name)
|
||||
{
|
||||
@@ -594,8 +552,22 @@ PREF_DeleteBranch(const char *branch_name)
|
||||
if ((len > 1) && branch_name[len - 1] != '.')
|
||||
branch_dot += '.';
|
||||
|
||||
PL_DHashTableEnumerate(gHashTable, pref_DeleteItem,
|
||||
(void*) branch_dot.get());
|
||||
/* Delete a branch. Used for deleting mime types */
|
||||
const char *to_delete = branch_dot.get();
|
||||
MOZ_ASSERT(to_delete);
|
||||
len = strlen(to_delete);
|
||||
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<PrefHashEntry*>(iter.Get());
|
||||
|
||||
/* note if we're deleting "ldap" then we want to delete "ldap.xxx"
|
||||
and "ldap" (if such a leaf node exists) but not "ldap_1.xxx" */
|
||||
if (PL_strncmp(entry->key, to_delete, (uint32_t) len) == 0 ||
|
||||
(len-1 == (int)strlen(entry->key) &&
|
||||
PL_strncmp(entry->key, to_delete, (uint32_t)(len-1)) == 0)) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
|
||||
gDirty = true;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -622,26 +594,6 @@ PREF_ClearUserPref(const char *pref_name)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
pref_ClearUserPref(PLDHashTable *table, PLDHashEntryHdr *he, uint32_t,
|
||||
void *arg)
|
||||
{
|
||||
PrefHashEntry *pref = static_cast<PrefHashEntry*>(he);
|
||||
|
||||
PLDHashOperator nextOp = PL_DHASH_NEXT;
|
||||
|
||||
if (PREF_HAS_USER_VALUE(pref))
|
||||
{
|
||||
pref->flags &= ~PREF_USERSET;
|
||||
|
||||
if (!(pref->flags & PREF_HAS_DEFAULT)) {
|
||||
nextOp = PL_DHASH_REMOVE;
|
||||
}
|
||||
static_cast<std::vector<std::string>*>(arg)->push_back(std::string(pref->key));
|
||||
}
|
||||
return nextOp;
|
||||
}
|
||||
|
||||
nsresult
|
||||
PREF_ClearAllUserPrefs()
|
||||
{
|
||||
@@ -653,7 +605,18 @@ PREF_ClearAllUserPrefs()
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
|
||||
std::vector<std::string> prefStrings;
|
||||
PL_DHashTableEnumerate(gHashTable, pref_ClearUserPref, static_cast<void*>(&prefStrings));
|
||||
for (auto iter = gHashTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto pref = static_cast<PrefHashEntry*>(iter.Get());
|
||||
|
||||
if (PREF_HAS_USER_VALUE(pref)) {
|
||||
prefStrings.push_back(std::string(pref->key));
|
||||
|
||||
pref->flags &= ~PREF_USERSET;
|
||||
if (!(pref->flags & PREF_HAS_DEFAULT)) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (std::string& prefString : prefStrings) {
|
||||
pref_DoCallback(prefString.c_str());
|
||||
|
||||
@@ -19,20 +19,8 @@ class PrefSetting;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
enum pref_SaveTypes { SAVE_NONSHARED, SAVE_SHARED, SAVE_ALL, SAVE_ALL_AND_DEFAULTS };
|
||||
|
||||
// Passed as the arg to pref_savePref
|
||||
struct pref_saveArgs {
|
||||
char **prefArray;
|
||||
pref_SaveTypes saveTypes;
|
||||
};
|
||||
|
||||
PLDHashOperator
|
||||
pref_savePref(PLDHashTable *table, PLDHashEntryHdr *heh, uint32_t i, void *arg);
|
||||
|
||||
PLDHashOperator
|
||||
pref_GetPrefs(PLDHashTable *table,
|
||||
PLDHashEntryHdr *heh, uint32_t i, void *arg);
|
||||
void
|
||||
pref_savePrefs(PLDHashTable* aTable, char** aPrefArray);
|
||||
|
||||
nsresult
|
||||
pref_SetPref(const mozilla::dom::PrefSetting& aPref);
|
||||
|
||||
Vendored
+3
-7
@@ -462,16 +462,12 @@ nsCacheEntryHashTable::RemoveEntry( nsCacheEntry *cacheEntry)
|
||||
PL_DHashTableRemove(&table, &(cacheEntry->mKey));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsCacheEntryHashTable::VisitEntries( PLDHashEnumerator etor, void *arg)
|
||||
PLDHashTable::Iterator
|
||||
nsCacheEntryHashTable::Iter()
|
||||
{
|
||||
NS_ASSERTION(initialized, "nsCacheEntryHashTable not initialized");
|
||||
if (!initialized) return; // NS_ERROR_NOT_INITIALIZED
|
||||
PL_DHashTableEnumerate(&table, etor, arg);
|
||||
return PLDHashTable::Iterator(&table);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hash table operation callback functions
|
||||
*/
|
||||
|
||||
Vendored
+5
-16
@@ -255,11 +255,11 @@ private:
|
||||
/******************************************************************************
|
||||
* nsCacheEntryHashTable
|
||||
*******************************************************************************/
|
||||
typedef struct {
|
||||
PLDHashNumber keyHash;
|
||||
nsCacheEntry *cacheEntry;
|
||||
} nsCacheEntryHashTableEntry;
|
||||
|
||||
struct nsCacheEntryHashTableEntry : public PLDHashEntryHdr
|
||||
{
|
||||
nsCacheEntry *cacheEntry;
|
||||
};
|
||||
|
||||
class nsCacheEntryHashTable
|
||||
{
|
||||
@@ -274,7 +274,7 @@ public:
|
||||
nsresult AddEntry( nsCacheEntry *entry);
|
||||
void RemoveEntry( nsCacheEntry *entry);
|
||||
|
||||
void VisitEntries( PLDHashEnumerator etor, void *arg);
|
||||
PLDHashTable::Iterator Iter();
|
||||
|
||||
private:
|
||||
// PLDHashTable operation callbacks
|
||||
@@ -292,17 +292,6 @@ private:
|
||||
|
||||
static void Finalize( PLDHashTable *table);
|
||||
|
||||
static
|
||||
PLDHashOperator FreeCacheEntries(PLDHashTable * table,
|
||||
PLDHashEntryHdr * hdr,
|
||||
uint32_t number,
|
||||
void * arg);
|
||||
static
|
||||
PLDHashOperator VisitEntry(PLDHashTable * table,
|
||||
PLDHashEntryHdr * hdr,
|
||||
uint32_t number,
|
||||
void * arg);
|
||||
|
||||
// member variables
|
||||
static const PLDHashTableOps ops;
|
||||
PLDHashTable table;
|
||||
|
||||
Vendored
+20
-43
@@ -2883,58 +2883,32 @@ nsCacheService::ClearDoomList()
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsCacheService::GetActiveEntries(PLDHashTable * table,
|
||||
PLDHashEntryHdr * hdr,
|
||||
uint32_t number,
|
||||
void * arg)
|
||||
{
|
||||
static_cast<nsTArray<nsCacheEntry*>*>(arg)->AppendElement(
|
||||
((nsCacheEntryHashTableEntry *)hdr)->cacheEntry);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
struct ActiveEntryArgs
|
||||
{
|
||||
nsTArray<nsCacheEntry*>* mActiveArray;
|
||||
nsCacheService::DoomCheckFn mCheckFn;
|
||||
};
|
||||
|
||||
void
|
||||
nsCacheService::DoomActiveEntries(DoomCheckFn check)
|
||||
{
|
||||
nsAutoTArray<nsCacheEntry*, 8> array;
|
||||
ActiveEntryArgs args = { &array, check };
|
||||
|
||||
mActiveEntries.VisitEntries(RemoveActiveEntry, &args);
|
||||
for (auto iter = mActiveEntries.Iter(); !iter.Done(); iter.Next()) {
|
||||
nsCacheEntry* entry =
|
||||
static_cast<nsCacheEntryHashTableEntry*>(iter.Get())->cacheEntry;
|
||||
|
||||
if (check && !check(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
array.AppendElement(entry);
|
||||
|
||||
// entry is being removed from the active entry list
|
||||
entry->MarkInactive();
|
||||
iter.Remove();
|
||||
}
|
||||
|
||||
uint32_t count = array.Length();
|
||||
for (uint32_t i=0; i < count; ++i)
|
||||
for (uint32_t i = 0; i < count; ++i) {
|
||||
DoomEntry_Internal(array[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsCacheService::RemoveActiveEntry(PLDHashTable * table,
|
||||
PLDHashEntryHdr * hdr,
|
||||
uint32_t number,
|
||||
void * arg)
|
||||
{
|
||||
nsCacheEntry * entry = ((nsCacheEntryHashTableEntry *)hdr)->cacheEntry;
|
||||
NS_ASSERTION(entry, "### active entry = nullptr!");
|
||||
|
||||
ActiveEntryArgs* args = static_cast<ActiveEntryArgs*>(arg);
|
||||
if (args->mCheckFn && !args->mCheckFn(entry))
|
||||
return PL_DHASH_NEXT;
|
||||
|
||||
NS_ASSERTION(args->mActiveArray, "### array = nullptr!");
|
||||
args->mActiveArray->AppendElement(entry);
|
||||
|
||||
// entry is being removed from the active entry list
|
||||
entry->MarkInactive();
|
||||
return PL_DHASH_REMOVE; // and continue enumerating
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsCacheService::CloseAllStreams()
|
||||
{
|
||||
@@ -2948,7 +2922,10 @@ nsCacheService::CloseAllStreams()
|
||||
|
||||
#if DEBUG
|
||||
// make sure there is no active entry
|
||||
mActiveEntries.VisitEntries(GetActiveEntries, &entries);
|
||||
for (auto iter = mActiveEntries.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<nsCacheEntryHashTableEntry*>(iter.Get());
|
||||
entries.AppendElement(entry->cacheEntry);
|
||||
}
|
||||
NS_ASSERTION(entries.IsEmpty(), "Bad state");
|
||||
#endif
|
||||
|
||||
|
||||
Vendored
-11
@@ -310,17 +310,6 @@ private:
|
||||
void CloseAllStreams();
|
||||
void FireClearNetworkCacheStoredAnywhereNotification();
|
||||
|
||||
static
|
||||
PLDHashOperator GetActiveEntries(PLDHashTable * table,
|
||||
PLDHashEntryHdr * hdr,
|
||||
uint32_t number,
|
||||
void * arg);
|
||||
static
|
||||
PLDHashOperator RemoveActiveEntry(PLDHashTable * table,
|
||||
PLDHashEntryHdr * hdr,
|
||||
uint32_t number,
|
||||
void * arg);
|
||||
|
||||
static
|
||||
PLDHashOperator ShutdownCustomCacheDeviceEnum(const nsAString& aProfileDir,
|
||||
nsRefPtr<nsOfflineCacheDevice>& aDevice,
|
||||
|
||||
+4
-10
@@ -527,14 +527,6 @@ nsMemoryCacheDevice::SetMaxEntrySize(int32_t maxSizeInKilobytes)
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
static PLDHashOperator
|
||||
CountEntry(PLDHashTable * table, PLDHashEntryHdr * hdr, uint32_t number, void * arg)
|
||||
{
|
||||
int32_t *entryCount = (int32_t *)arg;
|
||||
++(*entryCount);
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsMemoryCacheDevice::CheckEntryCount()
|
||||
{
|
||||
@@ -551,8 +543,10 @@ nsMemoryCacheDevice::CheckEntryCount()
|
||||
NS_ASSERTION(mEntryCount == evictionListCount, "### mem cache badness");
|
||||
|
||||
int32_t entryCount = 0;
|
||||
mMemCacheEntries.VisitEntries(CountEntry, &entryCount);
|
||||
NS_ASSERTION(mEntryCount == entryCount, "### mem cache badness");
|
||||
for (auto iter = mMemCacheEntries.Iter(); !iter.Done(); iter.Next()) {
|
||||
++entryCount;
|
||||
}
|
||||
NS_ASSERTION(mEntryCount == entryCount, "### mem cache badness");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -489,30 +489,6 @@ static const PLDHashTableOps gHostDB_ops =
|
||||
HostDB_InitEntry,
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
HostDB_RemoveEntry(PLDHashTable *table,
|
||||
PLDHashEntryHdr *hdr,
|
||||
uint32_t number,
|
||||
void *arg)
|
||||
{
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
HostDB_PruneEntry(PLDHashTable *table,
|
||||
PLDHashEntryHdr *hdr,
|
||||
uint32_t number,
|
||||
void *arg)
|
||||
{
|
||||
nsHostDBEnt* ent = static_cast<nsHostDBEnt *>(hdr);
|
||||
// Try to remove the record, or mark it for refresh
|
||||
if (ent->rec->RemoveOrRefresh()) {
|
||||
PR_REMOVE_LINK(ent->rec);
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#if TTL_AVAILABLE
|
||||
@@ -630,24 +606,31 @@ nsHostResolver::ClearPendingQueue(PRCList *aPendingQ)
|
||||
void
|
||||
nsHostResolver::FlushCache()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mEvictionQSize = 0;
|
||||
MutexAutoLock lock(mLock);
|
||||
mEvictionQSize = 0;
|
||||
|
||||
// Clear the evictionQ and remove all its corresponding entries from
|
||||
// the cache first
|
||||
if (!PR_CLIST_IS_EMPTY(&mEvictionQ)) {
|
||||
PRCList *node = mEvictionQ.next;
|
||||
while (node != &mEvictionQ) {
|
||||
nsHostRecord *rec = static_cast<nsHostRecord *>(node);
|
||||
node = node->next;
|
||||
PR_REMOVE_AND_INIT_LINK(rec);
|
||||
PL_DHashTableRemove(&mDB, (nsHostKey *) rec);
|
||||
NS_RELEASE(rec);
|
||||
}
|
||||
}
|
||||
// Clear the evictionQ and remove all its corresponding entries from
|
||||
// the cache first
|
||||
if (!PR_CLIST_IS_EMPTY(&mEvictionQ)) {
|
||||
PRCList *node = mEvictionQ.next;
|
||||
while (node != &mEvictionQ) {
|
||||
nsHostRecord *rec = static_cast<nsHostRecord *>(node);
|
||||
node = node->next;
|
||||
PR_REMOVE_AND_INIT_LINK(rec);
|
||||
PL_DHashTableRemove(&mDB, (nsHostKey *) rec);
|
||||
NS_RELEASE(rec);
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh the cache entries that are resolving RIGHT now, remove the rest.
|
||||
PL_DHashTableEnumerate(&mDB, HostDB_PruneEntry, nullptr);
|
||||
// Refresh the cache entries that are resolving RIGHT now, remove the rest.
|
||||
for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<nsHostDBEnt *>(iter.Get());
|
||||
// Try to remove the record, or mark it for refresh.
|
||||
if (entry->rec->RemoveOrRefresh()) {
|
||||
PR_REMOVE_LINK(entry->rec);
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -686,7 +669,7 @@ nsHostResolver::Shutdown()
|
||||
mIdleThreadCV.NotifyAll();
|
||||
|
||||
// empty host database
|
||||
PL_DHashTableEnumerate(&mDB, HostDB_RemoveEntry, nullptr);
|
||||
mDB.Clear();
|
||||
}
|
||||
|
||||
ClearPendingQueue(&pendingQHigh);
|
||||
@@ -1442,58 +1425,51 @@ nsHostResolver::Create(uint32_t maxCacheEntries,
|
||||
return rv;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
CacheEntryEnumerator(PLDHashTable *table, PLDHashEntryHdr *entry,
|
||||
uint32_t number, void *arg)
|
||||
{
|
||||
// We don't pay attention to address literals, only resolved domains.
|
||||
// Also require a host.
|
||||
nsHostRecord *rec = static_cast<nsHostDBEnt*>(entry)->rec;
|
||||
MOZ_ASSERT(rec, "rec should never be null here!");
|
||||
if (!rec || !rec->addr_info || !rec->host) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
DNSCacheEntries info;
|
||||
info.hostname = rec->host;
|
||||
info.family = rec->af;
|
||||
info.netInterface = rec->netInterface;
|
||||
info.expiration =
|
||||
(int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds();
|
||||
if (info.expiration <= 0) {
|
||||
// We only need valid DNS cache entries
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(rec->addr_info_lock);
|
||||
|
||||
NetAddr *addr = nullptr;
|
||||
NetAddrElement *addrElement = rec->addr_info->mAddresses.getFirst();
|
||||
if (addrElement) {
|
||||
addr = &addrElement->mAddress;
|
||||
}
|
||||
while (addr) {
|
||||
char buf[kIPv6CStrBufSize];
|
||||
if (NetAddrToString(addr, buf, sizeof(buf))) {
|
||||
info.hostaddr.AppendElement(buf);
|
||||
}
|
||||
addr = nullptr;
|
||||
addrElement = addrElement->getNext();
|
||||
if (addrElement) {
|
||||
addr = &addrElement->mAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<DNSCacheEntries> *args = static_cast<nsTArray<DNSCacheEntries> *>(arg);
|
||||
args->AppendElement(info);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
nsHostResolver::GetDNSCacheEntries(nsTArray<DNSCacheEntries> *args)
|
||||
{
|
||||
PL_DHashTableEnumerate(&mDB, CacheEntryEnumerator, args);
|
||||
for (auto iter = mDB.Iter(); !iter.Done(); iter.Next()) {
|
||||
// We don't pay attention to address literals, only resolved domains.
|
||||
// Also require a host.
|
||||
auto entry = static_cast<nsHostDBEnt*>(iter.Get());
|
||||
nsHostRecord* rec = entry->rec;
|
||||
MOZ_ASSERT(rec, "rec should never be null here!");
|
||||
if (!rec || !rec->addr_info || !rec->host) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DNSCacheEntries info;
|
||||
info.hostname = rec->host;
|
||||
info.family = rec->af;
|
||||
info.netInterface = rec->netInterface;
|
||||
info.expiration =
|
||||
(int64_t)(rec->mValidEnd - TimeStamp::NowLoRes()).ToSeconds();
|
||||
if (info.expiration <= 0) {
|
||||
// We only need valid DNS cache entries
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
MutexAutoLock lock(rec->addr_info_lock);
|
||||
|
||||
NetAddr *addr = nullptr;
|
||||
NetAddrElement *addrElement = rec->addr_info->mAddresses.getFirst();
|
||||
if (addrElement) {
|
||||
addr = &addrElement->mAddress;
|
||||
}
|
||||
while (addr) {
|
||||
char buf[kIPv6CStrBufSize];
|
||||
if (NetAddrToString(addr, buf, sizeof(buf))) {
|
||||
info.hostaddr.AppendElement(buf);
|
||||
}
|
||||
addr = nullptr;
|
||||
addrElement = addrElement->getNext();
|
||||
if (addrElement) {
|
||||
addr = &addrElement->mAddress;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args->AppendElement(info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1806,7 +1806,7 @@ void
|
||||
InMemoryDataSource::SweepForwardArcsEntries(PLDHashTable* aTable,
|
||||
SweepInfo* aInfo)
|
||||
{
|
||||
for (auto iter = aTable->RemovingIter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = aTable->Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<Entry*>(iter.Get());
|
||||
|
||||
Assertion* as = entry->mAssertions;
|
||||
|
||||
@@ -133,25 +133,16 @@ nsresult nsNSSShutDownList::doPK11Logout()
|
||||
// This is guaranteed by holding the list lock.
|
||||
|
||||
MutexAutoLock lock(singleton->mListLock);
|
||||
PL_DHashTableEnumerate(&mPK11LogoutCancelObjects, doPK11LogoutHelper, 0);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsNSSShutDownList::doPK11LogoutHelper(PLDHashTable *table,
|
||||
PLDHashEntryHdr *hdr, uint32_t number, void *arg)
|
||||
{
|
||||
ObjectHashEntry *entry = static_cast<ObjectHashEntry*>(hdr);
|
||||
|
||||
nsOnPK11LogoutCancelObject *pklco =
|
||||
reinterpret_cast<nsOnPK11LogoutCancelObject*>(entry->obj);
|
||||
|
||||
if (pklco) {
|
||||
pklco->logout();
|
||||
for (auto iter = mPK11LogoutCancelObjects.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<ObjectHashEntry*>(iter.Get());
|
||||
nsOnPK11LogoutCancelObject *pklco =
|
||||
reinterpret_cast<nsOnPK11LogoutCancelObject*>(entry->obj);
|
||||
if (pklco) {
|
||||
pklco->logout();
|
||||
}
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool nsNSSShutDownList::isUIActive()
|
||||
@@ -180,29 +171,26 @@ nsresult nsNSSShutDownList::evaporateAllNSSResources()
|
||||
}
|
||||
|
||||
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("now evaporating NSS resources\n"));
|
||||
int removedCount;
|
||||
do {
|
||||
MutexAutoLock lock(mListLock);
|
||||
removedCount = PL_DHashTableEnumerate(&mObjects, evaporateAllNSSResourcesHelper, 0);
|
||||
} while (removedCount > 0);
|
||||
|
||||
mActivityState.releaseCurrentThreadActivityRestriction();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsNSSShutDownList::evaporateAllNSSResourcesHelper(PLDHashTable *table,
|
||||
PLDHashEntryHdr *hdr, uint32_t number, void *arg)
|
||||
{
|
||||
ObjectHashEntry *entry = static_cast<ObjectHashEntry*>(hdr);
|
||||
{
|
||||
MutexAutoUnlock unlock(singleton->mListLock);
|
||||
entry->obj->shutdown(nsNSSShutDownObject::calledFromList);
|
||||
}
|
||||
// Never free more than one entry, because other threads might be calling
|
||||
// us and remove themselves while we are iterating over the list,
|
||||
// and the behaviour of changing the list while iterating is undefined.
|
||||
return (PLDHashOperator)(PL_DHASH_STOP | PL_DHASH_REMOVE);
|
||||
while (true) {
|
||||
MutexAutoLock lock(mListLock);
|
||||
auto iter = mObjects.Iter();
|
||||
if (iter.Done()) {
|
||||
break;
|
||||
}
|
||||
auto entry = static_cast<ObjectHashEntry*>(iter.Get());
|
||||
{
|
||||
MutexAutoUnlock unlock(singleton->mListLock);
|
||||
entry->obj->shutdown(nsNSSShutDownObject::calledFromList);
|
||||
}
|
||||
iter.Remove();
|
||||
}
|
||||
|
||||
mActivityState.releaseCurrentThreadActivityRestriction();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsNSSShutDownList *nsNSSShutDownList::construct()
|
||||
|
||||
@@ -147,13 +147,7 @@ public:
|
||||
|
||||
private:
|
||||
nsNSSShutDownList();
|
||||
static PLDHashOperator
|
||||
evaporateAllNSSResourcesHelper(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
uint32_t number, void *arg);
|
||||
|
||||
static PLDHashOperator
|
||||
doPK11LogoutHelper(PLDHashTable *table, PLDHashEntryHdr *hdr,
|
||||
uint32_t number, void *arg);
|
||||
protected:
|
||||
mozilla::Mutex mListLock;
|
||||
static nsNSSShutDownList *singleton;
|
||||
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
uint32_t EnumerateRead(EnumReadFunction aEnumFunc, void* aUserArg) const
|
||||
{
|
||||
uint32_t n = 0;
|
||||
for (auto iter = this->mTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = this->mTable.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<EntryType*>(iter.Get());
|
||||
PLDHashOperator op = aEnumFunc(entry->GetKey(), entry->mData, aUserArg);
|
||||
n++;
|
||||
@@ -204,7 +204,7 @@ public:
|
||||
uint32_t Enumerate(EnumFunction aEnumFunc, void* aUserArg)
|
||||
{
|
||||
uint32_t n = 0;
|
||||
for (auto iter = this->mTable.RemovingIter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = this->mTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<EntryType*>(iter.Get());
|
||||
PLDHashOperator op = aEnumFunc(entry->GetKey(), entry->mData, aUserArg);
|
||||
n++;
|
||||
|
||||
@@ -208,7 +208,7 @@ public:
|
||||
uint32_t EnumerateEntries(Enumerator aEnumFunc, void* aUserArg)
|
||||
{
|
||||
uint32_t n = 0;
|
||||
for (auto iter = mTable.RemovingIter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = mTable.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<EntryType*>(iter.Get());
|
||||
PLDHashOperator op = aEnumFunc(entry, aUserArg);
|
||||
n++;
|
||||
|
||||
+12
-36
@@ -827,7 +827,7 @@ PLDHashTable::SizeOfExcludingThis(
|
||||
|
||||
size_t n = aMallocSizeOf(mEntryStore);
|
||||
if (aSizeOfEntryExcludingThis) {
|
||||
for (auto iter = Iter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = ConstIter(); !iter.Done(); iter.Next()) {
|
||||
n += aSizeOfEntryExcludingThis(iter.Get(), aMallocSizeOf, aArg);
|
||||
}
|
||||
}
|
||||
@@ -868,17 +868,20 @@ PLDHashTable::Iterator::Iterator(Iterator&& aOther)
|
||||
: mTable(aOther.mTable)
|
||||
, mCurrent(aOther.mCurrent)
|
||||
, mLimit(aOther.mLimit)
|
||||
, mHaveRemoved(aOther.mHaveRemoved)
|
||||
{
|
||||
// No need to change |mChecker| here.
|
||||
aOther.mTable = nullptr;
|
||||
aOther.mCurrent = nullptr;
|
||||
aOther.mLimit = nullptr;
|
||||
aOther.mHaveRemoved = false;
|
||||
}
|
||||
|
||||
PLDHashTable::Iterator::Iterator(const PLDHashTable* aTable)
|
||||
PLDHashTable::Iterator::Iterator(PLDHashTable* aTable)
|
||||
: mTable(aTable)
|
||||
, mCurrent(mTable->mEntryStore)
|
||||
, mLimit(mTable->mEntryStore + mTable->Capacity() * mTable->mEntrySize)
|
||||
, mHaveRemoved(false)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
mTable->mChecker.StartReadOp();
|
||||
@@ -892,11 +895,14 @@ PLDHashTable::Iterator::Iterator(const PLDHashTable* aTable)
|
||||
|
||||
PLDHashTable::Iterator::~Iterator()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (mTable) {
|
||||
if (mHaveRemoved) {
|
||||
mTable->ShrinkIfAppropriate();
|
||||
}
|
||||
#ifdef DEBUG
|
||||
mTable->mChecker.EndReadOp();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -931,41 +937,11 @@ PLDHashTable::Iterator::Next()
|
||||
} while (IsOnNonLiveEntry());
|
||||
}
|
||||
|
||||
PLDHashTable::RemovingIterator::RemovingIterator(RemovingIterator&& aOther)
|
||||
: Iterator(mozilla::Move(aOther))
|
||||
, mHaveRemoved(aOther.mHaveRemoved)
|
||||
{
|
||||
// Do nothing with mChecker here. We treat RemovingIterator like Iterator --
|
||||
// i.e. as a read operation -- until the very end. Then, if any elements have
|
||||
// been removed, we temporarily treat it as a write operation.
|
||||
}
|
||||
|
||||
PLDHashTable::RemovingIterator::RemovingIterator(PLDHashTable* aTable)
|
||||
: Iterator(aTable)
|
||||
, mHaveRemoved(false)
|
||||
{
|
||||
}
|
||||
|
||||
PLDHashTable::RemovingIterator::~RemovingIterator()
|
||||
{
|
||||
if (mHaveRemoved) {
|
||||
#ifdef DEBUG
|
||||
AutoIteratorRemovalOp op(mTable->mChecker);
|
||||
#endif
|
||||
|
||||
// Why is this cast needed? In Iterator, |mTable| is const. In
|
||||
// RemovingIterator it should be non-const, but it inherits from Iterator
|
||||
// so that's not possible. But it's ok because RemovingIterator's
|
||||
// constructor takes a pointer to a non-const table in the first place.
|
||||
const_cast<PLDHashTable*>(mTable)->ShrinkIfAppropriate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PLDHashTable::RemovingIterator::Remove()
|
||||
PLDHashTable::Iterator::Remove()
|
||||
{
|
||||
// This cast is needed for the same reason as the one in the destructor.
|
||||
const_cast<PLDHashTable*>(mTable)->RawRemove(Get());
|
||||
mTable->RawRemove(Get());
|
||||
mHaveRemoved = true;
|
||||
}
|
||||
|
||||
|
||||
+22
-32
@@ -404,15 +404,19 @@ public:
|
||||
|
||||
void ClearEntryStub(PLDHashEntryHdr* aEntry);
|
||||
|
||||
// This is an iterator for PLDHashtable. It is not safe to modify the
|
||||
// table while it is being iterated over; on debug builds, attempting to do
|
||||
// so will result in an assertion failure.
|
||||
// This is an iterator for PLDHashtable. Assertions will detect some, but not
|
||||
// all, mid-iteration table modifications that might invalidate (e.g.
|
||||
// reallocate) the entry storage.
|
||||
//
|
||||
// Any element can be removed during iteration using Remove(). If any
|
||||
// elements are removed, the table may be resized once iteration ends.
|
||||
//
|
||||
// Example usage:
|
||||
//
|
||||
// for (auto iter = table.Iter(); !iter.Done(); iter.Next()) {
|
||||
// auto entry = static_cast<FooEntry*>(iter.Get());
|
||||
// // ... do stuff with |entry| ...
|
||||
// // ... possibly call iter.Remove() once ...
|
||||
// }
|
||||
//
|
||||
// or:
|
||||
@@ -420,6 +424,7 @@ public:
|
||||
// for (PLDHashTable::Iterator iter(&table); !iter.Done(); iter.Next()) {
|
||||
// auto entry = static_cast<FooEntry*>(iter.Get());
|
||||
// // ... do stuff with |entry| ...
|
||||
// // ... possibly call iter.Remove() once ...
|
||||
// }
|
||||
//
|
||||
// The latter form is more verbose but is easier to work with when
|
||||
@@ -428,20 +433,27 @@ public:
|
||||
class Iterator
|
||||
{
|
||||
public:
|
||||
explicit Iterator(const PLDHashTable* aTable);
|
||||
explicit Iterator(PLDHashTable* aTable);
|
||||
Iterator(Iterator&& aOther);
|
||||
~Iterator();
|
||||
|
||||
bool Done() const; // Have we finished?
|
||||
PLDHashEntryHdr* Get() const; // Get the current entry.
|
||||
void Next(); // Advance to the next entry.
|
||||
|
||||
// Remove the current entry. Must only be called once per entry, and Get()
|
||||
// must not be called on that entry afterwards.
|
||||
void Remove();
|
||||
|
||||
protected:
|
||||
const PLDHashTable* mTable; // Main table pointer.
|
||||
PLDHashTable* mTable; // Main table pointer.
|
||||
|
||||
private:
|
||||
char* mCurrent; // Pointer to the current entry.
|
||||
char* mLimit; // One past the last entry.
|
||||
|
||||
bool mHaveRemoved; // Have any elements been removed?
|
||||
|
||||
bool IsOnNonLiveEntry() const;
|
||||
|
||||
Iterator() = delete;
|
||||
@@ -450,35 +462,13 @@ public:
|
||||
Iterator& operator=(const Iterator&&) = delete;
|
||||
};
|
||||
|
||||
Iterator Iter() const { return Iterator(this); }
|
||||
Iterator Iter() { return Iterator(this); }
|
||||
|
||||
// This is an iterator that allows elements to be removed during iteration.
|
||||
// If any elements are removed, the table may be resized once iteration ends.
|
||||
// Its usage is similar to that of Iterator, with the addition that Remove()
|
||||
// can be called once per element.
|
||||
class RemovingIterator : public Iterator
|
||||
// Use this if you need to initialize an Iterator in a const method. If you
|
||||
// use this case, you should not call Remove() on the iterator.
|
||||
Iterator ConstIter() const
|
||||
{
|
||||
public:
|
||||
explicit RemovingIterator(PLDHashTable* aTable);
|
||||
RemovingIterator(RemovingIterator&& aOther);
|
||||
~RemovingIterator();
|
||||
|
||||
// Remove the current entry. Must only be called once per entry, and Get()
|
||||
// must not be called on that entry afterwards.
|
||||
void Remove();
|
||||
|
||||
private:
|
||||
bool mHaveRemoved; // Have any elements been removed?
|
||||
|
||||
RemovingIterator() = delete;
|
||||
RemovingIterator(const RemovingIterator&) = delete;
|
||||
RemovingIterator& operator=(const RemovingIterator&) = delete;
|
||||
RemovingIterator& operator=(const RemovingIterator&&) = delete;
|
||||
};
|
||||
|
||||
RemovingIterator RemovingIter() const
|
||||
{
|
||||
return RemovingIterator(const_cast<PLDHashTable*>(this));
|
||||
return Iterator(const_cast<PLDHashTable*>(this));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -51,10 +51,6 @@ TEST(PLDHashTableTest, LazyStorage)
|
||||
ASSERT_TRUE(false); // shouldn't hit this on an empty table
|
||||
}
|
||||
|
||||
for (auto iter = t.RemovingIter(); !iter.Done(); iter.Next()) {
|
||||
ASSERT_TRUE(false); // shouldn't hit this on an empty table
|
||||
}
|
||||
|
||||
// Using a null |mallocSizeOf| should be fine because it shouldn't be called
|
||||
// for an empty table.
|
||||
mozilla::MallocSizeOf mallocSizeOf = nullptr;
|
||||
@@ -185,19 +181,8 @@ TEST(PLDHashTableIterator, Iterator)
|
||||
n++;
|
||||
}
|
||||
ASSERT_TRUE(saw77 && saw88 && saw99 && n == 3);
|
||||
}
|
||||
|
||||
TEST(PLDHashTableTest, RemovingIterator)
|
||||
{
|
||||
PLDHashTable t(&trivialOps, sizeof(PLDHashEntryStub));
|
||||
|
||||
// Explicitly test the move constructor. We do this because, due to copy
|
||||
// elision, compilers might optimize away move constructor calls for normal
|
||||
// iterator use.
|
||||
{
|
||||
PLDHashTable::RemovingIterator iter1(&t);
|
||||
PLDHashTable::RemovingIterator iter2(mozilla::Move(iter1));
|
||||
}
|
||||
t.Clear();
|
||||
|
||||
// First, we insert 64 items, which results in a capacity of 128, and a load
|
||||
// factor of 50%.
|
||||
@@ -209,7 +194,7 @@ TEST(PLDHashTableTest, RemovingIterator)
|
||||
|
||||
// The first removing iterator does no removing; capacity and entry count are
|
||||
// unchanged.
|
||||
for (PLDHashTable::RemovingIterator iter(&t); !iter.Done(); iter.Next()) {
|
||||
for (PLDHashTable::Iterator iter(&t); !iter.Done(); iter.Next()) {
|
||||
(void) iter.Get();
|
||||
}
|
||||
ASSERT_EQ(t.EntryCount(), 64u);
|
||||
@@ -217,7 +202,7 @@ TEST(PLDHashTableTest, RemovingIterator)
|
||||
|
||||
// The second removing iterator removes 16 items. This reduces the load
|
||||
// factor to 37.5% (48 / 128), which isn't low enough to shrink the table.
|
||||
for (auto iter = t.RemovingIter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = t.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<PLDHashEntryStub*>(iter.Get());
|
||||
if ((intptr_t)(entry->key) % 4 == 0) {
|
||||
iter.Remove();
|
||||
@@ -228,7 +213,7 @@ TEST(PLDHashTableTest, RemovingIterator)
|
||||
|
||||
// The third removing iterator removes another 16 items. This reduces
|
||||
// the load factor to 25% (32 / 128), so the table is shrunk.
|
||||
for (auto iter = t.RemovingIter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = t.Iter(); !iter.Done(); iter.Next()) {
|
||||
auto entry = static_cast<PLDHashEntryStub*>(iter.Get());
|
||||
if ((intptr_t)(entry->key) % 2 == 0) {
|
||||
iter.Remove();
|
||||
@@ -239,7 +224,7 @@ TEST(PLDHashTableTest, RemovingIterator)
|
||||
|
||||
// The fourth removing iterator removes all remaining items. This reduces
|
||||
// the capacity to the minimum.
|
||||
for (auto iter = t.RemovingIter(); !iter.Done(); iter.Next()) {
|
||||
for (auto iter = t.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.Remove();
|
||||
}
|
||||
ASSERT_EQ(t.EntryCount(), 0u);
|
||||
|
||||
Reference in New Issue
Block a user