Attachment #805980: Frame constructor support for multiple ::before/::after per frame; deal with them when display:contents is involved. for bug #907396

View | Details | Raw Unified | Return to bug 907396
Collapse All | Expand All

(-)a/layout/base/nsCSSFrameConstructor.cpp (-20 / +54 lines)
Line     Link Here 
 Lines 5386-5419   nsCSSFrameConstructor::AddFrameConstruct Link Here 
5386
      ((bits & FCDATA_DISALLOW_OUT_OF_FLOW) ||
5386
      ((bits & FCDATA_DISALLOW_OUT_OF_FLOW) ||
5387
       !aState.GetGeometricParent(display, nullptr))) {
5387
       !aState.GetGeometricParent(display, nullptr))) {
5388
    item->mIsLineParticipant = true;
5388
    item->mIsLineParticipant = true;
5389
    aItems.LineParticipantItemAdded();
5389
    aItems.LineParticipantItemAdded();
5390
  }
5390
  }
5391
}
5391
}
5392
5392
5393
static void
5393
static void
5394
DestroyContent(void* aPropertyValue)
5394
DestroyContentArray(void* aPropertyValue)
5395
{
5395
{
5396
  nsIContent* content = static_cast<nsIContent*>(aPropertyValue);
5396
  typedef nsTArray<nsIContent*> T;
5397
  content->UnbindFromTree();
5397
  T* arr = static_cast<T*>(aPropertyValue);
5398
  NS_RELEASE(content);
5398
  for (T::size_type i = 0; i < arr->Length(); ++i) {
5399
}
5399
    nsIContent* content = (*arr)[i];
5400
5400
    content->UnbindFromTree();
5401
NS_DECLARE_FRAME_PROPERTY(BeforeProperty, DestroyContent)
5401
    NS_RELEASE(content);
5402
NS_DECLARE_FRAME_PROPERTY(AfterProperty, DestroyContent)
5402
  }
5403
5403
  delete arr;
5404
static const FramePropertyDescriptor*
5404
}
5405
GenConPseudoToProperty(nsIAtom* aPseudo)
5405
5406
{
5406
NS_DECLARE_FRAME_PROPERTY(GenConProperty, DestroyContentArray)
5407
  NS_ASSERTION(aPseudo == nsCSSPseudoElements::before ||
5407
5408
               aPseudo == nsCSSPseudoElements::after,
5408
static void
5409
               "Bad gen-con pseudo");
5409
AddGenConPseudoToFrame(nsIFrame* aOwnerFrame, nsIAtom* aPseudo,
5410
  return aPseudo == nsCSSPseudoElements::before ? BeforeProperty()
5410
                       nsIContent* aContent)
5411
      : AfterProperty();
5411
{
5412
  typedef nsTArray<nsIContent*> T;
5413
  const FramePropertyDescriptor* prop = GenConProperty();
5414
  FrameProperties props = aOwnerFrame->Properties();
5415
  T* value = static_cast<T*>(props.Get(prop));
5416
  if (!value) {
5417
    value = new T(2);
5418
    props.Set(prop, value);
5419
  }
5420
  value->AppendElement(aContent);
5421
}
5422
5423
static nsTArray<nsIContent*>*
5424
GetGenConPseudos(nsIFrame* aOwnerFrame)
5425
{
5426
  const FramePropertyDescriptor* prop = GenConProperty();
5427
  FrameProperties props = aOwnerFrame->Properties();
5428
  return static_cast<nsTArray<nsIContent*> *>(props.Get(prop));
5412
}
5429
}
5413
5430
5414
/**
5431
/**
5415
 * Return true if the frame construction item pointed to by aIter will
5432
 * Return true if the frame construction item pointed to by aIter will
5416
 * create a frame adjacent to a line boundary in the frame tree, and that
5433
 * create a frame adjacent to a line boundary in the frame tree, and that
5417
 * line boundary is induced by a content node adjacent to the frame's
5434
 * line boundary is induced by a content node adjacent to the frame's
5418
 * content node in the content tree. The latter condition is necessary so
5435
 * content node in the content tree. The latter condition is necessary so
5419
 * that ContentAppended/ContentInserted/ContentRemoved can easily find any
5436
 * that ContentAppended/ContentInserted/ContentRemoved can easily find any
 Lines 5506-5523   nsCSSFrameConstructor::ConstructFramesFr Link Here 
5506
    // NS_FRAME_GENERATED_CONTENT.
5523
    // NS_FRAME_GENERATED_CONTENT.
5507
    aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
5524
    aState.mAdditionalStateBits |= NS_FRAME_GENERATED_CONTENT;
5508
5525
5509
    // Note that we're not necessarily setting this property on the primary
5526
    // Note that we're not necessarily setting this property on the primary
5510
    // frame for the content for which this is generated content.  We might be
5527
    // frame for the content for which this is generated content.  We might be
5511
    // setting it on a table pseudo-frame inserted under that instead.  That's
5528
    // setting it on a table pseudo-frame inserted under that instead.  That's
5512
    // OK, though; we just need to do the property set so that the content will
5529
    // OK, though; we just need to do the property set so that the content will
5513
    // get cleaned up when the frame is destroyed.
5530
    // get cleaned up when the frame is destroyed.
5514
    aParentFrame->Properties().Set(GenConPseudoToProperty(styleContext->GetPseudo()),
5531
    ::AddGenConPseudoToFrame(aParentFrame, styleContext->GetPseudo(),
5515
                                   item.mContent);
5532
                             item.mContent);
5516
5533
5517
    // Now that we've passed ownership of item.mContent to the frame, unset
5534
    // Now that we've passed ownership of item.mContent to the frame, unset
5518
    // our generated content flag so we don't release or unbind it ourselves.
5535
    // our generated content flag so we don't release or unbind it ourselves.
5519
    item.mIsGeneratedContent = false;
5536
    item.mIsGeneratedContent = false;
5520
  }
5537
  }
5521
5538
5522
  // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
5539
  // XXXbz maybe just inline ConstructFrameFromItemInternal here or something?
5523
  ConstructFrameFromItemInternal(item, aState, adjParentFrame, aFrameItems);
5540
  ConstructFrameFromItemInternal(item, aState, adjParentFrame, aFrameItems);
 Lines 7402-7417   nsCSSFrameConstructor::ContentRemoved(ns Link Here 
7402
  if (!childFrame || childFrame->GetContent() != aChild) {
7419
  if (!childFrame || childFrame->GetContent() != aChild) {
7403
    // XXXbz the GetContent() != aChild check is needed due to bug 135040.
7420
    // XXXbz the GetContent() != aChild check is needed due to bug 135040.
7404
    // Remove it once that's fixed.
7421
    // Remove it once that's fixed.
7405
    ClearUndisplayedContentIn(aChild, aContainer);
7422
    ClearUndisplayedContentIn(aChild, aContainer);
7406
  }
7423
  }
7407
  MOZ_ASSERT(!childFrame || !GetDisplayContents(aChild),
7424
  MOZ_ASSERT(!childFrame || !GetDisplayContents(aChild),
7408
             "display:contents nodes shouldn't have a frame");
7425
             "display:contents nodes shouldn't have a frame");
7409
  if (!childFrame && GetDisplayContents(aChild)) {
7426
  if (!childFrame && GetDisplayContents(aChild)) {
7427
    nsIFrame* ancestorFrame = nullptr;
7428
    for (nsIContent* p = aContainer; p && !ancestorFrame; p = p->GetParent()) {
7429
      ancestorFrame = p->GetPrimaryFrame();
7430
    }
7431
    if (ancestorFrame) {
7432
      nsTArray<nsIContent*>* generated = GetGenConPseudos(ancestorFrame);
7433
      if (generated) {
7434
        LAYOUT_PHASE_TEMP_EXIT();
7435
        // XXXmats Can we recreate frames only for the ::after/::before content?
7436
        // XXX Perhaps even only those that belong to the aChild sub-tree?
7437
        RecreateFramesForContent(ancestorFrame->GetContent(), false);
7438
        LAYOUT_PHASE_TEMP_REENTER();
7439
        *aDidReconstruct = true;
7440
        return NS_OK;
7441
      }
7442
    }
7443
7410
    FlattenedChildIterator iter(aChild);
7444
    FlattenedChildIterator iter(aChild);
7411
    for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
7445
    for (nsIContent* c = iter.GetNextChild(); c; c = iter.GetNextChild()) {
7412
      if (c->GetPrimaryFrame() || GetDisplayContents(c)) {
7446
      if (c->GetPrimaryFrame() || GetDisplayContents(c)) {
7413
        LAYOUT_PHASE_TEMP_EXIT();
7447
        LAYOUT_PHASE_TEMP_EXIT();
7414
        rv = ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct);
7448
        rv = ContentRemoved(aChild, c, nullptr, aFlags, aDidReconstruct);
7415
        LAYOUT_PHASE_TEMP_REENTER();
7449
        LAYOUT_PHASE_TEMP_REENTER();
7416
        NS_ENSURE_SUCCESS(rv, rv);
7450
        NS_ENSURE_SUCCESS(rv, rv);
7417
        if (*aDidReconstruct) {
7451
        if (*aDidReconstruct) {

Return to bug 907396