1/* 2 * Copyright (C) 2013 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' 14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS 17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 23 * THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#ifndef SimpleLineLayoutResolver_h 27#define SimpleLineLayoutResolver_h 28 29#include "LayoutRect.h" 30#include "RenderBlockFlow.h" 31#include "RenderText.h" 32#include "SimpleLineLayoutFunctions.h" 33#include <wtf/Vector.h> 34#include <wtf/text/WTFString.h> 35 36namespace WebCore { 37namespace SimpleLineLayout { 38 39template <class IteratorType> 40class Range { 41public: 42 Range(IteratorType begin, IteratorType end) : m_begin(begin), m_end(end) { } 43 44 IteratorType begin() const { return m_begin; } 45 IteratorType end() const { return m_end; } 46 47private: 48 IteratorType m_begin; 49 IteratorType m_end; 50}; 51 52class RunResolver { 53public: 54 class Iterator; 55 56 class Run { 57 public: 58 explicit Run(const Iterator&); 59 60 unsigned start() const; 61 unsigned end() const; 62 63 LayoutRect rect() const; 64 FloatPoint baseline() const; 65 String text() const; 66 67 unsigned lineIndex() const; 68 69 private: 70 const Iterator& m_iterator; 71 }; 72 73 class Iterator { 74 public: 75 Iterator(const RunResolver&, unsigned runIndex, unsigned lineIndex); 76 77 Iterator& operator++(); 78 79 bool operator==(const Iterator&) const; 80 bool operator!=(const Iterator&) const; 81 82 Run operator*() const; 83 84 Iterator& advance(); 85 Iterator& advanceLines(unsigned); 86 87 const RunResolver& resolver() const { return m_resolver; } 88 const SimpleLineLayout::Run& simpleRun() const; 89 unsigned lineIndex() const { return m_lineIndex; } 90 91 private: 92 const RunResolver& m_resolver; 93 unsigned m_runIndex; 94 unsigned m_lineIndex; 95 }; 96 97 RunResolver(const RenderBlockFlow&, const Layout&); 98 99 Iterator begin() const; 100 Iterator end() const; 101 102 Range<Iterator> rangeForRect(const LayoutRect&) const; 103 104private: 105 enum class IndexType { First, Last }; 106 unsigned lineIndexForHeight(LayoutUnit, IndexType) const; 107 108 const Layout& m_layout; 109 const String m_string; 110 const LayoutUnit m_lineHeight; 111 const LayoutUnit m_baseline; 112 const LayoutUnit m_borderAndPaddingBefore; 113 const float m_ascent; 114 const float m_descent; 115}; 116 117class LineResolver { 118public: 119 class Iterator; 120 121 class Iterator { 122 public: 123 explicit Iterator(RunResolver::Iterator); 124 125 Iterator& operator++(); 126 bool operator==(const Iterator&) const; 127 bool operator!=(const Iterator&) const; 128 129 const LayoutRect operator*() const; 130 131 private: 132 RunResolver::Iterator m_runIterator; 133 LayoutRect m_rect; 134 }; 135 136 LineResolver(const RenderBlockFlow&, const Layout&); 137 138 Iterator begin() const; 139 Iterator end() const; 140 141 Range<Iterator> rangeForRect(const LayoutRect&) const; 142 143private: 144 RunResolver m_runResolver; 145}; 146 147RunResolver runResolver(const RenderBlockFlow&, const Layout&); 148LineResolver lineResolver(const RenderBlockFlow&, const Layout&); 149 150inline RunResolver::Run::Run(const Iterator& iterator) 151 : m_iterator(iterator) 152{ 153} 154 155inline unsigned RunResolver::Run::start() const 156{ 157 return m_iterator.simpleRun().start; 158} 159 160inline unsigned RunResolver::Run::end() const 161{ 162 return m_iterator.simpleRun().end; 163} 164 165inline LayoutRect RunResolver::Run::rect() const 166{ 167 auto& resolver = m_iterator.resolver(); 168 auto& run = m_iterator.simpleRun(); 169 170 float baselinePosition = resolver.m_lineHeight * m_iterator.lineIndex() + resolver.m_baseline; 171 LayoutPoint linePosition(LayoutUnit::fromFloatFloor(run.left), roundToInt(baselinePosition - resolver.m_ascent + resolver.m_borderAndPaddingBefore)); 172 LayoutSize lineSize(LayoutUnit::fromFloatCeil(run.right) - LayoutUnit::fromFloatFloor(run.left), resolver.m_ascent + resolver.m_descent); 173 return LayoutRect(linePosition, lineSize); 174} 175 176inline FloatPoint RunResolver::Run::baseline() const 177{ 178 auto& resolver = m_iterator.resolver(); 179 auto& run = m_iterator.simpleRun(); 180 181 float baselinePosition = resolver.m_lineHeight * m_iterator.lineIndex() + resolver.m_baseline; 182 return FloatPoint(run.left, roundToInt(baselinePosition + resolver.m_borderAndPaddingBefore)); 183} 184 185inline String RunResolver::Run::text() const 186{ 187 auto& resolver = m_iterator.resolver(); 188 auto& run = m_iterator.simpleRun(); 189 return resolver.m_string.substringSharingImpl(run.start, run.end - run.start); 190} 191 192inline unsigned RunResolver::Run::lineIndex() const 193{ 194 return m_iterator.lineIndex(); 195} 196 197inline RunResolver::Iterator::Iterator(const RunResolver& resolver, unsigned runIndex, unsigned lineIndex) 198 : m_resolver(resolver) 199 , m_runIndex(runIndex) 200 , m_lineIndex(lineIndex) 201{ 202} 203 204inline RunResolver::Iterator& RunResolver::Iterator::operator++() 205{ 206 return advance(); 207} 208 209inline bool RunResolver::Iterator::operator==(const Iterator& other) const 210{ 211 ASSERT(&m_resolver == &other.m_resolver); 212 return m_runIndex == other.m_runIndex; 213} 214 215inline bool RunResolver::Iterator::operator!=(const Iterator& other) const 216{ 217 return !(*this == other); 218} 219 220inline RunResolver::Run RunResolver::Iterator::operator*() const 221{ 222 return Run(*this); 223} 224 225inline RunResolver::Iterator& RunResolver::Iterator::advance() 226{ 227 if (simpleRun().isEndOfLine) 228 ++m_lineIndex; 229 ++m_runIndex; 230 return *this; 231} 232 233inline RunResolver::Iterator& RunResolver::Iterator::advanceLines(unsigned lineCount) 234{ 235 unsigned runCount = m_resolver.m_layout.runCount(); 236 if (runCount == m_resolver.m_layout.lineCount()) { 237 m_runIndex = std::min(runCount, m_runIndex + lineCount); 238 m_lineIndex = m_runIndex; 239 return *this; 240 } 241 unsigned target = m_lineIndex + lineCount; 242 while (m_lineIndex < target && m_runIndex < runCount) 243 advance(); 244 245 return *this; 246} 247 248inline const SimpleLineLayout::Run& RunResolver::Iterator::simpleRun() const 249{ 250 return m_resolver.m_layout.runAt(m_runIndex); 251} 252 253inline RunResolver::RunResolver(const RenderBlockFlow& flow, const Layout& layout) 254 : m_layout(layout) 255 , m_string(toRenderText(*flow.firstChild()).text()) 256 , m_lineHeight(lineHeightFromFlow(flow)) 257 , m_baseline(baselineFromFlow(flow)) 258 , m_borderAndPaddingBefore(flow.borderAndPaddingBefore()) 259 , m_ascent(flow.style().font().fontMetrics().ascent()) 260 , m_descent(flow.style().font().fontMetrics().descent()) 261{ 262} 263 264inline RunResolver::Iterator RunResolver::begin() const 265{ 266 return Iterator(*this, 0, 0); 267} 268 269inline RunResolver::Iterator RunResolver::end() const 270{ 271 return Iterator(*this, m_layout.runCount(), m_layout.lineCount()); 272} 273 274inline unsigned RunResolver::lineIndexForHeight(LayoutUnit height, IndexType type) const 275{ 276 ASSERT(m_lineHeight); 277 float y = height - m_borderAndPaddingBefore; 278 // Lines may overlap, adjust to get the first or last line at this height. 279 if (type == IndexType::First) 280 y += m_lineHeight - (m_baseline + m_descent); 281 else 282 y -= m_baseline - m_ascent; 283 y = std::max<float>(y, 0); 284 return std::min<unsigned>(y / m_lineHeight, m_layout.lineCount() - 1); 285} 286 287inline Range<RunResolver::Iterator> RunResolver::rangeForRect(const LayoutRect& rect) const 288{ 289 if (!m_lineHeight) 290 return Range<Iterator>(begin(), end()); 291 292 unsigned firstLine = lineIndexForHeight(rect.y(), IndexType::First); 293 unsigned lastLine = std::max(firstLine, lineIndexForHeight(rect.maxY(), IndexType::Last)); 294 295 auto rangeBegin = begin().advanceLines(firstLine); 296 if (rangeBegin == end()) 297 return Range<Iterator>(end(), end()); 298 auto rangeEnd = rangeBegin; 299 ASSERT(lastLine >= firstLine); 300 rangeEnd.advanceLines(lastLine - firstLine + 1); 301 return Range<Iterator>(rangeBegin, rangeEnd); 302} 303 304inline LineResolver::Iterator::Iterator(RunResolver::Iterator runIterator) 305 : m_runIterator(runIterator) 306{ 307} 308 309inline LineResolver::Iterator& LineResolver::Iterator::operator++() 310{ 311 m_runIterator.advanceLines(1); 312 return *this; 313} 314 315inline bool LineResolver::Iterator::operator==(const Iterator& other) const 316{ 317 return m_runIterator == other.m_runIterator; 318} 319 320inline bool LineResolver::Iterator::operator!=(const Iterator& other) const 321{ 322 return m_runIterator != other.m_runIterator; 323} 324 325inline const LayoutRect LineResolver::Iterator::operator*() const 326{ 327 unsigned currentLine = m_runIterator.lineIndex(); 328 auto it = m_runIterator; 329 LayoutRect rect = (*it).rect(); 330 while (it.advance().lineIndex() == currentLine) 331 rect.unite((*it).rect()); 332 333 return rect; 334} 335 336inline LineResolver::LineResolver(const RenderBlockFlow& flow, const Layout& layout) 337 : m_runResolver(flow, layout) 338{ 339} 340 341inline LineResolver::Iterator LineResolver::begin() const 342{ 343 return Iterator(m_runResolver.begin()); 344} 345 346inline LineResolver::Iterator LineResolver::end() const 347{ 348 return Iterator(m_runResolver.end()); 349} 350 351inline Range<LineResolver::Iterator> LineResolver::rangeForRect(const LayoutRect& rect) const 352{ 353 auto runRange = m_runResolver.rangeForRect(rect); 354 return Range<Iterator>(Iterator(runRange.begin()), Iterator(runRange.end())); 355} 356 357inline RunResolver runResolver(const RenderBlockFlow& flow, const Layout& layout) 358{ 359 return RunResolver(flow, layout); 360} 361 362inline LineResolver lineResolver(const RenderBlockFlow& flow, const Layout& layout) 363{ 364 return LineResolver(flow, layout); 365} 366 367} 368} 369 370#endif 371