layout/generic/nsRubyTextContainerFrame.cpp
author Xidorn Quan <quanxunzhen@gmail.com>
Thu, 08 Jan 2015 23:20:16 +1100
changeset 222629 2ee5068037f2639dd7bed0ac957ad4887f88a446
parent 221826 305b1834db8549169de1e3880bf1de859e48cbf9
child 222691 84572abd99ab5eb6161121efbbfd67d267f0a563
permissions -rw-r--r--
Bug 1055658 part 4 - Revert RubyReflowState. r=dbaron

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 et sw=2 tw=80: */
/* This Source Code is subject to the terms of the Mozilla Public License
 * version 2.0 (the "License"). You can obtain a copy of the License at
 * http://mozilla.org/MPL/2.0/. */

/* rendering object for CSS "display: ruby-text-container" */

#include "nsRubyTextContainerFrame.h"
#include "nsPresContext.h"
#include "nsStyleContext.h"
#include "WritingModes.h"
#include "mozilla/UniquePtr.h"

using namespace mozilla;

//----------------------------------------------------------------------

// Frame class boilerplate
// =======================

NS_QUERYFRAME_HEAD(nsRubyTextContainerFrame)
  NS_QUERYFRAME_ENTRY(nsRubyTextContainerFrame)
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)

NS_IMPL_FRAMEARENA_HELPERS(nsRubyTextContainerFrame)

nsContainerFrame*
NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
                             nsStyleContext* aContext)
{
  return new (aPresShell) nsRubyTextContainerFrame(aContext);
}


//----------------------------------------------------------------------

// nsRubyTextContainerFrame Method Implementations
// ===============================================

nsIAtom*
nsRubyTextContainerFrame::GetType() const
{
  return nsGkAtoms::rubyTextContainerFrame;
}

#ifdef DEBUG_FRAME_DUMP
nsresult
nsRubyTextContainerFrame::GetFrameName(nsAString& aResult) const
{
  return MakeFrameName(NS_LITERAL_STRING("RubyTextContainer"), aResult);
}
#endif

/* virtual */ bool
nsRubyTextContainerFrame::IsFrameOfType(uint32_t aFlags) const
{
  if (aFlags & eSupportsCSSTransforms) {
    return false;
  }
  return nsRubyTextContainerFrameSuper::IsFrameOfType(aFlags);
}

/* virtual */ void
nsRubyTextContainerFrame::SetInitialChildList(ChildListID aListID,
                                              nsFrameList& aChildList)
{
  nsRubyTextContainerFrameSuper::SetInitialChildList(aListID, aChildList);
  UpdateSpanFlag();
}

/* virtual */ void
nsRubyTextContainerFrame::AppendFrames(ChildListID aListID,
                                       nsFrameList& aFrameList)
{
  nsRubyTextContainerFrameSuper::AppendFrames(aListID, aFrameList);
  UpdateSpanFlag();
}

/* virtual */ void
nsRubyTextContainerFrame::InsertFrames(ChildListID aListID,
                                       nsIFrame* aPrevFrame,
                                       nsFrameList& aFrameList)
{
  nsRubyTextContainerFrameSuper::InsertFrames(aListID, aPrevFrame, aFrameList);
  UpdateSpanFlag();
}

/* virtual */ void
nsRubyTextContainerFrame::RemoveFrame(ChildListID aListID,
                                      nsIFrame* aOldFrame)
{
  nsRubyTextContainerFrameSuper::RemoveFrame(aListID, aOldFrame);
  UpdateSpanFlag();
}

void
nsRubyTextContainerFrame::UpdateSpanFlag()
{
  bool isSpan = false;
  // The continuation checks are safe here because spans never break.
  if (!GetPrevContinuation() && !GetNextContinuation()) {
    nsIFrame* onlyChild = mFrames.OnlyChild();
    if (onlyChild && onlyChild->IsPseudoFrame(GetContent())) {
      // Per CSS Ruby spec, if the only child of an rtc frame is
      // a pseudo rt frame, it spans all bases in the segment.
      isSpan = true;
    }
  }

  if (isSpan) {
    AddStateBits(NS_RUBY_TEXT_CONTAINER_IS_SPAN);
  } else {
    RemoveStateBits(NS_RUBY_TEXT_CONTAINER_IS_SPAN);
  }
}

/* virtual */ void
nsRubyTextContainerFrame::Reflow(nsPresContext* aPresContext,
                                 nsHTMLReflowMetrics& aDesiredSize,
                                 const nsHTMLReflowState& aReflowState,
                                 nsReflowStatus& aStatus)
{
  DO_GLOBAL_REFLOW_COUNT("nsRubyTextContainerFrame");
  DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);

  // All rt children have already been reflowed. All we need to do is
  // to report complete and return the desired size provided by the
  // ruby base container.

  // Although a ruby text container may have continuations, returning
  // NS_FRAME_COMPLETE here is still safe, since its parent, ruby frame,
  // ignores the status, and continuations of the ruby base container
  // will take care of our continuations.
  aStatus = NS_FRAME_COMPLETE;
  WritingMode lineWM = aReflowState.mLineLayout->GetWritingMode();
  aDesiredSize.SetSize(lineWM, mLineSize);
}