OLD | NEW |
1 /* | 1 /* |
2 * (C) 1999 Lars Knoll (knoll@kde.org) | 2 * (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 2000 Dirk Mueller (mueller@kde.org) | 3 * (C) 2000 Dirk Mueller (mueller@kde.org) |
4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. | 4 * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. |
5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) | 5 * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net) |
6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) | 6 * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com) |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Library General Public | 9 * modify it under the terms of the GNU Library General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 702 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 left = max(left, leftEdge); | 713 left = max(left, leftEdge); |
714 left = min(left, rootRight - caretWidth); | 714 left = min(left, rootRight - caretWidth); |
715 } else { | 715 } else { |
716 left = min(left, rightEdge - caretWidthRightOfOffset); | 716 left = min(left, rightEdge - caretWidthRightOfOffset); |
717 left = max(left, rootLeft); | 717 left = max(left, rootLeft); |
718 } | 718 } |
719 | 719 |
720 return style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth, h
eight) : IntRect(top, left, height, caretWidth); | 720 return style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth, h
eight) : IntRect(top, left, height, caretWidth); |
721 } | 721 } |
722 | 722 |
723 ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len
, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyp
hOverflow) const | 723 ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len
, float xPos, TextDirection textDirection, HashSet<const SimpleFontData*>* fallb
ackFonts, GlyphOverflow* glyphOverflow) const |
724 { | 724 { |
725 if (style()->hasTextCombine() && isCombineText()) { | 725 if (style()->hasTextCombine() && isCombineText()) { |
726 const RenderCombineText* combineText = toRenderCombineText(this); | 726 const RenderCombineText* combineText = toRenderCombineText(this); |
727 if (combineText->isCombined()) | 727 if (combineText->isCombined()) |
728 return combineText->combinedTextWidth(f); | 728 return combineText->combinedTextWidth(f); |
729 } | 729 } |
730 | 730 |
731 if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII && (!glyphOverflow
|| !glyphOverflow->computeBounds)) { | 731 if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII && (!glyphOverflow
|| !glyphOverflow->computeBounds)) { |
732 float monospaceCharacterWidth = f.spaceWidth(); | 732 float monospaceCharacterWidth = f.spaceWidth(); |
733 float w = 0; | 733 float w = 0; |
(...skipping 19 matching lines...) Expand all Loading... |
753 } else { | 753 } else { |
754 w += monospaceCharacterWidth; | 754 w += monospaceCharacterWidth; |
755 isSpace = false; | 755 isSpace = false; |
756 } | 756 } |
757 if (isSpace && i > start) | 757 if (isSpace && i > start) |
758 w += f.wordSpacing(); | 758 w += f.wordSpacing(); |
759 } | 759 } |
760 return w; | 760 return w; |
761 } | 761 } |
762 | 762 |
763 TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this
), f, this, start, len, style()); | 763 TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(this
), f, this, start, len, style(), textDirection); |
764 run.setCharactersLength(textLength() - start); | 764 run.setCharactersLength(textLength() - start); |
765 ASSERT(run.charactersLength() >= run.length()); | 765 ASSERT(run.charactersLength() >= run.length()); |
766 | 766 |
767 run.setCharacterScanForCodePath(!canUseSimpleFontCodePath()); | 767 run.setCharacterScanForCodePath(!canUseSimpleFontCodePath()); |
768 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); | 768 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); |
769 run.setXPos(xPos); | 769 run.setXPos(xPos); |
770 return f.width(run, fallbackFonts, glyphOverflow); | 770 return f.width(run, fallbackFonts, glyphOverflow); |
771 } | 771 } |
772 | 772 |
773 void RenderText::trimmedPrefWidths(float leadWidth, | 773 void RenderText::trimmedPrefWidths(float leadWidth, |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
832 const Font& f = style()->font(); // FIXME: This ignores first-line. | 832 const Font& f = style()->font(); // FIXME: This ignores first-line. |
833 bool firstLine = true; | 833 bool firstLine = true; |
834 firstLineMaxWidth = maxWidth; | 834 firstLineMaxWidth = maxWidth; |
835 lastLineMaxWidth = maxWidth; | 835 lastLineMaxWidth = maxWidth; |
836 for (int i = 0; i < len; i++) { | 836 for (int i = 0; i < len; i++) { |
837 int linelen = 0; | 837 int linelen = 0; |
838 while (i + linelen < len && text[i + linelen] != '\n') | 838 while (i + linelen < len && text[i + linelen] != '\n') |
839 linelen++; | 839 linelen++; |
840 | 840 |
841 if (linelen) { | 841 if (linelen) { |
842 lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + las
tLineMaxWidth, 0, 0); | 842 lastLineMaxWidth = widthFromCache(f, i, linelen, leadWidth + las
tLineMaxWidth, LTR, 0, 0); |
843 if (firstLine) { | 843 if (firstLine) { |
844 firstLine = false; | 844 firstLine = false; |
845 leadWidth = 0; | 845 leadWidth = 0; |
846 firstLineMaxWidth = lastLineMaxWidth; | 846 firstLineMaxWidth = lastLineMaxWidth; |
847 } | 847 } |
848 i += linelen; | 848 i += linelen; |
849 } else if (firstLine) { | 849 } else if (firstLine) { |
850 firstLineMaxWidth = 0; | 850 firstLineMaxWidth = 0; |
851 firstLine = false; | 851 firstLine = false; |
852 leadWidth = 0; | 852 leadWidth = 0; |
(...skipping 21 matching lines...) Expand all Loading... |
874 if (preferredLogicalWidthsDirty()) | 874 if (preferredLogicalWidthsDirty()) |
875 const_cast<RenderText*>(this)->computePreferredLogicalWidths(0); | 875 const_cast<RenderText*>(this)->computePreferredLogicalWidths(0); |
876 | 876 |
877 return m_maxWidth; | 877 return m_maxWidth; |
878 } | 878 } |
879 | 879 |
880 void RenderText::computePreferredLogicalWidths(float leadWidth) | 880 void RenderText::computePreferredLogicalWidths(float leadWidth) |
881 { | 881 { |
882 HashSet<const SimpleFontData*> fallbackFonts; | 882 HashSet<const SimpleFontData*> fallbackFonts; |
883 GlyphOverflow glyphOverflow; | 883 GlyphOverflow glyphOverflow; |
884 computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphOverflow); | 884 computePreferredLogicalWidths(leadWidth, LTR, fallbackFonts, glyphOverflow); |
885 if (fallbackFonts.isEmpty() && !glyphOverflow.left && !glyphOverflow.right &
& !glyphOverflow.top && !glyphOverflow.bottom) | 885 if (fallbackFonts.isEmpty() && !glyphOverflow.left && !glyphOverflow.right &
& !glyphOverflow.top && !glyphOverflow.bottom) |
886 m_knownToHaveNoOverflowAndNoFallbackFonts = true; | 886 m_knownToHaveNoOverflowAndNoFallbackFonts = true; |
887 } | 887 } |
888 | 888 |
889 static inline float hyphenWidth(RenderText* renderer, const Font& font) | 889 static inline float hyphenWidth(RenderText* renderer, const Font& font) |
890 { | 890 { |
891 RenderStyle* style = renderer->style(); | 891 RenderStyle* style = renderer->style(); |
892 return font.width(RenderBlockFlow::constructTextRun(renderer, font, style->h
yphenString().string(), style)); | 892 return font.width(RenderBlockFlow::constructTextRun(renderer, font, style->h
yphenString().string(), style)); |
893 } | 893 } |
894 | 894 |
895 void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const Si
mpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow) | 895 void RenderText::computePreferredLogicalWidths(float leadWidth, TextDirection te
xtDirection, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyph
Overflow) |
896 { | 896 { |
897 ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflow
AndNoFallbackFonts); | 897 ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflow
AndNoFallbackFonts); |
898 | 898 |
899 m_minWidth = 0; | 899 m_minWidth = 0; |
900 m_maxWidth = 0; | 900 m_maxWidth = 0; |
901 m_firstLineMinWidth = 0; | 901 m_firstLineMinWidth = 0; |
902 m_lastLineLineMinWidth = 0; | 902 m_lastLineLineMinWidth = 0; |
903 | 903 |
904 if (isBR()) | 904 if (isBR()) |
905 return; | 905 return; |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 | 972 |
973 if (ignoringSpaces && !isSpace) | 973 if (ignoringSpaces && !isSpace) |
974 ignoringSpaces = false; | 974 ignoringSpaces = false; |
975 | 975 |
976 // Ignore spaces and soft hyphens | 976 // Ignore spaces and soft hyphens |
977 if (ignoringSpaces) { | 977 if (ignoringSpaces) { |
978 ASSERT(lastWordBoundary == i); | 978 ASSERT(lastWordBoundary == i); |
979 lastWordBoundary++; | 979 lastWordBoundary++; |
980 continue; | 980 continue; |
981 } else if (c == softHyphen) { | 981 } else if (c == softHyphen) { |
982 currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoun
dary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow); | 982 currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoun
dary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOverflow); |
983 if (firstGlyphLeftOverflow < 0) | 983 if (firstGlyphLeftOverflow < 0) |
984 firstGlyphLeftOverflow = glyphOverflow.left; | 984 firstGlyphLeftOverflow = glyphOverflow.left; |
985 lastWordBoundary = i + 1; | 985 lastWordBoundary = i + 1; |
986 continue; | 986 continue; |
987 } | 987 } |
988 | 988 |
989 bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable)
; | 989 bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable)
; |
990 bool betweenWords = true; | 990 bool betweenWords = true; |
991 int j = i; | 991 int j = i; |
992 while (c != '\n' && c != ' ' && c != '\t' && (c != softHyphen)) { | 992 while (c != '\n' && c != ' ' && c != '\t' && (c != softHyphen)) { |
993 j++; | 993 j++; |
994 if (j == len) | 994 if (j == len) |
995 break; | 995 break; |
996 c = uncheckedCharacterAt(j); | 996 c = uncheckedCharacterAt(j); |
997 if (isBreakable(breakIterator, j, nextBreakable) && characterAt(j -
1) != softHyphen) | 997 if (isBreakable(breakIterator, j, nextBreakable) && characterAt(j -
1) != softHyphen) |
998 break; | 998 break; |
999 if (breakAll) { | 999 if (breakAll) { |
1000 betweenWords = false; | 1000 betweenWords = false; |
1001 break; | 1001 break; |
1002 } | 1002 } |
1003 } | 1003 } |
1004 | 1004 |
1005 int wordLen = j - i; | 1005 int wordLen = j - i; |
1006 if (wordLen) { | 1006 if (wordLen) { |
1007 bool isSpace = (j < len) && c == ' '; | 1007 bool isSpace = (j < len) && c == ' '; |
1008 float w; | 1008 float w; |
1009 if (wordTrailingSpaceWidth && isSpace) | 1009 if (wordTrailingSpaceWidth && isSpace) |
1010 w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth,
&fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth; | 1010 w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth,
textDirection, &fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth; |
1011 else { | 1011 else { |
1012 w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fal
lbackFonts, &glyphOverflow); | 1012 w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, text
Direction, &fallbackFonts, &glyphOverflow); |
1013 if (c == softHyphen) | 1013 if (c == softHyphen) |
1014 currMinWidth += hyphenWidth(this, f); | 1014 currMinWidth += hyphenWidth(this, f); |
1015 } | 1015 } |
1016 | 1016 |
1017 maxWordWidth = max(maxWordWidth, w); | 1017 maxWordWidth = max(maxWordWidth, w); |
1018 | 1018 |
1019 if (firstGlyphLeftOverflow < 0) | 1019 if (firstGlyphLeftOverflow < 0) |
1020 firstGlyphLeftOverflow = glyphOverflow.left; | 1020 firstGlyphLeftOverflow = glyphOverflow.left; |
1021 currMinWidth += w; | 1021 currMinWidth += w; |
1022 if (betweenWords) { | 1022 if (betweenWords) { |
1023 if (lastWordBoundary == i) | 1023 if (lastWordBoundary == i) |
1024 currMaxWidth += w; | 1024 currMaxWidth += w; |
1025 else | 1025 else |
1026 currMaxWidth += widthFromCache(f, lastWordBoundary, j - last
WordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow); | 1026 currMaxWidth += widthFromCache(f, lastWordBoundary, j - last
WordBoundary, leadWidth + currMaxWidth, textDirection, &fallbackFonts, &glyphOve
rflow); |
1027 lastWordBoundary = j; | 1027 lastWordBoundary = j; |
1028 } | 1028 } |
1029 | 1029 |
1030 bool isCollapsibleWhiteSpace = (j < len) && styleToUse->isCollapsibl
eWhiteSpace(c); | 1030 bool isCollapsibleWhiteSpace = (j < len) && styleToUse->isCollapsibl
eWhiteSpace(c); |
1031 if (j < len && styleToUse->autoWrap()) | 1031 if (j < len && styleToUse->autoWrap()) |
1032 m_hasBreakableChar = true; | 1032 m_hasBreakableChar = true; |
1033 | 1033 |
1034 // Add in wordSpacing to our currMaxWidth, but not if this is the la
st word on a line or the | 1034 // Add in wordSpacing to our currMaxWidth, but not if this is the la
st word on a line or the |
1035 // last word in the run. | 1035 // last word in the run. |
1036 if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && !contains
OnlyWhitespace(j, len-j)) | 1036 if (wordSpacing && (isSpace || isCollapsibleWhiteSpace) && !contains
OnlyWhitespace(j, len-j)) |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1438 m_lastTextBox = s->prevTextBox(); | 1438 m_lastTextBox = s->prevTextBox(); |
1439 else | 1439 else |
1440 s->nextTextBox()->setPreviousTextBox(s->prevTextBox()); | 1440 s->nextTextBox()->setPreviousTextBox(s->prevTextBox()); |
1441 s->destroy(); | 1441 s->destroy(); |
1442 return; | 1442 return; |
1443 } | 1443 } |
1444 | 1444 |
1445 m_containsReversedText |= !s->isLeftToRightDirection(); | 1445 m_containsReversedText |= !s->isLeftToRightDirection(); |
1446 } | 1446 } |
1447 | 1447 |
1448 float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine,
HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) co
nst | 1448 float RenderText::width(unsigned from, unsigned len, float xPos, TextDirection t
extDirection, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, Gly
phOverflow* glyphOverflow) const |
1449 { | 1449 { |
1450 if (from >= textLength()) | 1450 if (from >= textLength()) |
1451 return 0; | 1451 return 0; |
1452 | 1452 |
1453 if (from + len > textLength()) | 1453 if (from + len > textLength()) |
1454 len = textLength() - from; | 1454 len = textLength() - from; |
1455 | 1455 |
1456 return width(from, len, style(firstLine)->font(), xPos, fallbackFonts, glyph
Overflow); | 1456 return width(from, len, style(firstLine)->font(), xPos, textDirection, fallb
ackFonts, glyphOverflow); |
1457 } | 1457 } |
1458 | 1458 |
1459 float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos,
HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) con
st | 1459 float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos,
TextDirection textDirection, HashSet<const SimpleFontData*>* fallbackFonts, Glyp
hOverflow* glyphOverflow) const |
1460 { | 1460 { |
1461 ASSERT(from + len <= textLength()); | 1461 ASSERT(from + len <= textLength()); |
1462 if (!textLength()) | 1462 if (!textLength()) |
1463 return 0; | 1463 return 0; |
1464 | 1464 |
1465 float w; | 1465 float w; |
1466 if (&f == &style()->font()) { | 1466 if (&f == &style()->font()) { |
1467 if (!style()->preserveNewline() && !from && len == textLength() && (!gly
phOverflow || !glyphOverflow->computeBounds)) { | 1467 if (!style()->preserveNewline() && !from && len == textLength() && (!gly
phOverflow || !glyphOverflow->computeBounds)) { |
1468 if (fallbackFonts) { | 1468 if (fallbackFonts) { |
1469 ASSERT(glyphOverflow); | 1469 ASSERT(glyphOverflow); |
1470 if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAnd
NoFallbackFonts) { | 1470 if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAnd
NoFallbackFonts) { |
1471 const_cast<RenderText*>(this)->computePreferredLogicalWidths
(0, *fallbackFonts, *glyphOverflow); | 1471 const_cast<RenderText*>(this)->computePreferredLogicalWidths
(0, textDirection, *fallbackFonts, *glyphOverflow); |
1472 if (fallbackFonts->isEmpty() && !glyphOverflow->left && !gly
phOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom) | 1472 if (fallbackFonts->isEmpty() && !glyphOverflow->left && !gly
phOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom) |
1473 m_knownToHaveNoOverflowAndNoFallbackFonts = true; | 1473 m_knownToHaveNoOverflowAndNoFallbackFonts = true; |
1474 } | 1474 } |
1475 w = m_maxWidth; | 1475 w = m_maxWidth; |
1476 } else | 1476 } else |
1477 w = maxLogicalWidth(); | 1477 w = maxLogicalWidth(); |
1478 } else | 1478 } else { |
1479 w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow)
; | 1479 w = widthFromCache(f, from, len, xPos, textDirection, fallbackFonts,
glyphOverflow); |
| 1480 } |
1480 } else { | 1481 } else { |
1481 TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(
this), f, this, from, len, style()); | 1482 TextRun run = RenderBlockFlow::constructTextRun(const_cast<RenderText*>(
this), f, this, from, len, style(), textDirection); |
1482 run.setCharactersLength(textLength() - from); | 1483 run.setCharactersLength(textLength() - from); |
1483 ASSERT(run.charactersLength() >= run.length()); | 1484 ASSERT(run.charactersLength() >= run.length()); |
1484 | 1485 |
1485 run.setCharacterScanForCodePath(!canUseSimpleFontCodePath()); | 1486 run.setCharacterScanForCodePath(!canUseSimpleFontCodePath()); |
1486 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); | 1487 run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize()); |
1487 run.setXPos(xPos); | 1488 run.setXPos(xPos); |
1488 w = f.width(run, fallbackFonts, glyphOverflow); | 1489 w = f.width(run, fallbackFonts, glyphOverflow); |
1489 } | 1490 } |
1490 | 1491 |
1491 return w; | 1492 return w; |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1841 } | 1842 } |
1842 secureTextTimer->restartWithNewText(lastTypedCharacterOffset); | 1843 secureTextTimer->restartWithNewText(lastTypedCharacterOffset); |
1843 } | 1844 } |
1844 | 1845 |
1845 PassRefPtr<AbstractInlineTextBox> RenderText::firstAbstractInlineTextBox() | 1846 PassRefPtr<AbstractInlineTextBox> RenderText::firstAbstractInlineTextBox() |
1846 { | 1847 { |
1847 return AbstractInlineTextBox::getOrCreate(this, m_firstTextBox); | 1848 return AbstractInlineTextBox::getOrCreate(this, m_firstTextBox); |
1848 } | 1849 } |
1849 | 1850 |
1850 } // namespace WebCore | 1851 } // namespace WebCore |
OLD | NEW |