Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/layout/generic/nsRubyTextContainerFrame.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/* rendering object for CSS "display: ruby-text-container" */
8
9
#include "nsRubyTextContainerFrame.h"
10
11
#include "mozilla/ComputedStyle.h"
12
#include "mozilla/UniquePtr.h"
13
#include "mozilla/WritingModes.h"
14
#include "nsLineLayout.h"
15
#include "nsPresContext.h"
16
17
using namespace mozilla;
18
19
//----------------------------------------------------------------------
20
21
// Frame class boilerplate
22
// =======================
23
24
0
NS_QUERYFRAME_HEAD(nsRubyTextContainerFrame)
25
0
  NS_QUERYFRAME_ENTRY(nsRubyTextContainerFrame)
26
0
NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
27
28
NS_IMPL_FRAMEARENA_HELPERS(nsRubyTextContainerFrame)
29
30
nsContainerFrame*
31
NS_NewRubyTextContainerFrame(nsIPresShell* aPresShell,
32
                             ComputedStyle* aStyle)
33
0
{
34
0
  return new (aPresShell) nsRubyTextContainerFrame(aStyle);
35
0
}
36
37
38
//----------------------------------------------------------------------
39
40
// nsRubyTextContainerFrame Method Implementations
41
// ===============================================
42
43
#ifdef DEBUG_FRAME_DUMP
44
nsresult
45
nsRubyTextContainerFrame::GetFrameName(nsAString& aResult) const
46
{
47
  return MakeFrameName(NS_LITERAL_STRING("RubyTextContainer"), aResult);
48
}
49
#endif
50
51
/* virtual */ bool
52
nsRubyTextContainerFrame::IsFrameOfType(uint32_t aFlags) const
53
0
{
54
0
  if (aFlags & (eSupportsCSSTransforms | eSupportsContainLayoutAndPaint)) {
55
0
    return false;
56
0
  }
57
0
  return nsContainerFrame::IsFrameOfType(aFlags);
58
0
}
59
60
/* virtual */ void
61
nsRubyTextContainerFrame::SetInitialChildList(ChildListID aListID,
62
                                              nsFrameList& aChildList)
63
0
{
64
0
  nsContainerFrame::SetInitialChildList(aListID, aChildList);
65
0
  if (aListID == kPrincipalList) {
66
0
    UpdateSpanFlag();
67
0
  }
68
0
}
69
70
/* virtual */ void
71
nsRubyTextContainerFrame::AppendFrames(ChildListID aListID,
72
                                       nsFrameList& aFrameList)
73
0
{
74
0
  nsContainerFrame::AppendFrames(aListID, aFrameList);
75
0
  UpdateSpanFlag();
76
0
}
77
78
/* virtual */ void
79
nsRubyTextContainerFrame::InsertFrames(ChildListID aListID,
80
                                       nsIFrame* aPrevFrame,
81
                                       nsFrameList& aFrameList)
82
0
{
83
0
  nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
84
0
  UpdateSpanFlag();
85
0
}
86
87
/* virtual */ void
88
nsRubyTextContainerFrame::RemoveFrame(ChildListID aListID,
89
                                      nsIFrame* aOldFrame)
90
0
{
91
0
  nsContainerFrame::RemoveFrame(aListID, aOldFrame);
92
0
  UpdateSpanFlag();
93
0
}
94
95
void
96
nsRubyTextContainerFrame::UpdateSpanFlag()
97
0
{
98
0
  bool isSpan = false;
99
0
  // The continuation checks are safe here because spans never break.
100
0
  if (!GetPrevContinuation() && !GetNextContinuation()) {
101
0
    nsIFrame* onlyChild = mFrames.OnlyChild();
102
0
    if (onlyChild && onlyChild->IsPseudoFrame(GetContent())) {
103
0
      // Per CSS Ruby spec, if the only child of an rtc frame is
104
0
      // a pseudo rt frame, it spans all bases in the segment.
105
0
      isSpan = true;
106
0
    }
107
0
  }
108
0
109
0
  if (isSpan) {
110
0
    AddStateBits(NS_RUBY_TEXT_CONTAINER_IS_SPAN);
111
0
  } else {
112
0
    RemoveStateBits(NS_RUBY_TEXT_CONTAINER_IS_SPAN);
113
0
  }
114
0
}
115
116
/* virtual */ void
117
nsRubyTextContainerFrame::Reflow(nsPresContext* aPresContext,
118
                                 ReflowOutput& aDesiredSize,
119
                                 const ReflowInput& aReflowInput,
120
                                 nsReflowStatus& aStatus)
