Combine event and touch action regions into a single class
[WebKit-https.git] / Source / WebCore / rendering / SimpleLineLayoutTextFragmentIterator.h
index c7906c1..a69f850 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * 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
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef SimpleLineLayoutTextFragmentIterator_h
-#define SimpleLineLayoutTextFragmentIterator_h
+#pragma once
 
+#include "BreakLines.h"
 #include "RenderLineBreak.h"
 #include "SimpleLineLayoutFlowContents.h"
-#include "TextBreakIterator.h"
-#include "break_lines.h"
 
 namespace WebCore {
 
@@ -43,7 +41,7 @@ public:
     TextFragmentIterator(const RenderBlockFlow&);
     class TextFragment {
     public:
-        enum Type { ContentEnd, SoftLineBreak, HardLineBreak, Whitespace, NonWhitespace };
+        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)
@@ -57,8 +55,10 @@ public:
         {
         }
 
+        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; }
@@ -66,9 +66,11 @@ public:
         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; }
 
         bool isEmpty() const { return start() == end() && !isLineBreak(); }
-        TextFragment split(unsigned splitPosition, const TextFragmentIterator&);
+        TextFragment split(unsigned splitPosition, float leftSideWidth, float rightSideWidth);
+        TextFragment splitWithHyphen(unsigned hyphenPosition, float hyphenStringWidth, float leftSideWidth, float rightSideWidth);
         bool operator==(const TextFragment& other) const
         {
             return m_start == other.m_start
@@ -78,37 +80,49 @@ public:
                 && m_isLastInRenderer == other.m_isLastInRenderer
                 && m_overlapsToNextRenderer == other.m_overlapsToNextRenderer
                 && m_isCollapsed == other.m_isCollapsed
-                && m_isCollapsible == other.m_isCollapsible;
+                && 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 { NonWhitespace };
+        Type m_type { Invalid };
         bool m_isLastInRenderer { false };
         bool m_overlapsToNextRenderer { false };
         bool m_isCollapsed { false };
         bool m_isCollapsible { false };
+        bool m_hasHyphen { false };
     };
     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;
+    Optional<unsigned> lastHyphenPosition(const TextFragmentIterator::TextFragment& run, unsigned beforeIndex) const;
 
     struct Style {
         explicit Style(const RenderStyle&);
 
         const FontCascade& font;
-        ETextAlign textAlign;
+        TextAlignMode textAlign;
+        bool hasKerningOrLigatures;
         bool collapseWhitespace;
         bool preserveNewline;
         bool wrapLines;
         bool breakAnyWordOnOverflow;
         bool breakFirstWordOnOverflow;
-        float spaceWidth;
+        bool breakNBSP;
+        bool keepAllWordsForCJK;
         float wordSpacing;
         unsigned tabWidth;
+        bool shouldHyphenate;
+        float hyphenStringWidth;
+        unsigned hyphenLimitBefore;
+        unsigned hyphenLimitAfter;
         AtomicString locale;
+        Optional<unsigned> hyphenLimitLines;
     };
     const Style& style() const { return m_style; }
 
@@ -118,9 +132,8 @@ private:
     unsigned skipToNextPosition(PositionType, unsigned startPosition, float& width, float xPosition, bool& overlappingFragment);
     bool isSoftLineBreak(unsigned position) const;
     bool isHardLineBreak(const FlowContents::Iterator& segment) const;
-    template <typename CharacterType> unsigned nextBreakablePosition(const FlowContents::Segment&, unsigned startPosition);
-    template <typename CharacterType> unsigned nextNonWhitespacePosition(const FlowContents::Segment&, unsigned startPosition);
-    template <typename CharacterType> float runWidth(const FlowContents::Segment&, unsigned startPosition, unsigned endPosition, float xPosition) const;
+    unsigned nextBreakablePosition(const FlowContents::Segment&, unsigned startPosition);
+    unsigned nextNonWhitespacePosition(const FlowContents::Segment&, unsigned startPosition);
 
     FlowContents m_flowContents;
     FlowContents::Iterator m_currentSegment;
@@ -130,25 +143,31 @@ private:
     bool m_atEndOfSegment { false };
 };
 
-inline TextFragmentIterator::TextFragment TextFragmentIterator::TextFragment::split(unsigned splitPosition, const TextFragmentIterator& textFragmentIterator)
+inline TextFragmentIterator::TextFragment TextFragmentIterator::TextFragment::split(unsigned splitPosition, float leftSideWidth, float rightSideWidth)
 {
-    auto updateFragmentProperties = [&textFragmentIterator] (TextFragment& fragment)
+    auto updateFragmentProperties = [] (TextFragment& fragment, unsigned start, unsigned end, float width)
     {
-        fragment.m_width = 0;
-        if (fragment.start() != fragment.end())
-            fragment.m_width = textFragmentIterator.textWidth(fragment.start(), fragment.end(), 0);
+        fragment.m_start = start;
+        fragment.m_end = end;
+        fragment.m_width = width;
         if (fragment.start() + 1 > fragment.end())
             return;
         fragment.m_isCollapsed = false;
     };
 
-    TextFragment newFragment(*this);
-    m_end = splitPosition;
-    updateFragmentProperties(*this);
+    TextFragment rightSide(*this);
+    updateFragmentProperties(*this, start(), splitPosition, leftSideWidth);
+    updateFragmentProperties(rightSide, splitPosition, rightSide.end(), rightSideWidth);
+    return rightSide;
+}
 
-    newFragment.m_start = splitPosition;
-    updateFragmentProperties(newFragment);
-    return newFragment;
+inline TextFragmentIterator::TextFragment TextFragmentIterator::TextFragment::splitWithHyphen(unsigned hyphenPosition, float hyphenStringWidth,
+    float leftSideWidth, float rightSideWidth)
+{
+    auto rightSide = split(hyphenPosition, leftSideWidth, rightSideWidth);
+    m_hasHyphen = true;
+    m_width += hyphenStringWidth;
+    return rightSide;
 }
 
 inline bool TextFragmentIterator::isSoftLineBreak(unsigned position) const
@@ -166,5 +185,3 @@ inline bool TextFragmentIterator::isHardLineBreak(const FlowContents::Iterator&
 
 }
 }
-
-#endif