mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1141931 part 6 - Move Ruby{Segment,Column}Enumerator to RubyUtils. r=dholbert
This commit is contained in:
parent
fc20e60823
commit
67079982ec
@ -5,6 +5,9 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "RubyUtils.h"
|
||||
#include "nsRubyFrame.h"
|
||||
#include "nsRubyBaseFrame.h"
|
||||
#include "nsRubyTextFrame.h"
|
||||
#include "nsRubyBaseContainerFrame.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -59,3 +62,129 @@ RubyTextContainerIterator::Next()
|
||||
mFrame = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RubySegmentEnumerator::RubySegmentEnumerator(nsRubyFrame* aRubyFrame)
|
||||
{
|
||||
nsIFrame* frame = aRubyFrame->GetFirstPrincipalChild();
|
||||
MOZ_ASSERT(!frame ||
|
||||
frame->GetType() == nsGkAtoms::rubyBaseContainerFrame);
|
||||
mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
|
||||
}
|
||||
|
||||
void
|
||||
RubySegmentEnumerator::Next()
|
||||
{
|
||||
MOZ_ASSERT(mBaseContainer);
|
||||
nsIFrame* frame = mBaseContainer->GetNextSibling();
|
||||
while (frame && frame->GetType() != nsGkAtoms::rubyBaseContainerFrame) {
|
||||
frame = frame->GetNextSibling();
|
||||
}
|
||||
mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
|
||||
}
|
||||
|
||||
RubyColumnEnumerator::RubyColumnEnumerator(
|
||||
nsRubyBaseContainerFrame* aBaseContainer,
|
||||
const nsTArray<nsRubyTextContainerFrame*>& aTextContainers)
|
||||
: mAtIntraLevelWhitespace(false)
|
||||
{
|
||||
const uint32_t rtcCount = aTextContainers.Length();
|
||||
mFrames.SetCapacity(rtcCount + 1);
|
||||
|
||||
nsIFrame* rbFrame = aBaseContainer->GetFirstPrincipalChild();
|
||||
MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
|
||||
mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rbFrame));
|
||||
for (uint32_t i = 0; i < rtcCount; i++) {
|
||||
nsRubyTextContainerFrame* container = aTextContainers[i];
|
||||
// If the container is for span, leave a nullptr here.
|
||||
// Spans do not take part in pairing.
|
||||
nsIFrame* rtFrame = !container->IsSpanContainer() ?
|
||||
container->GetFirstPrincipalChild() : nullptr;
|
||||
MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
|
||||
mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rtFrame));
|
||||
}
|
||||
|
||||
// We have to init mAtIntraLevelWhitespace to be correct for the
|
||||
// first column. There are two ways we could end up with intra-level
|
||||
// whitespace in our first colum:
|
||||
// 1. The current segment itself is an inter-segment whitespace;
|
||||
// 2. If our ruby segment is split across multiple lines, and some
|
||||
// intra-level whitespace happens to fall right after a line-break.
|
||||
// Each line will get its own nsRubyBaseContainerFrame, and the
|
||||
// container right after the line-break will end up with its first
|
||||
// column containing that intra-level whitespace.
|
||||
for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
|
||||
nsRubyContentFrame* frame = mFrames[i];
|
||||
if (frame && frame->IsIntraLevelWhitespace()) {
|
||||
mAtIntraLevelWhitespace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RubyColumnEnumerator::Next()
|
||||
{
|
||||
bool advancingToIntraLevelWhitespace = false;
|
||||
for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
|
||||
nsRubyContentFrame* frame = mFrames[i];
|
||||
// If we've got intra-level whitespace frames at some levels in the
|
||||
// current ruby column, we "faked" an anonymous box for all other
|
||||
// levels for this column. So when we advance off this column, we
|
||||
// don't advance any of the frames in those levels, because we're
|
||||
// just advancing across the "fake" frames.
|
||||
if (frame && (!mAtIntraLevelWhitespace ||
|
||||
frame->IsIntraLevelWhitespace())) {
|
||||
nsIFrame* nextSibling = frame->GetNextSibling();
|
||||
MOZ_ASSERT(!nextSibling || nextSibling->GetType() == frame->GetType(),
|
||||
"Frame type should be identical among a level");
|
||||
mFrames[i] = frame = static_cast<nsRubyContentFrame*>(nextSibling);
|
||||
if (!advancingToIntraLevelWhitespace &&
|
||||
frame && frame->IsIntraLevelWhitespace()) {
|
||||
advancingToIntraLevelWhitespace = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(!advancingToIntraLevelWhitespace || !mAtIntraLevelWhitespace,
|
||||
"Should never have adjacent intra-level whitespace columns");
|
||||
mAtIntraLevelWhitespace = advancingToIntraLevelWhitespace;
|
||||
}
|
||||
|
||||
bool
|
||||
RubyColumnEnumerator::AtEnd() const
|
||||
{
|
||||
for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
|
||||
if (mFrames[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsRubyContentFrame*
|
||||
RubyColumnEnumerator::GetFrameAtLevel(uint32_t aIndex) const
|
||||
{
|
||||
// If the current ruby column is for intra-level whitespaces, we
|
||||
// return nullptr for any levels that do not have an actual intra-
|
||||
// level whitespace frame in this column. This nullptr represents
|
||||
// an anonymous empty intra-level whitespace box. (In this case,
|
||||
// it's important that we NOT return mFrames[aIndex], because it's
|
||||
// really part of the next column, not the current one.)
|
||||
nsRubyContentFrame* frame = mFrames[aIndex];
|
||||
return !mAtIntraLevelWhitespace ||
|
||||
(frame && frame->IsIntraLevelWhitespace()) ? frame : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
RubyColumnEnumerator::GetColumn(RubyColumn& aColumn) const
|
||||
{
|
||||
nsRubyContentFrame* rbFrame = GetFrameAtLevel(0);
|
||||
MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
|
||||
aColumn.mBaseFrame = static_cast<nsRubyBaseFrame*>(rbFrame);
|
||||
aColumn.mTextFrames.ClearAndRetainStorage();
|
||||
for (uint32_t i = 1, iend = mFrames.Length(); i < iend; i++) {
|
||||
nsRubyContentFrame* rtFrame = GetFrameAtLevel(i);
|
||||
MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
|
||||
aColumn.mTextFrames.AppendElement(static_cast<nsRubyTextFrame*>(rtFrame));
|
||||
}
|
||||
aColumn.mIsIntraLevelWhitespace = mAtIntraLevelWhitespace;
|
||||
}
|
||||
|
@ -7,9 +7,16 @@
|
||||
#ifndef mozilla_RubyUtils_h_
|
||||
#define mozilla_RubyUtils_h_
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsRubyTextContainerFrame.h"
|
||||
|
||||
#define RTC_ARRAY_SIZE 1
|
||||
|
||||
class nsRubyFrame;
|
||||
class nsRubyBaseFrame;
|
||||
class nsRubyTextFrame;
|
||||
class nsRubyContentFrame;
|
||||
class nsRubyBaseContainerFrame;
|
||||
|
||||
namespace mozilla {
|
||||
@ -80,6 +87,64 @@ private:
|
||||
nsIFrame* mFrame;
|
||||
};
|
||||
|
||||
/**
|
||||
* This enumerator enumerates each ruby segment.
|
||||
*/
|
||||
class MOZ_STACK_CLASS RubySegmentEnumerator
|
||||
{
|
||||
public:
|
||||
explicit RubySegmentEnumerator(nsRubyFrame* aRubyFrame);
|
||||
|
||||
void Next();
|
||||
bool AtEnd() const { return !mBaseContainer; }
|
||||
|
||||
nsRubyBaseContainerFrame* GetBaseContainer() const
|
||||
{
|
||||
return mBaseContainer;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRubyBaseContainerFrame* mBaseContainer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Ruby column is a unit consists of one ruby base and all ruby
|
||||
* annotations paired with it.
|
||||
* See http://dev.w3.org/csswg/css-ruby/#ruby-pairing
|
||||
*/
|
||||
struct MOZ_STACK_CLASS RubyColumn
|
||||
{
|
||||
nsRubyBaseFrame* mBaseFrame;
|
||||
nsAutoTArray<nsRubyTextFrame*, RTC_ARRAY_SIZE> mTextFrames;
|
||||
bool mIsIntraLevelWhitespace;
|
||||
RubyColumn() : mBaseFrame(nullptr), mIsIntraLevelWhitespace(false) { }
|
||||
};
|
||||
|
||||
/**
|
||||
* This enumerator enumerates ruby columns in a segment.
|
||||
*/
|
||||
class MOZ_STACK_CLASS RubyColumnEnumerator
|
||||
{
|
||||
public:
|
||||
RubyColumnEnumerator(nsRubyBaseContainerFrame* aRBCFrame,
|
||||
const nsTArray<nsRubyTextContainerFrame*>& aRTCFrames);
|
||||
|
||||
void Next();
|
||||
bool AtEnd() const;
|
||||
|
||||
uint32_t GetLevelCount() const { return mFrames.Length(); }
|
||||
nsRubyContentFrame* GetFrameAtLevel(uint32_t aIndex) const;
|
||||
void GetColumn(RubyColumn& aColumn) const;
|
||||
|
||||
private:
|
||||
// Frames in this array are NOT necessary part of the current column.
|
||||
// When in doubt, use GetFrameAtLevel to access it.
|
||||
// See GetFrameAtLevel() and Next() for more info.
|
||||
nsAutoTArray<nsRubyContentFrame*, RTC_ARRAY_SIZE + 1> mFrames;
|
||||
// Whether we are on a column for intra-level whitespaces
|
||||
bool mAtIntraLevelWhitespace;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif /* !defined(mozilla_RubyUtils_h_) */
|
||||
|
@ -61,148 +61,6 @@ nsRubyBaseContainerFrame::GetFrameName(nsAString& aResult) const
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Ruby column is a unit consists of one ruby base and all ruby
|
||||
* annotations paired with it.
|
||||
* See http://dev.w3.org/csswg/css-ruby/#ruby-pairing
|
||||
*/
|
||||
struct MOZ_STACK_CLASS mozilla::RubyColumn
|
||||
{
|
||||
nsRubyBaseFrame* mBaseFrame;
|
||||
nsAutoTArray<nsRubyTextFrame*, RTC_ARRAY_SIZE> mTextFrames;
|
||||
bool mIsIntraLevelWhitespace;
|
||||
RubyColumn() : mBaseFrame(nullptr), mIsIntraLevelWhitespace(false) { }
|
||||
};
|
||||
|
||||
class MOZ_STACK_CLASS RubyColumnEnumerator
|
||||
{
|
||||
public:
|
||||
RubyColumnEnumerator(nsRubyBaseContainerFrame* aRBCFrame,
|
||||
const nsTArray<nsRubyTextContainerFrame*>& aRTCFrames);
|
||||
|
||||
void Next();
|
||||
bool AtEnd() const;
|
||||
|
||||
uint32_t GetLevelCount() const { return mFrames.Length(); }
|
||||
nsRubyContentFrame* GetFrameAtLevel(uint32_t aIndex) const;
|
||||
void GetColumn(RubyColumn& aColumn) const;
|
||||
|
||||
private:
|
||||
// Frames in this array are NOT necessary part of the current column.
|
||||
// When in doubt, use GetFrameAtLevel to access it.
|
||||
// See GetFrameAtLevel() and Next() for more info.
|
||||
nsAutoTArray<nsRubyContentFrame*, RTC_ARRAY_SIZE + 1> mFrames;
|
||||
// Whether we are on a column for intra-level whitespaces
|
||||
bool mAtIntraLevelWhitespace;
|
||||
};
|
||||
|
||||
RubyColumnEnumerator::RubyColumnEnumerator(
|
||||
nsRubyBaseContainerFrame* aBaseContainer,
|
||||
const nsTArray<nsRubyTextContainerFrame*>& aTextContainers)
|
||||
: mAtIntraLevelWhitespace(false)
|
||||
{
|
||||
const uint32_t rtcCount = aTextContainers.Length();
|
||||
mFrames.SetCapacity(rtcCount + 1);
|
||||
|
||||
nsIFrame* rbFrame = aBaseContainer->GetFirstPrincipalChild();
|
||||
MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
|
||||
mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rbFrame));
|
||||
for (uint32_t i = 0; i < rtcCount; i++) {
|
||||
nsRubyTextContainerFrame* container = aTextContainers[i];
|
||||
// If the container is for span, leave a nullptr here.
|
||||
// Spans do not take part in pairing.
|
||||
nsIFrame* rtFrame = !container->IsSpanContainer() ?
|
||||
container->GetFirstPrincipalChild() : nullptr;
|
||||
MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
|
||||
mFrames.AppendElement(static_cast<nsRubyContentFrame*>(rtFrame));
|
||||
}
|
||||
|
||||
// We have to init mAtIntraLevelWhitespace to be correct for the
|
||||
// first column. There are two ways we could end up with intra-level
|
||||
// whitespace in our first colum:
|
||||
// 1. The current segment itself is an inter-segment whitespace;
|
||||
// 2. If our ruby segment is split across multiple lines, and some
|
||||
// intra-level whitespace happens to fall right after a line-break.
|
||||
// Each line will get its own nsRubyBaseContainerFrame, and the
|
||||
// container right after the line-break will end up with its first
|
||||
// column containing that intra-level whitespace.
|
||||
for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
|
||||
nsRubyContentFrame* frame = mFrames[i];
|
||||
if (frame && frame->IsIntraLevelWhitespace()) {
|
||||
mAtIntraLevelWhitespace = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RubyColumnEnumerator::Next()
|
||||
{
|
||||
bool advancingToIntraLevelWhitespace = false;
|
||||
for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
|
||||
nsRubyContentFrame* frame = mFrames[i];
|
||||
// If we've got intra-level whitespace frames at some levels in the
|
||||
// current ruby column, we "faked" an anonymous box for all other
|
||||
// levels for this column. So when we advance off this column, we
|
||||
// don't advance any of the frames in those levels, because we're
|
||||
// just advancing across the "fake" frames.
|
||||
if (frame && (!mAtIntraLevelWhitespace ||
|
||||
frame->IsIntraLevelWhitespace())) {
|
||||
nsIFrame* nextSibling = frame->GetNextSibling();
|
||||
MOZ_ASSERT(!nextSibling || nextSibling->GetType() == frame->GetType(),
|
||||
"Frame type should be identical among a level");
|
||||
mFrames[i] = frame = static_cast<nsRubyContentFrame*>(nextSibling);
|
||||
if (!advancingToIntraLevelWhitespace &&
|
||||
frame && frame->IsIntraLevelWhitespace()) {
|
||||
advancingToIntraLevelWhitespace = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
MOZ_ASSERT(!advancingToIntraLevelWhitespace || !mAtIntraLevelWhitespace,
|
||||
"Should never have adjacent intra-level whitespace columns");
|
||||
mAtIntraLevelWhitespace = advancingToIntraLevelWhitespace;
|
||||
}
|
||||
|
||||
bool
|
||||
RubyColumnEnumerator::AtEnd() const
|
||||
{
|
||||
for (uint32_t i = 0, iend = mFrames.Length(); i < iend; i++) {
|
||||
if (mFrames[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
nsRubyContentFrame*
|
||||
RubyColumnEnumerator::GetFrameAtLevel(uint32_t aIndex) const
|
||||
{
|
||||
// If the current ruby column is for intra-level whitespaces, we
|
||||
// return nullptr for any levels that do not have an actual intra-
|
||||
// level whitespace frame in this column. This nullptr represents
|
||||
// an anonymous empty intra-level whitespace box. (In this case,
|
||||
// it's important that we NOT return mFrames[aIndex], because it's
|
||||
// really part of the next column, not the current one.)
|
||||
nsRubyContentFrame* frame = mFrames[aIndex];
|
||||
return !mAtIntraLevelWhitespace ||
|
||||
(frame && frame->IsIntraLevelWhitespace()) ? frame : nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
RubyColumnEnumerator::GetColumn(RubyColumn& aColumn) const
|
||||
{
|
||||
nsRubyContentFrame* rbFrame = GetFrameAtLevel(0);
|
||||
MOZ_ASSERT(!rbFrame || rbFrame->GetType() == nsGkAtoms::rubyBaseFrame);
|
||||
aColumn.mBaseFrame = static_cast<nsRubyBaseFrame*>(rbFrame);
|
||||
aColumn.mTextFrames.ClearAndRetainStorage();
|
||||
for (uint32_t i = 1, iend = mFrames.Length(); i < iend; i++) {
|
||||
nsRubyContentFrame* rtFrame = GetFrameAtLevel(i);
|
||||
MOZ_ASSERT(!rtFrame || rtFrame->GetType() == nsGkAtoms::rubyTextFrame);
|
||||
aColumn.mTextFrames.AppendElement(static_cast<nsRubyTextFrame*>(rtFrame));
|
||||
}
|
||||
aColumn.mIsIntraLevelWhitespace = mAtIntraLevelWhitespace;
|
||||
}
|
||||
|
||||
static gfxBreakPriority
|
||||
LineBreakBefore(nsIFrame* aFrame,
|
||||
nsRenderingContext* aRenderingContext,
|
||||
|
@ -9,10 +9,9 @@
|
||||
#ifndef nsRubyBaseContainerFrame_h___
|
||||
#define nsRubyBaseContainerFrame_h___
|
||||
|
||||
#include "RubyUtils.h"
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
#define RTC_ARRAY_SIZE 1
|
||||
|
||||
/**
|
||||
* Factory function.
|
||||
* @return a newly allocated nsRubyBaseContainerFrame (infallible)
|
||||
@ -20,12 +19,6 @@
|
||||
nsContainerFrame* NS_NewRubyBaseContainerFrame(nsIPresShell* aPresShell,
|
||||
nsStyleContext* aContext);
|
||||
|
||||
namespace mozilla {
|
||||
struct RubyColumn;
|
||||
}
|
||||
|
||||
class nsRubyTextContainerFrame;
|
||||
|
||||
class nsRubyBaseContainerFrame final : public nsContainerFrame
|
||||
{
|
||||
public:
|
||||
|
@ -65,51 +65,12 @@ nsRubyFrame::GetFrameName(nsAString& aResult) const
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This enumerator enumerates each segment.
|
||||
*/
|
||||
class MOZ_STACK_CLASS SegmentEnumerator
|
||||
{
|
||||
public:
|
||||
explicit SegmentEnumerator(nsRubyFrame* aRubyFrame);
|
||||
|
||||
void Next();
|
||||
bool AtEnd() const { return !mBaseContainer; }
|
||||
|
||||
nsRubyBaseContainerFrame* GetBaseContainer() const
|
||||
{
|
||||
return mBaseContainer;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRubyBaseContainerFrame* mBaseContainer;
|
||||
};
|
||||
|
||||
SegmentEnumerator::SegmentEnumerator(nsRubyFrame* aRubyFrame)
|
||||
{
|
||||
nsIFrame* frame = aRubyFrame->GetFirstPrincipalChild();
|
||||
MOZ_ASSERT(!frame ||
|
||||
frame->GetType() == nsGkAtoms::rubyBaseContainerFrame);
|
||||
mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
|
||||
}
|
||||
|
||||
void
|
||||
SegmentEnumerator::Next()
|
||||
{
|
||||
MOZ_ASSERT(mBaseContainer);
|
||||
nsIFrame* frame = mBaseContainer->GetNextSibling();
|
||||
while (frame && frame->GetType() != nsGkAtoms::rubyBaseContainerFrame) {
|
||||
frame = frame->GetNextSibling();
|
||||
}
|
||||
mBaseContainer = static_cast<nsRubyBaseContainerFrame*>(frame);
|
||||
}
|
||||
|
||||
/* virtual */ void
|
||||
nsRubyFrame::AddInlineMinISize(nsRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlineMinISizeData *aData)
|
||||
{
|
||||
for (nsIFrame* frame = this; frame; frame = frame->GetNextInFlow()) {
|
||||
for (SegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
|
||||
for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
|
||||
!e.AtEnd(); e.Next()) {
|
||||
e.GetBaseContainer()->AddInlineMinISize(aRenderingContext, aData);
|
||||
}
|
||||
@ -121,7 +82,7 @@ nsRubyFrame::AddInlinePrefISize(nsRenderingContext *aRenderingContext,
|
||||
nsIFrame::InlinePrefISizeData *aData)
|
||||
{
|
||||
for (nsIFrame* frame = this; frame; frame = frame->GetNextInFlow()) {
|
||||
for (SegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
|
||||
for (RubySegmentEnumerator e(static_cast<nsRubyFrame*>(frame));
|
||||
!e.AtEnd(); e.Next()) {
|
||||
e.GetBaseContainer()->AddInlinePrefISize(aRenderingContext, aData);
|
||||
}
|
||||
@ -169,7 +130,7 @@ nsRubyFrame::Reflow(nsPresContext* aPresContext,
|
||||
startEdge, availableISize, &mBaseline);
|
||||
|
||||
aStatus = NS_FRAME_COMPLETE;
|
||||
for (SegmentEnumerator e(this); !e.AtEnd(); e.Next()) {
|
||||
for (RubySegmentEnumerator e(this); !e.AtEnd(); e.Next()) {
|
||||
ReflowSegment(aPresContext, aReflowState, e.GetBaseContainer(), aStatus);
|
||||
|
||||
if (NS_INLINE_IS_BREAK(aStatus)) {
|
||||
|
Loading…
Reference in New Issue
Block a user