121
0
{
122
0
  MarkInReflow();
123
0
  DO_GLOBAL_REFLOW_COUNT("nsRubyTextContainerFrame");
124
0
  DISPLAY_REFLOW(aPresContext, this, aReflowInput, aDesiredSize, aStatus);
125
0
  MOZ_ASSERT(aStatus.IsEmpty(), "Caller should pass a fresh reflow status!");
126
0
127
0
  // Although a ruby text container may have continuations, returning
128
0
  // complete reflow status is still safe, since its parent, ruby frame,
129
0
  // ignores the status, and continuations of the ruby base container
130
0
  // will take care of our continuations.
131
0
  WritingMode rtcWM = GetWritingMode();
132
0
133
0
  nscoord minBCoord = nscoord_MAX;
134
0
  nscoord maxBCoord = nscoord_MIN;
135
0
  // The container size is not yet known, so we use a dummy (0, 0) size.
136
0
  // The block-dir position will be corrected below after containerSize
137
0
  // is finalized.
138
0
  const nsSize dummyContainerSize;
139
0
  for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
140
0
    nsIFrame* child = e.get();
141
0
    MOZ_ASSERT(child->IsRubyTextFrame());
142
0
    LogicalRect rect = child->GetLogicalRect(rtcWM, dummyContainerSize);
143
0
    LogicalMargin margin = child->GetLogicalUsedMargin(rtcWM);
144
0
    nscoord blockStart = rect.BStart(rtcWM) - margin.BStart(rtcWM);
145
0
    minBCoord = std::min(minBCoord, blockStart);
146
0
    nscoord blockEnd = rect.BEnd(rtcWM) + margin.BEnd(rtcWM);
147
0
    maxBCoord = std::max(maxBCoord, blockEnd);
148
0
  }
149
0
150
0
  LogicalSize size(rtcWM, mISize, 0);
151
0
  if (!mFrames.IsEmpty()) {
152
0
    if (MOZ_UNLIKELY(minBCoord > maxBCoord)) {
153
0
      // XXX When bug 765861 gets fixed, this warning should be upgraded.
154
0
      NS_WARNING("bad block coord");
155
0
      minBCoord = maxBCoord = 0;
156
0
    }
157
0
    size.BSize(rtcWM) = maxBCoord - minBCoord;
158
0
    nsSize containerSize = size.GetPhysicalSize(rtcWM);
159
0
    for (nsFrameList::Enumerator e(mFrames); !e.AtEnd(); e.Next()) {
160
0
      nsIFrame* child = e.get();
161
0
      // We reflowed the child with a dummy container size, as the true size
162
0
      // was not yet known at that time.
163
0
      LogicalPoint pos = child->GetLogicalPosition(rtcWM, dummyContainerSize);
164
0
      // Adjust block position to account for minBCoord,
165
0
      // then reposition child based on the true container width.
166
0
      pos.B(rtcWM) -= minBCoord;
167
0
      // Relative positioning hasn't happened yet.
168
0
      // So MovePositionBy should not be used here.
169
0
      child->SetPosition(rtcWM, pos, containerSize);
170
0
      nsContainerFrame::PlaceFrameView(child);
171
0
    }
172
0
  }
173
0
174
0
  aDesiredSize.SetSize(rtcWM, size);
175
0
}