summaryrefslogtreecommitdiff
path: root/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-06-27 06:07:23 +0000
commit1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c (patch)
tree46dcd36c86e7fbc6e5df36deb463b33e9967a6f7 /Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h
parent32761a6cee1d0dee366b885b7b9c777e67885688 (diff)
downloadWebKitGtk-tarball-master.tar.gz
Diffstat (limited to 'Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h')
-rw-r--r--Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h194
1 files changed, 194 insertions, 0 deletions
diff --git a/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h b/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h
new file mode 100644
index 000000000..3734863a1
--- /dev/null
+++ b/Source/WebCore/rendering/SimpleLineLayoutTextFragmentIterator.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "BreakLines.h"
+#include "RenderLineBreak.h"
+#include "SimpleLineLayoutFlowContents.h"
+
+namespace WebCore {
+
+class RenderBlockFlow;
+class RenderStyle;
+
+namespace SimpleLineLayout {
+
+class TextFragmentIterator {
+public:
+ TextFragmentIterator(const RenderBlockFlow&);
+ class TextFragment {
+ public:
+ enum Type { Invalid, ContentEnd, SoftLineBreak, HardLineBreak, Whitespace, NonWhitespace };
+ TextFragment() = default;
+ TextFragment(unsigned start, unsigned end, float width, Type type, bool isLastInRenderer = false, bool overlapsToNextRenderer = false, bool isCollapsed = false, bool isCollapsible = false)
+ : m_start(start)
+ , m_end(end)
+ , m_width(width)
+ , m_type(type)
+ , m_isLastInRenderer(isLastInRenderer)
+ , m_overlapsToNextRenderer(overlapsToNextRenderer)
+ , m_isCollapsed(isCollapsed)
+ , m_isCollapsible(isCollapsible)
+ {
+ }
+
+ bool isValid() const { return m_type != Invalid; }
+ unsigned start() const { return m_start; }
+ unsigned end() const { return m_end; }
+ unsigned length() const { ASSERT(m_end >= m_start); return m_end - m_start; }
+ float width() const { return m_width; }
+ Type type() const { return m_type; }
+ bool overlapsToNextRenderer() const { return m_overlapsToNextRenderer; }
+ bool isLastInRenderer() const { return m_isLastInRenderer; }
+ bool isLineBreak() const { return m_type == SoftLineBreak || m_type == HardLineBreak; }
+ bool isCollapsed() const { return m_isCollapsed; }
+ bool isCollapsible() const { return m_isCollapsible; }
+ bool hasHyphen() const { return m_hasHyphen; }
+ unsigned wrappingWithHyphenCounter() const { return m_hyphenationCounter; }
+
+ bool isEmpty() const { return start() == end() && !isLineBreak(); }
+ TextFragment split(unsigned splitPosition, const TextFragmentIterator&);
+ TextFragment splitWithHyphen(unsigned hyphenPosition, const TextFragmentIterator&);
+ bool operator==(const TextFragment& other) const
+ {
+ return m_start == other.m_start
+ && m_end == other.m_end
+ && m_width == other.m_width
+ && m_type == other.m_type
+ && m_isLastInRenderer == other.m_isLastInRenderer
+ && m_overlapsToNextRenderer == other.m_overlapsToNextRenderer
+ && m_isCollapsed == other.m_isCollapsed
+ && m_isCollapsible == other.m_isCollapsible
+ && m_hasHyphen == other.m_hasHyphen;
+ }
+
+ private:
+ unsigned m_start { 0 };
+ unsigned m_end { 0 };
+ float m_width { 0 };
+ Type m_type { Invalid };
+ bool m_isLastInRenderer { false };
+ bool m_overlapsToNextRenderer { false };
+ bool m_isCollapsed { false };
+ bool m_isCollapsible { false };
+ bool m_hasHyphen { false };
+ unsigned m_hyphenationCounter { 0 };
+ };
+ TextFragment nextTextFragment(float xPosition = 0);
+ void revertToEndOfFragment(const TextFragment&);
+
+ // FIXME: These functions below should be decoupled from the text iterator.
+ float textWidth(unsigned startPosition, unsigned endPosition, float xPosition) const;
+ std::optional<unsigned> lastHyphenPosition(const TextFragmentIterator::TextFragment& run, unsigned beforeIndex) const;
+
+ struct Style {
+ explicit Style(const RenderStyle&, bool useSimplifiedTextMeasuring);
+
+ const FontCascade& font;
+ ETextAlign textAlign;
+ bool hasKerningOrLigatures;
+ bool collapseWhitespace;
+ bool preserveNewline;
+ bool wrapLines;
+ bool breakAnyWordOnOverflow;
+ bool breakFirstWordOnOverflow;
+ bool breakNBSP;
+ bool keepAllWordsForCJK;
+ float wordSpacing;
+ unsigned tabWidth;
+ bool shouldHyphenate;
+ float hyphenStringWidth;
+ unsigned hyphenLimitBefore;
+ unsigned hyphenLimitAfter;
+ AtomicString locale;
+ std::optional<unsigned> hyphenLimitLines;
+ };
+ const Style& style() const { return m_style; }
+
+private:
+ TextFragment findNextTextFragment(float xPosition);
+ enum PositionType { Breakable, NonWhitespace };
+ unsigned skipToNextPosition(PositionType, unsigned startPosition, float& width, float xPosition, bool& overlappingFragment);
+ bool isSoftLineBreak(unsigned position) const;
+ bool isHardLineBreak(const FlowContents::Iterator& segment) const;
+ unsigned nextBreakablePosition(const FlowContents::Segment&, unsigned startPosition);
+ unsigned nextNonWhitespacePosition(const FlowContents::Segment&, unsigned startPosition);
+
+ FlowContents m_flowContents;
+ FlowContents::Iterator m_currentSegment;
+ LazyLineBreakIterator m_lineBreakIterator;
+ const Style m_style;
+ unsigned m_position { 0 };
+ bool m_atEndOfSegment { false };
+};
+
+inline TextFragmentIterator::TextFragment TextFragmentIterator::TextFragment::split(unsigned splitPosition, const TextFragmentIterator& textFragmentIterator)
+{
+ auto updateFragmentProperties = [&textFragmentIterator] (TextFragment& fragment)
+ {
+ fragment.m_width = 0;
+ if (fragment.start() != fragment.end())
+ fragment.m_width = textFragmentIterator.textWidth(fragment.start(), fragment.end(), 0);
+ if (fragment.start() + 1 > fragment.end())
+ return;
+ fragment.m_isCollapsed = false;
+ };
+
+ TextFragment rightSide(*this);
+ m_end = splitPosition;
+ updateFragmentProperties(*this);
+
+ rightSide.m_start = splitPosition;
+ updateFragmentProperties(rightSide);
+ return rightSide;
+}
+
+inline TextFragmentIterator::TextFragment TextFragmentIterator::TextFragment::splitWithHyphen(unsigned hyphenPosition,
+ const TextFragmentIterator& textFragmentIterator)
+{
+ ASSERT(textFragmentIterator.style().shouldHyphenate);
+ auto rightSide = split(hyphenPosition, textFragmentIterator);
+ rightSide.m_hyphenationCounter = m_hyphenationCounter + 1;
+ m_hasHyphen = true;
+ m_width += textFragmentIterator.style().hyphenStringWidth;
+ return rightSide;
+}
+
+inline bool TextFragmentIterator::isSoftLineBreak(unsigned position) const
+{
+ const auto& segment = *m_currentSegment;
+ ASSERT(segment.start <= position && position < segment.end);
+ return m_style.preserveNewline && segment.text[position - segment.start] == '\n';
+}
+
+inline bool TextFragmentIterator::isHardLineBreak(const FlowContents::Iterator& segment) const
+{
+ ASSERT(segment->start != segment->end || (segment->start == segment->end && is<RenderLineBreak>(segment->renderer)));
+ return segment->start == segment->end;
+}
+
+}
+}