/src/3rdparty/webkit/Source/WebCore/rendering/RenderText.cpp

https://bitbucket.org/ultra_iter/qt-vtl · C++ · 1670 lines · 1313 code · 241 blank · 116 comment · 487 complexity · 34efc4829a1f95fc9b0987457e9c2523 MD5 · raw file

Large files are truncated click here to view the full file

  1. /*
  2. * (C) 1999 Lars Knoll (knoll@kde.org)
  3. * (C) 2000 Dirk Mueller (mueller@kde.org)
  4. * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
  5. * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
  6. * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Library General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Library General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Library General Public License
  19. * along with this library; see the file COPYING.LIB. If not, write to
  20. * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  21. * Boston, MA 02110-1301, USA.
  22. *
  23. */
  24. #include "config.h"
  25. #include "RenderText.h"
  26. #include "AXObjectCache.h"
  27. #include "EllipsisBox.h"
  28. #include "FloatQuad.h"
  29. #include "FontTranscoder.h"
  30. #include "FrameView.h"
  31. #include "InlineTextBox.h"
  32. #include "Range.h"
  33. #include "RenderArena.h"
  34. #include "RenderBlock.h"
  35. #include "RenderCombineText.h"
  36. #include "RenderLayer.h"
  37. #include "RenderView.h"
  38. #include "Settings.h"
  39. #include "Text.h"
  40. #include "TextBreakIterator.h"
  41. #include "TextResourceDecoder.h"
  42. #include "TextRun.h"
  43. #include "VisiblePosition.h"
  44. #include "break_lines.h"
  45. #include <wtf/AlwaysInline.h>
  46. #include <wtf/text/StringBuffer.h>
  47. #include <wtf/unicode/CharacterNames.h>
  48. using namespace std;
  49. using namespace WTF;
  50. using namespace Unicode;
  51. namespace WebCore {
  52. class SecureTextTimer;
  53. typedef HashMap<RenderText*, SecureTextTimer*> SecureTextTimerMap;
  54. static SecureTextTimerMap* gSecureTextTimers = 0;
  55. class SecureTextTimer : public TimerBase {
  56. public:
  57. SecureTextTimer(RenderText* renderText)
  58. : m_renderText(renderText)
  59. , m_lastTypedCharacterOffset(-1)
  60. {
  61. }
  62. void restartWithNewText(unsigned lastTypedCharacterOffset)
  63. {
  64. m_lastTypedCharacterOffset = lastTypedCharacterOffset;
  65. startOneShot(m_renderText->document()->settings()->passwordEchoDurationInSeconds());
  66. }
  67. void invalidate() { m_lastTypedCharacterOffset = -1; }
  68. unsigned lastTypedCharacterOffset() { return m_lastTypedCharacterOffset; }
  69. private:
  70. virtual void fired()
  71. {
  72. ASSERT(gSecureTextTimers->contains(m_renderText));
  73. m_renderText->setText(m_renderText->text(), true /* forcing setting text as it may be masked later */);
  74. }
  75. RenderText* m_renderText;
  76. int m_lastTypedCharacterOffset;
  77. };
  78. static void makeCapitalized(String* string, UChar previous)
  79. {
  80. if (string->isNull())
  81. return;
  82. unsigned length = string->length();
  83. const UChar* characters = string->characters();
  84. if (length >= numeric_limits<unsigned>::max())
  85. CRASH();
  86. StringBuffer stringWithPrevious(length + 1);
  87. stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous;
  88. for (unsigned i = 1; i < length + 1; i++) {
  89. // Replace &nbsp with a real space since ICU no longer treats &nbsp as a word separator.
  90. if (characters[i - 1] == noBreakSpace)
  91. stringWithPrevious[i] = ' ';
  92. else
  93. stringWithPrevious[i] = characters[i - 1];
  94. }
  95. TextBreakIterator* boundary = wordBreakIterator(stringWithPrevious.characters(), length + 1);
  96. if (!boundary)
  97. return;
  98. StringBuffer data(length);
  99. int32_t endOfWord;
  100. int32_t startOfWord = textBreakFirst(boundary);
  101. for (endOfWord = textBreakNext(boundary); endOfWord != TextBreakDone; startOfWord = endOfWord, endOfWord = textBreakNext(boundary)) {
  102. if (startOfWord != 0) // Ignore first char of previous string
  103. data[startOfWord - 1] = characters[startOfWord - 1] == noBreakSpace ? noBreakSpace : toTitleCase(stringWithPrevious[startOfWord]);
  104. for (int i = startOfWord + 1; i < endOfWord; i++)
  105. data[i - 1] = characters[i - 1];
  106. }
  107. *string = String::adopt(data);
  108. }
  109. RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
  110. : RenderObject(node)
  111. , m_minWidth(-1)
  112. , m_text(str)
  113. , m_firstTextBox(0)
  114. , m_lastTextBox(0)
  115. , m_maxWidth(-1)
  116. , m_beginMinWidth(0)
  117. , m_endMinWidth(0)
  118. , m_hasTab(false)
  119. , m_linesDirty(false)
  120. , m_containsReversedText(false)
  121. , m_isAllASCII(m_text.containsOnlyASCII())
  122. , m_knownToHaveNoOverflowAndNoFallbackFonts(false)
  123. , m_needsTranscoding(false)
  124. {
  125. ASSERT(m_text);
  126. setIsText();
  127. // FIXME: It would be better to call this only if !m_text->containsOnlyWhitespace().
  128. // But that might slow things down, and maybe should only be done if visuallyNonEmpty
  129. // is still false. Not making any change for now, but should consider in the future.
  130. view()->frameView()->setIsVisuallyNonEmpty();
  131. }
  132. #ifndef NDEBUG
  133. RenderText::~RenderText()
  134. {
  135. ASSERT(!m_firstTextBox);
  136. ASSERT(!m_lastTextBox);
  137. }
  138. #endif
  139. const char* RenderText::renderName() const
  140. {
  141. return "RenderText";
  142. }
  143. bool RenderText::isTextFragment() const
  144. {
  145. return false;
  146. }
  147. bool RenderText::isWordBreak() const
  148. {
  149. return false;
  150. }
  151. void RenderText::updateNeedsTranscoding()
  152. {
  153. const TextEncoding* encoding = document()->decoder() ? &document()->decoder()->encoding() : 0;
  154. m_needsTranscoding = fontTranscoder().needsTranscoding(style()->font().fontDescription(), encoding);
  155. }
  156. void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
  157. {
  158. // There is no need to ever schedule repaints from a style change of a text run, since
  159. // we already did this for the parent of the text run.
  160. // We do have to schedule layouts, though, since a style change can force us to
  161. // need to relayout.
  162. if (diff == StyleDifferenceLayout) {
  163. setNeedsLayoutAndPrefWidthsRecalc();
  164. m_knownToHaveNoOverflowAndNoFallbackFonts = false;
  165. }
  166. bool needsResetText = false;
  167. if (!oldStyle) {
  168. updateNeedsTranscoding();
  169. needsResetText = m_needsTranscoding;
  170. } else if (oldStyle->font().needsTranscoding() != style()->font().needsTranscoding() || (style()->font().needsTranscoding() && oldStyle->font().family().family() != style()->font().family().family())) {
  171. updateNeedsTranscoding();
  172. needsResetText = true;
  173. }
  174. ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE;
  175. ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE;
  176. if (needsResetText || oldTransform != style()->textTransform() || oldSecurity != style()->textSecurity()) {
  177. if (RefPtr<StringImpl> textToTransform = originalText())
  178. setText(textToTransform.release(), true);
  179. }
  180. }
  181. void RenderText::removeAndDestroyTextBoxes()
  182. {
  183. if (!documentBeingDestroyed()) {
  184. if (firstTextBox()) {
  185. if (isBR()) {
  186. RootInlineBox* next = firstTextBox()->root()->nextRootBox();
  187. if (next)
  188. next->markDirty();
  189. }
  190. for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
  191. box->remove();
  192. } else if (parent())
  193. parent()->dirtyLinesFromChangedChild(this);
  194. }
  195. deleteTextBoxes();
  196. }
  197. void RenderText::destroy()
  198. {
  199. if (SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->take(this) : 0)
  200. delete secureTextTimer;
  201. removeAndDestroyTextBoxes();
  202. RenderObject::destroy();
  203. }
  204. void RenderText::extractTextBox(InlineTextBox* box)
  205. {
  206. checkConsistency();
  207. m_lastTextBox = box->prevTextBox();
  208. if (box == m_firstTextBox)
  209. m_firstTextBox = 0;
  210. if (box->prevTextBox())
  211. box->prevTextBox()->setNextTextBox(0);
  212. box->setPreviousTextBox(0);
  213. for (InlineTextBox* curr = box; curr; curr = curr->nextTextBox())
  214. curr->setExtracted();
  215. checkConsistency();
  216. }
  217. void RenderText::attachTextBox(InlineTextBox* box)
  218. {
  219. checkConsistency();
  220. if (m_lastTextBox) {
  221. m_lastTextBox->setNextTextBox(box);
  222. box->setPreviousTextBox(m_lastTextBox);
  223. } else
  224. m_firstTextBox = box;
  225. InlineTextBox* last = box;
  226. for (InlineTextBox* curr = box; curr; curr = curr->nextTextBox()) {
  227. curr->setExtracted(false);
  228. last = curr;
  229. }
  230. m_lastTextBox = last;
  231. checkConsistency();
  232. }
  233. void RenderText::removeTextBox(InlineTextBox* box)
  234. {
  235. checkConsistency();
  236. if (box == m_firstTextBox)
  237. m_firstTextBox = box->nextTextBox();
  238. if (box == m_lastTextBox)
  239. m_lastTextBox = box->prevTextBox();
  240. if (box->nextTextBox())
  241. box->nextTextBox()->setPreviousTextBox(box->prevTextBox());
  242. if (box->prevTextBox())
  243. box->prevTextBox()->setNextTextBox(box->nextTextBox());
  244. checkConsistency();
  245. }
  246. void RenderText::deleteTextBoxes()
  247. {
  248. if (firstTextBox()) {
  249. RenderArena* arena = renderArena();
  250. InlineTextBox* next;
  251. for (InlineTextBox* curr = firstTextBox(); curr; curr = next) {
  252. next = curr->nextTextBox();
  253. curr->destroy(arena);
  254. }
  255. m_firstTextBox = m_lastTextBox = 0;
  256. }
  257. }
  258. PassRefPtr<StringImpl> RenderText::originalText() const
  259. {
  260. Node* e = node();
  261. return (e && e->isTextNode()) ? static_cast<Text*>(e)->dataImpl() : 0;
  262. }
  263. void RenderText::absoluteRects(Vector<IntRect>& rects, int tx, int ty)
  264. {
  265. for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
  266. rects.append(enclosingIntRect(FloatRect(tx + box->x(), ty + box->y(), box->width(), box->height())));
  267. }
  268. void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, unsigned end, bool useSelectionHeight)
  269. {
  270. // Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
  271. // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this
  272. // function to take ints causes various internal mismatches. But selectionRect takes ints, and
  273. // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but
  274. // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
  275. ASSERT(end == UINT_MAX || end <= INT_MAX);
  276. ASSERT(start <= INT_MAX);
  277. start = min(start, static_cast<unsigned>(INT_MAX));
  278. end = min(end, static_cast<unsigned>(INT_MAX));
  279. for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
  280. // Note: box->end() returns the index of the last character, not the index past it
  281. if (start <= box->start() && box->end() < end) {
  282. IntRect r = box->calculateBoundaries();
  283. if (useSelectionHeight) {
  284. IntRect selectionRect = box->selectionRect(0, 0, start, end);
  285. if (box->isHorizontal()) {
  286. r.setHeight(selectionRect.height());
  287. r.setY(selectionRect.y());
  288. } else {
  289. r.setWidth(selectionRect.width());
  290. r.setX(selectionRect.x());
  291. }
  292. }
  293. rects.append(localToAbsoluteQuad(FloatQuad(r)).enclosingBoundingBox());
  294. } else {
  295. unsigned realEnd = min(box->end() + 1, end);
  296. IntRect r = box->selectionRect(0, 0, start, realEnd);
  297. if (!r.isEmpty()) {
  298. if (!useSelectionHeight) {
  299. // change the height and y position because selectionRect uses selection-specific values
  300. if (box->isHorizontal()) {
  301. r.setHeight(box->logicalHeight());
  302. r.setY(box->y());
  303. } else {
  304. r.setWidth(box->logicalWidth());
  305. r.setX(box->x());
  306. }
  307. }
  308. rects.append(localToAbsoluteQuad(FloatQuad(r)).enclosingBoundingBox());
  309. }
  310. }
  311. }
  312. }
  313. static IntRect ellipsisRectForBox(InlineTextBox* box, unsigned startPos, unsigned endPos)
  314. {
  315. if (!box)
  316. return IntRect();
  317. unsigned short truncation = box->truncation();
  318. if (truncation == cNoTruncation)
  319. return IntRect();
  320. IntRect rect;
  321. if (EllipsisBox* ellipsis = box->root()->ellipsisBox()) {
  322. int ellipsisStartPosition = max<int>(startPos - box->start(), 0);
  323. int ellipsisEndPosition = min<int>(endPos - box->start(), box->len());
  324. // The ellipsis should be considered to be selected if the end of
  325. // the selection is past the beginning of the truncation and the
  326. // beginning of the selection is before or at the beginning of the truncation.
  327. if (ellipsisEndPosition >= truncation && ellipsisStartPosition <= truncation)
  328. return ellipsis->selectionRect(0, 0);
  329. }
  330. return IntRect();
  331. }
  332. void RenderText::absoluteQuads(Vector<FloatQuad>& quads, ClippingOption option)
  333. {
  334. for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
  335. IntRect boundaries = box->calculateBoundaries();
  336. // Shorten the width of this text box if it ends in an ellipsis.
  337. IntRect ellipsisRect = (option == ClipToEllipsis) ? ellipsisRectForBox(box, 0, textLength()) : IntRect();
  338. if (!ellipsisRect.isEmpty()) {
  339. if (style()->isHorizontalWritingMode())
  340. boundaries.setWidth(ellipsisRect.maxX() - boundaries.x());
  341. else
  342. boundaries.setHeight(ellipsisRect.maxY() - boundaries.y());
  343. }
  344. quads.append(localToAbsoluteQuad(FloatRect(boundaries)));
  345. }
  346. }
  347. void RenderText::absoluteQuads(Vector<FloatQuad>& quads)
  348. {
  349. absoluteQuads(quads, NoClipping);
  350. }
  351. void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start, unsigned end, bool useSelectionHeight)
  352. {
  353. // Work around signed/unsigned issues. This function takes unsigneds, and is often passed UINT_MAX
  354. // to mean "all the way to the end". InlineTextBox coordinates are unsigneds, so changing this
  355. // function to take ints causes various internal mismatches. But selectionRect takes ints, and
  356. // passing UINT_MAX to it causes trouble. Ideally we'd change selectionRect to take unsigneds, but
  357. // that would cause many ripple effects, so for now we'll just clamp our unsigned parameters to INT_MAX.
  358. ASSERT(end == UINT_MAX || end <= INT_MAX);
  359. ASSERT(start <= INT_MAX);
  360. start = min(start, static_cast<unsigned>(INT_MAX));
  361. end = min(end, static_cast<unsigned>(INT_MAX));
  362. for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
  363. // Note: box->end() returns the index of the last character, not the index past it
  364. if (start <= box->start() && box->end() < end) {
  365. IntRect r(box->calculateBoundaries());
  366. if (useSelectionHeight) {
  367. IntRect selectionRect = box->selectionRect(0, 0, start, end);
  368. if (box->isHorizontal()) {
  369. r.setHeight(selectionRect.height());
  370. r.setY(selectionRect.y());
  371. } else {
  372. r.setWidth(selectionRect.width());
  373. r.setX(selectionRect.x());
  374. }
  375. }
  376. quads.append(localToAbsoluteQuad(FloatRect(r)));
  377. } else {
  378. unsigned realEnd = min(box->end() + 1, end);
  379. IntRect r = box->selectionRect(0, 0, start, realEnd);
  380. if (r.height()) {
  381. if (!useSelectionHeight) {
  382. // change the height and y position because selectionRect uses selection-specific values
  383. if (box->isHorizontal()) {
  384. r.setHeight(box->logicalHeight());
  385. r.setY(box->y());
  386. } else {
  387. r.setWidth(box->logicalHeight());
  388. r.setX(box->x());
  389. }
  390. }
  391. quads.append(localToAbsoluteQuad(FloatRect(r)));
  392. }
  393. }
  394. }
  395. }
  396. InlineTextBox* RenderText::findNextInlineTextBox(int offset, int& pos) const
  397. {
  398. // The text runs point to parts of the RenderText's m_text
  399. // (they don't include '\n')
  400. // Find the text run that includes the character at offset
  401. // and return pos, which is the position of the char in the run.
  402. if (!m_firstTextBox)
  403. return 0;
  404. InlineTextBox* s = m_firstTextBox;
  405. int off = s->len();
  406. while (offset > off && s->nextTextBox()) {
  407. s = s->nextTextBox();
  408. off = s->start() + s->len();
  409. }
  410. // we are now in the correct text run
  411. pos = (offset > off ? s->len() : s->len() - (off - offset) );
  412. return s;
  413. }
  414. static bool lineDirectionPointFitsInBox(int pointLineDirection, InlineTextBox* box, int offset, EAffinity& affinity)
  415. {
  416. affinity = DOWNSTREAM;
  417. // the x coordinate is equal to the left edge of this box
  418. // the affinity must be downstream so the position doesn't jump back to the previous line
  419. if (pointLineDirection == box->logicalLeft())
  420. return true;
  421. // and the x coordinate is to the left of the right edge of this box
  422. // check to see if position goes in this box
  423. if (pointLineDirection < box->logicalRight()) {
  424. affinity = offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM;
  425. return true;
  426. }
  427. // box is first on line
  428. // and the x coordinate is to the left of the first text box left edge
  429. if (!box->prevOnLine() && pointLineDirection < box->logicalLeft())
  430. return true;
  431. if (!box->nextOnLine()) {
  432. // box is last on line
  433. // and the x coordinate is to the right of the last text box right edge
  434. // generate VisiblePosition, use UPSTREAM affinity if possible
  435. affinity = offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM;
  436. return true;
  437. }
  438. return false;
  439. }
  440. VisiblePosition RenderText::positionForPoint(const IntPoint& point)
  441. {
  442. if (!firstTextBox() || textLength() == 0)
  443. return createVisiblePosition(0, DOWNSTREAM);
  444. // Get the offset for the position, since this will take rtl text into account.
  445. int offset;
  446. int pointLineDirection = firstTextBox()->isHorizontal() ? point.x() : point.y();
  447. int pointBlockDirection = firstTextBox()->isHorizontal() ? point.y() : point.x();
  448. // FIXME: We should be able to roll these special cases into the general cases in the loop below.
  449. if (firstTextBox() && pointBlockDirection < firstTextBox()->root()->selectionBottom() && pointLineDirection < firstTextBox()->logicalLeft()) {
  450. // at the y coordinate of the first line or above
  451. // and the x coordinate is to the left of the first text box left edge
  452. offset = firstTextBox()->offsetForPosition(pointLineDirection);
  453. return createVisiblePosition(offset + firstTextBox()->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
  454. }
  455. if (lastTextBox() && pointBlockDirection >= lastTextBox()->root()->selectionTop() && pointLineDirection >= lastTextBox()->logicalRight()) {
  456. // at the y coordinate of the last line or below
  457. // and the x coordinate is to the right of the last text box right edge
  458. offset = lastTextBox()->offsetForPosition(pointLineDirection);
  459. return createVisiblePosition(offset + lastTextBox()->start(), VP_UPSTREAM_IF_POSSIBLE);
  460. }
  461. InlineTextBox* lastBoxAbove = 0;
  462. for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
  463. RootInlineBox* rootBox = box->root();
  464. if (pointBlockDirection >= rootBox->selectionTop() || pointBlockDirection >= rootBox->lineTop()) {
  465. int bottom = rootBox->selectionBottom();
  466. if (rootBox->nextRootBox())
  467. bottom = min(bottom, rootBox->nextRootBox()->lineTop());
  468. if (pointBlockDirection < bottom) {
  469. EAffinity affinity;
  470. int offset = box->offsetForPosition(pointLineDirection);
  471. if (lineDirectionPointFitsInBox(pointLineDirection, box, offset, affinity))
  472. return createVisiblePosition(offset + box->start(), affinity);
  473. }
  474. lastBoxAbove = box;
  475. }
  476. }
  477. return createVisiblePosition(lastBoxAbove ? lastBoxAbove->start() + lastBoxAbove->len() : 0, DOWNSTREAM);
  478. }
  479. IntRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
  480. {
  481. if (!inlineBox)
  482. return IntRect();
  483. ASSERT(inlineBox->isInlineTextBox());
  484. if (!inlineBox->isInlineTextBox())
  485. return IntRect();
  486. InlineTextBox* box = static_cast<InlineTextBox*>(inlineBox);
  487. int height = box->root()->selectionHeight();
  488. int top = box->root()->selectionTop();
  489. // Go ahead and round left to snap it to the nearest pixel.
  490. float left = box->positionForOffset(caretOffset);
  491. // Distribute the caret's width to either side of the offset.
  492. int caretWidthLeftOfOffset = caretWidth / 2;
  493. left -= caretWidthLeftOfOffset;
  494. int caretWidthRightOfOffset = caretWidth - caretWidthLeftOfOffset;
  495. left = roundf(left);
  496. float rootLeft = box->root()->logicalLeft();
  497. float rootRight = box->root()->logicalRight();
  498. // FIXME: should we use the width of the root inline box or the
  499. // width of the containing block for this?
  500. if (extraWidthToEndOfLine)
  501. *extraWidthToEndOfLine = (box->root()->logicalWidth() + rootLeft) - (left + 1);
  502. RenderBlock* cb = containingBlock();
  503. RenderStyle* cbStyle = cb->style();
  504. float leftEdge;
  505. float rightEdge;
  506. if (style()->autoWrap()) {
  507. leftEdge = 0;
  508. rightEdge = cb->logicalWidth();
  509. } else {
  510. leftEdge = min(static_cast<float>(0), rootLeft);
  511. rightEdge = max(static_cast<float>(cb->logicalWidth()), rootRight);
  512. }
  513. bool rightAligned = false;
  514. switch (cbStyle->textAlign()) {
  515. case TAAUTO:
  516. case JUSTIFY:
  517. rightAligned = !cbStyle->isLeftToRightDirection();
  518. break;
  519. case RIGHT:
  520. case WEBKIT_RIGHT:
  521. rightAligned = true;
  522. break;
  523. case LEFT:
  524. case WEBKIT_LEFT:
  525. case CENTER:
  526. case WEBKIT_CENTER:
  527. break;
  528. case TASTART:
  529. rightAligned = !cbStyle->isLeftToRightDirection();
  530. break;
  531. case TAEND:
  532. rightAligned = cbStyle->isLeftToRightDirection();
  533. break;
  534. }
  535. if (rightAligned) {
  536. left = max(left, leftEdge);
  537. left = min(left, rootRight - caretWidth);
  538. } else {
  539. left = min(left, rightEdge - caretWidthRightOfOffset);
  540. left = max(left, rootLeft);
  541. }
  542. return style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth, height) : IntRect(top, left, height, caretWidth);
  543. }
  544. ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
  545. {
  546. if (style()->hasTextCombine() && isCombineText()) {
  547. const RenderCombineText* combineText = toRenderCombineText(this);
  548. if (combineText->isCombined())
  549. return combineText->combinedTextWidth(f);
  550. }
  551. if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) {
  552. float monospaceCharacterWidth = f.spaceWidth();
  553. float tabWidth = allowTabs() ? monospaceCharacterWidth * 8 : 0;
  554. float w = 0;
  555. bool isSpace;
  556. bool previousCharWasSpace = true; // FIXME: Preserves historical behavior, but seems wrong for start > 0.
  557. ASSERT(m_text);
  558. StringImpl& text = *m_text.impl();
  559. for (int i = start; i < start + len; i++) {
  560. char c = text[i];
  561. if (c <= ' ') {
  562. if (c == ' ' || c == '\n') {
  563. w += monospaceCharacterWidth;
  564. isSpace = true;
  565. } else if (c == '\t') {
  566. w += tabWidth ? tabWidth - fmodf(xPos + w, tabWidth) : monospaceCharacterWidth;
  567. isSpace = true;
  568. } else
  569. isSpace = false;
  570. } else {
  571. w += monospaceCharacterWidth;
  572. isSpace = false;
  573. }
  574. if (isSpace && !previousCharWasSpace)
  575. w += f.wordSpacing();
  576. previousCharWasSpace = isSpace;
  577. }
  578. return w;
  579. }
  580. return f.width(TextRun(text()->characters() + start, len, allowTabs(), xPos), fallbackFonts, glyphOverflow);
  581. }
  582. void RenderText::trimmedPrefWidths(float leadWidth,
  583. float& beginMinW, bool& beginWS,
  584. float& endMinW, bool& endWS,
  585. bool& hasBreakableChar, bool& hasBreak,
  586. float& beginMaxW, float& endMaxW,
  587. float& minW, float& maxW, bool& stripFrontSpaces)
  588. {
  589. bool collapseWhiteSpace = style()->collapseWhiteSpace();
  590. if (!collapseWhiteSpace)
  591. stripFrontSpaces = false;
  592. if (m_hasTab || preferredLogicalWidthsDirty())
  593. computePreferredLogicalWidths(leadWidth);
  594. beginWS = !stripFrontSpaces && m_hasBeginWS;
  595. endWS = m_hasEndWS;
  596. int len = textLength();
  597. if (!len || (stripFrontSpaces && text()->containsOnlyWhitespace())) {
  598. beginMinW = 0;
  599. endMinW = 0;
  600. beginMaxW = 0;
  601. endMaxW = 0;
  602. minW = 0;
  603. maxW = 0;
  604. hasBreak = false;
  605. return;
  606. }
  607. minW = m_minWidth;
  608. maxW = m_maxWidth;
  609. beginMinW = m_beginMinWidth;
  610. endMinW = m_endMinWidth;
  611. hasBreakableChar = m_hasBreakableChar;
  612. hasBreak = m_hasBreak;
  613. ASSERT(m_text);
  614. StringImpl& text = *m_text.impl();
  615. if (text[0] == ' ' || (text[0] == '\n' && !style()->preserveNewline()) || text[0] == '\t') {
  616. const Font& f = style()->font(); // FIXME: This ignores first-line.
  617. if (stripFrontSpaces) {
  618. const UChar space = ' ';
  619. float spaceWidth = f.width(TextRun(&space, 1));
  620. maxW -= spaceWidth;
  621. } else
  622. maxW += f.wordSpacing();
  623. }
  624. stripFrontSpaces = collapseWhiteSpace && m_hasEndWS;
  625. if (!style()->autoWrap() || minW > maxW)
  626. minW = maxW;
  627. // Compute our max widths by scanning the string for newlines.
  628. if (hasBreak) {
  629. const Font& f = style()->font(); // FIXME: This ignores first-line.
  630. bool firstLine = true;
  631. beginMaxW = maxW;
  632. endMaxW = maxW;
  633. for (int i = 0; i < len; i++) {
  634. int linelen = 0;
  635. while (i + linelen < len && text[i + linelen] != '\n')
  636. linelen++;
  637. if (linelen) {
  638. endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW, 0, 0);
  639. if (firstLine) {
  640. firstLine = false;
  641. leadWidth = 0;
  642. beginMaxW = endMaxW;
  643. }
  644. i += linelen;
  645. } else if (firstLine) {
  646. beginMaxW = 0;
  647. firstLine = false;
  648. leadWidth = 0;
  649. }
  650. if (i == len - 1)
  651. // A <pre> run that ends with a newline, as in, e.g.,
  652. // <pre>Some text\n\n<span>More text</pre>
  653. endMaxW = 0;
  654. }
  655. }
  656. }
  657. static inline bool isSpaceAccordingToStyle(UChar c, RenderStyle* style)
  658. {
  659. return c == ' ' || (c == noBreakSpace && style->nbspMode() == SPACE);
  660. }
  661. float RenderText::minLogicalWidth() const
  662. {
  663. if (preferredLogicalWidthsDirty())
  664. const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
  665. return m_minWidth;
  666. }
  667. float RenderText::maxLogicalWidth() const
  668. {
  669. if (preferredLogicalWidthsDirty())
  670. const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
  671. return m_maxWidth;
  672. }
  673. void RenderText::computePreferredLogicalWidths(float leadWidth)
  674. {
  675. HashSet<const SimpleFontData*> fallbackFonts;
  676. GlyphOverflow glyphOverflow;
  677. computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphOverflow);
  678. if (fallbackFonts.isEmpty() && !glyphOverflow.left && !glyphOverflow.right && !glyphOverflow.top && !glyphOverflow.bottom)
  679. m_knownToHaveNoOverflowAndNoFallbackFonts = true;
  680. }
  681. void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow)
  682. {
  683. ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts);
  684. m_minWidth = 0;
  685. m_beginMinWidth = 0;
  686. m_endMinWidth = 0;
  687. m_maxWidth = 0;
  688. if (isBR())
  689. return;
  690. float currMinWidth = 0;
  691. float currMaxWidth = 0;
  692. m_hasBreakableChar = false;
  693. m_hasBreak = false;
  694. m_hasTab = false;
  695. m_hasBeginWS = false;
  696. m_hasEndWS = false;
  697. const Font& f = style()->font(); // FIXME: This ignores first-line.
  698. float wordSpacing = style()->wordSpacing();
  699. int len = textLength();
  700. const UChar* txt = characters();
  701. LazyLineBreakIterator breakIterator(txt, len);
  702. bool needsWordSpacing = false;
  703. bool ignoringSpaces = false;
  704. bool isSpace = false;
  705. bool firstWord = true;
  706. bool firstLine = true;
  707. int nextBreakable = -1;
  708. int lastWordBoundary = 0;
  709. int firstGlyphLeftOverflow = -1;
  710. bool breakNBSP = style()->autoWrap() && style()->nbspMode() == SPACE;
  711. bool breakAll = (style()->wordBreak() == BreakAllWordBreak || style()->wordBreak() == BreakWordBreak) && style()->autoWrap();
  712. for (int i = 0; i < len; i++) {
  713. UChar c = txt[i];
  714. bool previousCharacterIsSpace = isSpace;
  715. bool isNewline = false;
  716. if (c == '\n') {
  717. if (style()->preserveNewline()) {
  718. m_hasBreak = true;
  719. isNewline = true;
  720. isSpace = false;
  721. } else
  722. isSpace = true;
  723. } else if (c == '\t') {
  724. if (!style()->collapseWhiteSpace()) {
  725. m_hasTab = true;
  726. isSpace = false;
  727. } else
  728. isSpace = true;
  729. } else
  730. isSpace = c == ' ';
  731. if ((isSpace || isNewline) && !i)
  732. m_hasBeginWS = true;
  733. if ((isSpace || isNewline) && i == len - 1)
  734. m_hasEndWS = true;
  735. if (!ignoringSpaces && style()->collapseWhiteSpace() && previousCharacterIsSpace && isSpace)
  736. ignoringSpaces = true;
  737. if (ignoringSpaces && !isSpace)
  738. ignoringSpaces = false;
  739. // Ignore spaces and soft hyphens
  740. if (ignoringSpaces) {
  741. ASSERT(lastWordBoundary == i);
  742. lastWordBoundary++;
  743. continue;
  744. } else if (c == softHyphen) {
  745. currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
  746. if (firstGlyphLeftOverflow < 0)
  747. firstGlyphLeftOverflow = glyphOverflow.left;
  748. lastWordBoundary = i + 1;
  749. continue;
  750. }
  751. bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable, breakNBSP);
  752. bool betweenWords = true;
  753. int j = i;
  754. while (c != '\n' && !isSpaceAccordingToStyle(c, style()) && c != '\t' && c != softHyphen) {
  755. j++;
  756. if (j == len)
  757. break;
  758. c = txt[j];
  759. if (isBreakable(breakIterator, j, nextBreakable, breakNBSP))
  760. break;
  761. if (breakAll) {
  762. betweenWords = false;
  763. break;
  764. }
  765. }
  766. int wordLen = j - i;
  767. if (wordLen) {
  768. float w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
  769. if (firstGlyphLeftOverflow < 0)
  770. firstGlyphLeftOverflow = glyphOverflow.left;
  771. currMinWidth += w;
  772. if (betweenWords) {
  773. if (lastWordBoundary == i)
  774. currMaxWidth += w;
  775. else
  776. currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
  777. lastWordBoundary = j;
  778. }
  779. bool isSpace = (j < len) && isSpaceAccordingToStyle(c, style());
  780. bool isCollapsibleWhiteSpace = (j < len) && style()->isCollapsibleWhiteSpace(c);
  781. if (j < len && style()->autoWrap())
  782. m_hasBreakableChar = true;
  783. // Add in wordSpacing to our currMaxWidth, but not if this is the last word on a line or the
  784. // last word in the run.
  785. if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && !containsOnlyWhitespace(j, len-j))
  786. currMaxWidth += wordSpacing;
  787. if (firstWord) {
  788. firstWord = false;
  789. // If the first character in the run is breakable, then we consider ourselves to have a beginning
  790. // minimum width of 0, since a break could occur right before our run starts, preventing us from ever
  791. // being appended to a previous text run when considering the total minimum width of the containing block.
  792. if (hasBreak)
  793. m_hasBreakableChar = true;
  794. m_beginMinWidth = hasBreak ? 0 : w;
  795. }
  796. m_endMinWidth = w;
  797. if (currMinWidth > m_minWidth)
  798. m_minWidth = currMinWidth;
  799. currMinWidth = 0;
  800. i += wordLen - 1;
  801. } else {
  802. // Nowrap can never be broken, so don't bother setting the
  803. // breakable character boolean. Pre can only be broken if we encounter a newline.
  804. if (style()->autoWrap() || isNewline)
  805. m_hasBreakableChar = true;
  806. if (currMinWidth > m_minWidth)
  807. m_minWidth = currMinWidth;
  808. currMinWidth = 0;
  809. if (isNewline) { // Only set if preserveNewline was true and we saw a newline.
  810. if (firstLine) {
  811. firstLine = false;
  812. leadWidth = 0;
  813. if (!style()->autoWrap())
  814. m_beginMinWidth = currMaxWidth;
  815. }
  816. if (currMaxWidth > m_maxWidth)
  817. m_maxWidth = currMaxWidth;
  818. currMaxWidth = 0;
  819. } else {
  820. currMaxWidth += f.width(TextRun(txt + i, 1, allowTabs(), leadWidth + currMaxWidth));
  821. glyphOverflow.right = 0;
  822. needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1;
  823. }
  824. ASSERT(lastWordBoundary == i);
  825. lastWordBoundary++;
  826. }
  827. }
  828. if (firstGlyphLeftOverflow > 0)
  829. glyphOverflow.left = firstGlyphLeftOverflow;
  830. if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord))
  831. currMaxWidth += wordSpacing;
  832. m_minWidth = max(currMinWidth, m_minWidth);
  833. m_maxWidth = max(currMaxWidth, m_maxWidth);
  834. if (!style()->autoWrap())
  835. m_minWidth = m_maxWidth;
  836. if (style()->whiteSpace() == PRE) {
  837. if (firstLine)
  838. m_beginMinWidth = m_maxWidth;
  839. m_endMinWidth = currMaxWidth;
  840. }
  841. setPreferredLogicalWidthsDirty(false);
  842. }
  843. bool RenderText::isAllCollapsibleWhitespace()
  844. {
  845. int length = textLength();
  846. const UChar* text = characters();
  847. for (int i = 0; i < length; i++) {
  848. if (!style()->isCollapsibleWhiteSpace(text[i]))
  849. return false;
  850. }
  851. return true;
  852. }
  853. bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const
  854. {
  855. ASSERT(m_text);
  856. StringImpl& text = *m_text.impl();
  857. unsigned currPos;
  858. for (currPos = from;
  859. currPos < from + len && (text[currPos] == '\n' || text[currPos] == ' ' || text[currPos] == '\t');
  860. currPos++) { }
  861. return currPos >= (from + len);
  862. }
  863. FloatPoint RenderText::firstRunOrigin() const
  864. {
  865. return IntPoint(firstRunX(), firstRunY());
  866. }
  867. float RenderText::firstRunX() const
  868. {
  869. return m_firstTextBox ? m_firstTextBox->m_x : 0;
  870. }
  871. float RenderText::firstRunY() const
  872. {
  873. return m_firstTextBox ? m_firstTextBox->m_y : 0;
  874. }
  875. void RenderText::setSelectionState(SelectionState state)
  876. {
  877. InlineTextBox* box;
  878. RenderObject::setSelectionState(state);
  879. if (state == SelectionStart || state == SelectionEnd || state == SelectionBoth) {
  880. int startPos, endPos;
  881. selectionStartEnd(startPos, endPos);
  882. if (selectionState() == SelectionStart) {
  883. endPos = textLength();
  884. // to handle selection from end of text to end of line
  885. if (startPos != 0 && startPos == endPos)
  886. startPos = endPos - 1;
  887. } else if (selectionState() == SelectionEnd)
  888. startPos = 0;
  889. for (box = firstTextBox(); box; box = box->nextTextBox()) {
  890. if (box->isSelected(startPos, endPos)) {
  891. RootInlineBox* line = box->root();
  892. if (line)
  893. line->setHasSelectedChildren(true);
  894. }
  895. }
  896. } else {
  897. for (box = firstTextBox(); box; box = box->nextTextBox()) {
  898. RootInlineBox* line = box->root();
  899. if (line)
  900. line->setHasSelectedChildren(state == SelectionInside);
  901. }
  902. }
  903. // The returned value can be null in case of an orphaned tree.
  904. if (RenderBlock* cb = containingBlock())
  905. cb->setSelectionState(state);
  906. }
  907. void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset, unsigned len, bool force)
  908. {
  909. unsigned oldLen = textLength();
  910. unsigned newLen = text->length();
  911. int delta = newLen - oldLen;
  912. unsigned end = len ? offset + len - 1 : offset;
  913. RootInlineBox* firstRootBox = 0;
  914. RootInlineBox* lastRootBox = 0;
  915. bool dirtiedLines = false;
  916. // Dirty all text boxes that include characters in between offset and offset+len.
  917. for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
  918. // Text run is entirely before the affected range.
  919. if (curr->end() < offset)
  920. continue;
  921. // Text run is entirely after the affected range.
  922. if (curr->start() > end) {
  923. curr->offsetRun(delta);
  924. RootInlineBox* root = curr->root();
  925. if (!firstRootBox) {
  926. firstRootBox = root;
  927. if (!dirtiedLines) {
  928. // The affected area was in between two runs. Go ahead and mark the root box of
  929. // the run after the affected area as dirty.
  930. firstRootBox->markDirty();
  931. dirtiedLines = true;
  932. }
  933. }
  934. lastRootBox = root;
  935. } else if (curr->end() >= offset && curr->end() <= end) {
  936. // Text run overlaps with the left end of the affected range.
  937. curr->dirtyLineBoxes();
  938. dirtiedLines = true;
  939. } else if (curr->start() <= offset && curr->end() >= end) {
  940. // Text run subsumes the affected range.
  941. curr->dirtyLineBoxes();
  942. dirtiedLines = true;
  943. } else if (curr->start() <= end && curr->end() >= end) {
  944. // Text run overlaps with right end of the affected range.
  945. curr->dirtyLineBoxes();
  946. dirtiedLines = true;
  947. }
  948. }
  949. // Now we have to walk all of the clean lines and adjust their cached line break information
  950. // to reflect our updated offsets.
  951. if (lastRootBox)
  952. lastRootBox = lastRootBox->nextRootBox();
  953. if (firstRootBox) {
  954. RootInlineBox* prev = firstRootBox->prevRootBox();
  955. if (prev)
  956. firstRootBox = prev;
  957. } else if (lastTextBox()) {
  958. ASSERT(!lastRootBox);
  959. firstRootBox = lastTextBox()->root();
  960. firstRootBox->markDirty();
  961. dirtiedLines = true;
  962. }
  963. for (RootInlineBox* curr = firstRootBox; curr && curr != lastRootBox; curr = curr->nextRootBox()) {
  964. if (curr->lineBreakObj() == this && curr->lineBreakPos() > end)
  965. curr->setLineBreakPos(curr->lineBreakPos() + delta);
  966. }
  967. // If the text node is empty, dirty the line where new text will be inserted.
  968. if (!firstTextBox() && parent()) {
  969. parent()->dirtyLinesFromChangedChild(this);
  970. dirtiedLines = true;
  971. }
  972. m_linesDirty = dirtiedLines;
  973. setText(text, force);
  974. }
  975. static inline bool isInlineFlowOrEmptyText(const RenderObject* o)
  976. {
  977. if (o->isRenderInline())
  978. return true;
  979. if (!o->isText())
  980. return false;
  981. StringImpl* text = toRenderText(o)->text();
  982. if (!text)
  983. return true;
  984. return !text->length();
  985. }
  986. UChar RenderText::previousCharacter() const
  987. {
  988. // find previous text renderer if one exists
  989. const RenderObject* previousText = this;
  990. while ((previousText = previousText->previousInPreOrder()))
  991. if (!isInlineFlowOrEmptyText(previousText))
  992. break;
  993. UChar prev = ' ';
  994. if (previousText && previousText->isText())
  995. if (StringImpl* previousString = toRenderText(previousText)->text())
  996. prev = (*previousString)[previousString->length() - 1];
  997. return prev;
  998. }
  999. void RenderText::transformText(String& text) const
  1000. {
  1001. ASSERT(style());
  1002. switch (style()->textTransform()) {
  1003. case TTNONE:
  1004. break;
  1005. case CAPITALIZE:
  1006. makeCapitalized(&text, previousCharacter());
  1007. break;
  1008. case UPPERCASE:
  1009. text.makeUpper();
  1010. break;
  1011. case LOWERCASE:
  1012. text.makeLower();
  1013. break;
  1014. }
  1015. }
  1016. void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
  1017. {
  1018. ASSERT(text);
  1019. m_text = text;
  1020. if (m_needsTranscoding) {
  1021. const TextEncoding* encoding = document()->decoder() ? &document()->decoder()->encoding() : 0;
  1022. fontTranscoder().convert(m_text, style()->font().fontDescription(), encoding);
  1023. }
  1024. ASSERT(m_text);
  1025. if (style()) {
  1026. transformText(m_text);
  1027. // We use the same characters here as for list markers.
  1028. // See the listMarkerText function in RenderListMarker.cpp.
  1029. switch (style()->textSecurity()) {
  1030. case TSNONE:
  1031. break;
  1032. case TSCIRCLE:
  1033. secureText(whiteBullet);
  1034. break;
  1035. case TSDISC:
  1036. secureText(bullet);
  1037. break;
  1038. case TSSQUARE:
  1039. secureText(blackSquare);
  1040. }
  1041. }
  1042. ASSERT(m_text);
  1043. ASSERT(!isBR() || (textLength() == 1 && m_text[0] == '\n'));
  1044. m_isAllASCII = m_text.containsOnlyASCII();
  1045. }
  1046. void RenderText::secureText(UChar mask)
  1047. {
  1048. if (!m_text.length())
  1049. return;
  1050. int lastTypedCharacterOffsetToReveal = -1;
  1051. String revealedText;
  1052. SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->get(this) : 0;
  1053. if (secureTextTimer && secureTextTimer->isActive()) {
  1054. lastTypedCharacterOffsetToReveal = secureTextTimer->lastTypedCharacterOffset();
  1055. if (lastTypedCharacterOffsetToReveal >= 0)
  1056. revealedText.append(m_text[lastTypedCharacterOffsetToReveal]);
  1057. }
  1058. m_text.fill(mask);
  1059. if (lastTypedCharacterOffsetToReveal >= 0) {
  1060. m_text.replace(lastTypedCharacterOffsetToReveal, 1, revealedText);
  1061. // m_text may be updated later before timer fires. We invalidate the lastTypedCharacterOffset to avoid inconsistency.
  1062. secureTextTimer->invalidate();
  1063. }
  1064. }
  1065. void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
  1066. {
  1067. ASSERT(text);
  1068. if (!force && equal(m_text.impl(), text.get()))
  1069. return;
  1070. setTextInternal(text);
  1071. setNeedsLayoutAndPrefWidthsRecalc();
  1072. m_knownToHaveNoOverflowAndNoFallbackFonts = false;
  1073. AXObjectCache* axObjectCache = document()->axObjectCache();
  1074. if (axObjectCache->accessibilityEnabled())
  1075. axObjectCache->contentChanged(this);
  1076. }
  1077. String RenderText::textWithoutTranscoding() const
  1078. {
  1079. // If m_text isn't transcoded or is secure, we can just return the modified text.
  1080. if (!m_needsTranscoding || style()->textSecurity() != TSNONE)
  1081. return text();
  1082. // Otherwise, we should use original text. If text-transform is
  1083. // specified, we should transform the text on the fly.
  1084. String text = originalText();
  1085. if (style())
  1086. transformText(text);
  1087. return text;
  1088. }
  1089. void RenderText::dirtyLineBoxes(bool fullLayout)
  1090. {
  1091. if (fullLayout)
  1092. deleteTextBoxes();
  1093. else if (!m_linesDirty) {
  1094. for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
  1095. box->dirtyLineBoxes();
  1096. }
  1097. m_linesDirty = false;
  1098. }
  1099. InlineTextBox* RenderText::createTextBox()
  1100. {
  1101. return new (renderArena()) InlineTextBox(this);
  1102. }
  1103. InlineTextBox* RenderText::createInlineTextBox()
  1104. {
  1105. InlineTextBox* textBox = createTextBox();
  1106. if (!m_firstTextBox)
  1107. m_firstTextBox = m_lastTextBox = textBox;
  1108. else {
  1109. m_lastTextBox->setNextTextBox(textBox);
  1110. textBox->setPreviousTextBox(m_lastTextBox);
  1111. m_lastTextBox = textBox;
  1112. }
  1113. textBox->setIsText(true);
  1114. return textBox;
  1115. }
  1116. void RenderText::positionLineBox(InlineBox* box)
  1117. {
  1118. InlineTextBox* s = static_cast<InlineTextBox*>(box);
  1119. // FIXME: should not be needed!!!
  1120. if (!s->len()) {
  1121. // We want the box to be destroyed.
  1122. s->remove();
  1123. if (m_firstTextBox == s)
  1124. m_firstTextBox = s->nextTextBox();
  1125. else
  1126. s->prevTextBox()->setNextTextBox(s->nextTextBox());
  1127. if (m_lastTextBox == s)
  1128. m_lastTextBox = s->prevTextBox();
  1129. else
  1130. s->nextTextBox()->setPreviousTextBox(s->prevTextBox());
  1131. s->destroy(renderArena());
  1132. return;
  1133. }
  1134. m_containsReversedText |= !s->isLeftToRightDirection();
  1135. }
  1136. float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
  1137. {
  1138. if (from >= textLength())
  1139. return 0;
  1140. if (from + len > textLength())
  1141. len = textLength() - from;
  1142. return width(from, len, style(firstLine)->font(), xPos, fallbackFonts, glyphOverflow);
  1143. }
  1144. float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
  1145. {
  1146. ASSERT(from + len <= textLength());
  1147. if (!characters())
  1148. return 0;
  1149. float w;
  1150. if (&f == &style()->font()) {
  1151. if (!style()->preserveNewline() && !from && len == textLength() && (!glyphOverflow || !glyphOverflow->computeBounds)) {
  1152. if (fallbackFonts) {
  1153. ASSERT(glyphOverflow);
  1154. if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts) {
  1155. const_cast<RenderText*>(this)->computePreferredLogicalWidths(0, *fallbackFonts, *glyphOverflow);
  1156. if (fallbackFonts->isEmpty() && !glyphOverflow->left && !glyphOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom)
  1157. m_knownToHaveNoOverflowAndNoFallbackFonts = true;
  1158. }
  1159. w = m_maxWidth;
  1160. } else
  1161. w = maxLogicalWidth();
  1162. } else
  1163. w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow);
  1164. } else
  1165. w = f.width(TextRun(text()->characters() + from, len, allowTabs(), xPos), fallbackFonts, glyphOverflow);
  1166. return w;
  1167. }
  1168. IntRect RenderText::linesBoundingBox() const
  1169. {
  1170. IntRect result;
  1171. ASSERT(!firstTextBox() == !lastTextBox()); // Either both are null or both exist.
  1172. if (firstTextBox() && lastTextBox()) {
  1173. // Return the width of the minimal left side and the maximal right side.
  1174. float logicalLeftSide = 0;
  1175. float logicalRightSide = 0;
  1176. for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
  1177. if (curr == firstTextBox() || curr->logicalLeft() < logicalLeftSide)
  1178. logicalLeftSide = curr->logicalLeft();
  1179. if (curr == firstTextBox() || curr->logicalRight() > logicalRightSide)
  1180. logicalRightSide = curr->logicalRight();
  1181. }
  1182. bool isHorizontal = style()->isHorizontalWritingMode();
  1183. float x = isHorizontal ? logicalLeftSide : firstTextBox()->x();
  1184. float y = isHorizontal ? firstTextBox()->y() : logicalLeftSide;
  1185. float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastTextBox()->logicalBottom() - x;
  1186. float height = isHorizontal ? lastTextBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
  1187. result = enclosingIntRect(FloatRect(x, y, width, height));
  1188. }
  1189. return result;
  1190. }
  1191. IntRect RenderText::linesVisualOverflowBoundingBox() const
  1192. {
  1193. if (!firstTextBox())
  1194. return IntRect();
  1195. // Return the width of the minimal left side and the maximal right side.
  1196. int logicalLeftSide = numeric_limits<int>::max();
  1197. int logicalRightSide = numeric_limits<int>::min();
  1198. for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
  1199. logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
  1200. logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
  1201. }
  1202. int logicalTop = firstTextBox()->logicalTopVisualOverflow();
  1203. int logicalWidth = logicalRightSide - logicalLeftSide;
  1204. int logicalHeight = lastTextBox()->logicalBottomVisualOverflow() - logicalTop;
  1205. IntRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
  1206. if (!style()->isHorizontalWritingMode())
  1207. rect = rect.transposedRect();
  1208. return rect;
  1209. }
  1210. IntRect RenderText::clippedOverflowRectForRepaint(RenderBoxModelObject* repaintContainer)
  1211. {
  1212. RenderObject* rendererToRepaint = containingBlock();
  1213. // Do not cross self-painting layer boundaries.
  1214. RenderObject* enclosingLayerRenderer = enclosingLayer()->renderer();
  1215. if (enclosingLayerRenderer != rendererToRepaint &&