Move parseFontFaceDescriptor to CSSPropertyParser.cpp
[chromium-blink-merge.git] / third_party / WebKit / Source / core / editing / RenderedPosition.cpp
blob6a78ad57044785232f22d51f4f20427644f3b557
1 /*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "config.h"
32 #include "core/editing/RenderedPosition.h"
34 #include "core/editing/TextAffinity.h"
35 #include "core/editing/VisiblePosition.h"
36 #include "core/editing/VisibleUnits.h"
37 #include "core/layout/compositing/CompositedSelectionBound.h"
38 #include "core/paint/DeprecatedPaintLayer.h"
40 namespace blink {
42 static inline LayoutObject* layoutObjectFromPosition(const Position& position)
44 ASSERT(position.isNotNull());
45 Node* layoutObjectNode = nullptr;
46 switch (position.anchorType()) {
47 case PositionAnchorType::OffsetInAnchor:
48 layoutObjectNode = position.computeNodeAfterPosition();
49 if (!layoutObjectNode || !layoutObjectNode->layoutObject())
50 layoutObjectNode = position.anchorNode()->lastChild();
51 break;
53 case PositionAnchorType::BeforeAnchor:
54 case PositionAnchorType::AfterAnchor:
55 break;
57 case PositionAnchorType::BeforeChildren:
58 layoutObjectNode = position.anchorNode()->firstChild();
59 break;
60 case PositionAnchorType::AfterChildren:
61 layoutObjectNode = position.anchorNode()->lastChild();
62 break;
64 if (!layoutObjectNode || !layoutObjectNode->layoutObject())
65 layoutObjectNode = position.anchorNode();
66 return layoutObjectNode->layoutObject();
69 RenderedPosition::RenderedPosition(const VisiblePosition& position)
70 : RenderedPosition(position.deepEquivalent(), position.affinity())
74 RenderedPosition::RenderedPosition(const VisiblePositionInComposedTree& position)
75 : RenderedPosition(position.deepEquivalent(), position.affinity())
79 RenderedPosition::RenderedPosition(const Position& position, TextAffinity affinity)
80 : m_layoutObject(nullptr)
81 , m_inlineBox(nullptr)
82 , m_offset(0)
83 , m_prevLeafChild(uncachedInlineBox())
84 , m_nextLeafChild(uncachedInlineBox())
86 if (position.isNull())
87 return;
88 InlineBoxPosition boxPosition = computeInlineBoxPosition(position, affinity);
89 m_inlineBox = boxPosition.inlineBox;
90 m_offset = boxPosition.offsetInBox;
91 if (m_inlineBox)
92 m_layoutObject = &m_inlineBox->layoutObject();
93 else
94 m_layoutObject = layoutObjectFromPosition(position);
97 RenderedPosition::RenderedPosition(const PositionInComposedTree& position, TextAffinity affinity)
98 : RenderedPosition(toPositionInDOMTree(position), affinity)
102 InlineBox* RenderedPosition::prevLeafChild() const
104 if (m_prevLeafChild == uncachedInlineBox())
105 m_prevLeafChild = m_inlineBox->prevLeafChildIgnoringLineBreak();
106 return m_prevLeafChild;
109 InlineBox* RenderedPosition::nextLeafChild() const
111 if (m_nextLeafChild == uncachedInlineBox())
112 m_nextLeafChild = m_inlineBox->nextLeafChildIgnoringLineBreak();
113 return m_nextLeafChild;
116 bool RenderedPosition::isEquivalent(const RenderedPosition& other) const
118 return (m_layoutObject == other.m_layoutObject && m_inlineBox == other.m_inlineBox && m_offset == other.m_offset)
119 || (atLeftmostOffsetInBox() && other.atRightmostOffsetInBox() && prevLeafChild() == other.m_inlineBox)
120 || (atRightmostOffsetInBox() && other.atLeftmostOffsetInBox() && nextLeafChild() == other.m_inlineBox);
123 unsigned char RenderedPosition::bidiLevelOnLeft() const
125 InlineBox* box = atLeftmostOffsetInBox() ? prevLeafChild() : m_inlineBox;
126 return box ? box->bidiLevel() : 0;
129 unsigned char RenderedPosition::bidiLevelOnRight() const
131 InlineBox* box = atRightmostOffsetInBox() ? nextLeafChild() : m_inlineBox;
132 return box ? box->bidiLevel() : 0;
135 RenderedPosition RenderedPosition::leftBoundaryOfBidiRun(unsigned char bidiLevelOfRun)
137 if (!m_inlineBox || bidiLevelOfRun > m_inlineBox->bidiLevel())
138 return RenderedPosition();
140 InlineBox* box = m_inlineBox;
141 do {
142 InlineBox* prev = box->prevLeafChildIgnoringLineBreak();
143 if (!prev || prev->bidiLevel() < bidiLevelOfRun)
144 return RenderedPosition(&box->layoutObject(), box, box->caretLeftmostOffset());
145 box = prev;
146 } while (box);
148 ASSERT_NOT_REACHED();
149 return RenderedPosition();
152 RenderedPosition RenderedPosition::rightBoundaryOfBidiRun(unsigned char bidiLevelOfRun)
154 if (!m_inlineBox || bidiLevelOfRun > m_inlineBox->bidiLevel())
155 return RenderedPosition();
157 InlineBox* box = m_inlineBox;
158 do {
159 InlineBox* next = box->nextLeafChildIgnoringLineBreak();
160 if (!next || next->bidiLevel() < bidiLevelOfRun)
161 return RenderedPosition(&box->layoutObject(), box, box->caretRightmostOffset());
162 box = next;
163 } while (box);
165 ASSERT_NOT_REACHED();
166 return RenderedPosition();
169 bool RenderedPosition::atLeftBoundaryOfBidiRun(ShouldMatchBidiLevel shouldMatchBidiLevel, unsigned char bidiLevelOfRun) const
171 if (!m_inlineBox)
172 return false;
174 if (atLeftmostOffsetInBox()) {
175 if (shouldMatchBidiLevel == IgnoreBidiLevel)
176 return !prevLeafChild() || prevLeafChild()->bidiLevel() < m_inlineBox->bidiLevel();
177 return m_inlineBox->bidiLevel() >= bidiLevelOfRun && (!prevLeafChild() || prevLeafChild()->bidiLevel() < bidiLevelOfRun);
180 if (atRightmostOffsetInBox()) {
181 if (shouldMatchBidiLevel == IgnoreBidiLevel)
182 return nextLeafChild() && m_inlineBox->bidiLevel() < nextLeafChild()->bidiLevel();
183 return nextLeafChild() && m_inlineBox->bidiLevel() < bidiLevelOfRun && nextLeafChild()->bidiLevel() >= bidiLevelOfRun;
186 return false;
189 bool RenderedPosition::atRightBoundaryOfBidiRun(ShouldMatchBidiLevel shouldMatchBidiLevel, unsigned char bidiLevelOfRun) const
191 if (!m_inlineBox)
192 return false;
194 if (atRightmostOffsetInBox()) {
195 if (shouldMatchBidiLevel == IgnoreBidiLevel)
196 return !nextLeafChild() || nextLeafChild()->bidiLevel() < m_inlineBox->bidiLevel();
197 return m_inlineBox->bidiLevel() >= bidiLevelOfRun && (!nextLeafChild() || nextLeafChild()->bidiLevel() < bidiLevelOfRun);
200 if (atLeftmostOffsetInBox()) {
201 if (shouldMatchBidiLevel == IgnoreBidiLevel)
202 return prevLeafChild() && m_inlineBox->bidiLevel() < prevLeafChild()->bidiLevel();
203 return prevLeafChild() && m_inlineBox->bidiLevel() < bidiLevelOfRun && prevLeafChild()->bidiLevel() >= bidiLevelOfRun;
206 return false;
209 Position RenderedPosition::positionAtLeftBoundaryOfBiDiRun() const
211 ASSERT(atLeftBoundaryOfBidiRun());
213 if (atLeftmostOffsetInBox())
214 return Position::editingPositionOf(m_layoutObject->node(), m_offset);
216 return Position::editingPositionOf(nextLeafChild()->layoutObject().node(), nextLeafChild()->caretLeftmostOffset());
219 Position RenderedPosition::positionAtRightBoundaryOfBiDiRun() const
221 ASSERT(atRightBoundaryOfBidiRun());
223 if (atRightmostOffsetInBox())
224 return Position::editingPositionOf(m_layoutObject->node(), m_offset);
226 return Position::editingPositionOf(prevLeafChild()->layoutObject().node(), prevLeafChild()->caretRightmostOffset());
229 IntRect RenderedPosition::absoluteRect(LayoutUnit* extraWidthToEndOfLine) const
231 if (isNull())
232 return IntRect();
234 IntRect localRect = pixelSnappedIntRect(m_layoutObject->localCaretRect(m_inlineBox, m_offset, extraWidthToEndOfLine));
235 return localRect == IntRect() ? IntRect() : m_layoutObject->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
238 void RenderedPosition::positionInGraphicsLayerBacking(CompositedSelectionBound& bound) const
240 bound.layer = nullptr;
241 bound.edgeTopInLayer = bound.edgeBottomInLayer = FloatPoint();
243 if (isNull())
244 return;
246 LayoutRect rect = m_layoutObject->localCaretRect(m_inlineBox, m_offset);
247 DeprecatedPaintLayer* layer = nullptr;
248 bound.edgeTopInLayer = m_layoutObject->localToInvalidationBackingPoint(rect.minXMinYCorner(), &layer);
249 bound.edgeBottomInLayer = m_layoutObject->localToInvalidationBackingPoint(rect.minXMaxYCorner(), nullptr);
250 bound.layer = layer ? layer->graphicsLayerBacking() : nullptr;
253 bool layoutObjectContainsPosition(LayoutObject* target, const Position& position)
255 for (LayoutObject* layoutObject = layoutObjectFromPosition(position); layoutObject && layoutObject->node(); layoutObject = layoutObject->parent()) {
256 if (layoutObject == target)
257 return true;
259 return false;