summaryrefslogtreecommitdiffstats
path: root/layout/generic/RubyUtils.cpp
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /layout/generic/RubyUtils.cpp
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'layout/generic/RubyUtils.cpp')
-rw-r--r--layout/generic/RubyUtils.cpp203
1 files changed, 203 insertions, 0 deletions
diff --git a/layout/generic/RubyUtils.cpp b/layout/generic/RubyUtils.cpp
new file mode 100644
index 000000000..f340663bc
--- /dev/null
+++ b/layout/generic/RubyUtils.cpp
@@ -0,0 +1,203 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "RubyUtils.h"
+#include "nsRubyFrame.h"
+#include "nsRubyBaseFrame.h"
+#include "nsRubyTextFrame.h"
+#include "nsRubyBaseContainerFrame.h"
+#include "nsRubyTextContainerFrame.h"
+
+using namespace mozilla;
+
+NS_DECLARE_FRAME_PROPERTY_SMALL_VALUE(ReservedISize, nscoord)
+
+/* static */ void
+RubyUtils::SetReservedISize(nsIFrame* aFrame, nscoord aISize)
+{
+ MOZ_ASSERT(IsExpandableRubyBox(aFrame));
+ aFrame->Properties().Set(ReservedISize(), aISize);
+}
+
+/* static */ void
+RubyUtils::ClearReservedISize(nsIFrame* aFrame)
+{
+ MOZ_ASSERT(IsExpandableRubyBox(aFrame));
+ aFrame->Properties().Remove(ReservedISize());
+}
+
+/* static */ nscoord
+RubyUtils::GetReservedISize(nsIFrame* aFrame)
+{
+ MOZ_ASSERT(IsExpandableRubyBox(aFrame));
+ return aFrame->Properties().Get(ReservedISize());
+}
+
+AutoRubyTextContainerArray::AutoRubyTextContainerArray(
+ nsRubyBaseContainerFrame* aBaseContainer)
+{
+ for (nsIFrame* frame = aBaseContainer->GetNextSibling();
+ frame && frame->GetType() == nsGkAtoms::rubyTextContainerFrame;
+ frame = frame->GetNextSibling()) {
+ AppendElement(static_cast<nsRubyTextContainerFrame*>(frame));
+ }
+}
+
+nsIFrame*
+RubyColumn::Iterator::operator*() const
+{
+ nsIFrame* frame;
+ if (mIndex == -1) {
+ frame = mColumn.mBaseFrame;
+ } else {
+ frame = mColumn.mTextFrames[mIndex];
+ }
+ MOZ_ASSERT(frame, "Frame here cannot be null");
+ return frame;
+}
+
+void
+RubyColumn::Iterator::SkipUntilExistingFrame()
+{
+ if (mIndex == -1) {
+ if (mColumn.mBaseFrame) {
+ return;
+ }
+ ++mIndex;
+ }
+ int32_t numTextFrames = mColumn.mTextFrames.Length();
+ for (; mIndex < numTextFrames; ++mIndex) {
+ if (mColumn.mTextFrames[mIndex]) {
+ break;
+ }
+ }
+}
+
+RubySegmentEnumerator::RubySegmentEnumerator(nsRubyFrame* aRubyFrame)
+{
+ nsIFrame* frame = aRubyFrame->PrincipalChildList().FirstChild();
+ 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 AutoRubyTextContainerArray& aTextContainers)
+ : mAtIntraLevelWhitespace(false)
+{
+ const uint32_t rtcCount = aTextContainers.Length();
+ mFrames.SetCapacity(rtcCount + 1);
+
+ nsIFrame* rbFrame = aBaseContainer->PrincipalChildList().FirstChild();
+ 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->PrincipalChildList().FirstChild() : 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;
+}