1 /* 2 * (C) 1999 Lars Knoll (knoll (at) kde.org) 3 * (C) 2000 Dirk Mueller (mueller (at) kde.org) 4 * Copyright (C) 2004, 2005, 2006, 2009, 2010, 2011 Apple Inc. All rights reserved. 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Library General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Library General Public License for more details. 15 * 16 * You should have received a copy of the GNU Library General Public License 17 * along with this library; see the file COPYING.LIB. If not, write to 18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef InlineTextBox_h 24 #define InlineTextBox_h 25 26 #include "core/rendering/InlineBox.h" 27 #include "core/rendering/RenderText.h" // so textRenderer() can be inline 28 #include "platform/graphics/GraphicsContext.h" 29 #include "platform/text/TextRun.h" 30 #include "wtf/Forward.h" 31 32 namespace WebCore { 33 34 struct CompositionUnderline; 35 class DocumentMarker; 36 37 const unsigned short cNoTruncation = USHRT_MAX; 38 const unsigned short cFullTruncation = USHRT_MAX - 1; 39 40 // Helper functions shared by InlineTextBox / SVGRootInlineBox 41 void updateGraphicsContext(GraphicsContext*, const Color& fillColor, const Color& strokeColor, float strokeThickness, ColorSpace); 42 Color correctedTextColor(Color textColor, Color backgroundColor); 43 44 class InlineTextBox : public InlineBox { 45 public: 46 InlineTextBox(RenderObject* obj) 47 : InlineBox(obj) 48 , m_prevTextBox(0) 49 , m_nextTextBox(0) 50 , m_start(0) 51 , m_len(0) 52 , m_truncation(cNoTruncation) 53 { 54 } 55 56 virtual void destroy() OVERRIDE FINAL; 57 58 InlineTextBox* prevTextBox() const { return m_prevTextBox; } 59 InlineTextBox* nextTextBox() const { return m_nextTextBox; } 60 void setNextTextBox(InlineTextBox* n) { m_nextTextBox = n; } 61 void setPreviousTextBox(InlineTextBox* p) { m_prevTextBox = p; } 62 63 // FIXME: These accessors should ASSERT(!isDirty()). See https://bugs.webkit.org/show_bug.cgi?id=97264 64 unsigned start() const { return m_start; } 65 unsigned end() const { return m_len ? m_start + m_len - 1 : m_start; } 66 unsigned len() const { return m_len; } 67 68 void setStart(unsigned start) { m_start = start; } 69 void setLen(unsigned len) { m_len = len; } 70 71 void offsetRun(int d) { ASSERT(!isDirty()); m_start += d; } 72 73 unsigned short truncation() { return m_truncation; } 74 75 virtual void markDirty(bool dirty = true) OVERRIDE FINAL; 76 77 using InlineBox::hasHyphen; 78 using InlineBox::setHasHyphen; 79 using InlineBox::canHaveLeadingExpansion; 80 using InlineBox::setCanHaveLeadingExpansion; 81 82 static inline bool compareByStart(const InlineTextBox* first, const InlineTextBox* second) { return first->start() < second->start(); } 83 84 virtual int baselinePosition(FontBaseline) const OVERRIDE FINAL; 85 virtual LayoutUnit lineHeight() const OVERRIDE FINAL; 86 87 bool getEmphasisMarkPosition(RenderStyle*, TextEmphasisPosition&) const; 88 89 LayoutRect logicalOverflowRect() const; 90 void setLogicalOverflowRect(const LayoutRect&); 91 LayoutUnit logicalTopVisualOverflow() const { return logicalOverflowRect().y(); } 92 LayoutUnit logicalBottomVisualOverflow() const { return logicalOverflowRect().maxY(); } 93 LayoutUnit logicalLeftVisualOverflow() const { return logicalOverflowRect().x(); } 94 LayoutUnit logicalRightVisualOverflow() const { return logicalOverflowRect().maxX(); } 95 96 #ifndef NDEBUG 97 virtual void showBox(int = 0) const; 98 virtual const char* boxName() const; 99 #endif 100 101 enum RotationDirection { Counterclockwise, Clockwise }; 102 static AffineTransform rotation(const FloatRect& boxRect, RotationDirection); 103 private: 104 LayoutUnit selectionTop(); 105 LayoutUnit selectionBottom(); 106 LayoutUnit selectionHeight(); 107 108 // charactersWithHyphen, if provided, must not be destroyed before the TextRun. 109 TextRun constructTextRun(RenderStyle*, const Font&, StringBuilder* charactersWithHyphen = 0) const; 110 TextRun constructTextRun(RenderStyle*, const Font&, StringView, int maximumLength, StringBuilder* charactersWithHyphen = 0) const; 111 112 public: 113 TextRun constructTextRunForInspector(RenderStyle*, const Font&) const; 114 virtual FloatRect calculateBoundaries() const { return FloatRect(x(), y(), width(), height()); } 115 116 virtual LayoutRect localSelectionRect(int startPos, int endPos); 117 bool isSelected(int startPos, int endPos) const; 118 void selectionStartEnd(int& sPos, int& ePos); 119 120 protected: 121 virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom); 122 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE; 123 124 public: 125 RenderText* textRenderer() const; 126 127 private: 128 virtual void deleteLine() OVERRIDE FINAL; 129 virtual void extractLine() OVERRIDE FINAL; 130 virtual void attachLine() OVERRIDE FINAL; 131 132 public: 133 virtual RenderObject::SelectionState selectionState() OVERRIDE FINAL; 134 135 private: 136 virtual void clearTruncation() OVERRIDE FINAL { m_truncation = cNoTruncation; } 137 virtual float placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox) OVERRIDE FINAL; 138 139 public: 140 virtual bool isLineBreak() const OVERRIDE FINAL; 141 142 void setExpansion(int newExpansion) 143 { 144 m_logicalWidth -= expansion(); 145 InlineBox::setExpansion(newExpansion); 146 m_logicalWidth += newExpansion; 147 } 148 149 private: 150 virtual bool isInlineTextBox() const OVERRIDE FINAL { return true; } 151 152 public: 153 virtual int caretMinOffset() const OVERRIDE FINAL; 154 virtual int caretMaxOffset() const OVERRIDE FINAL; 155 156 private: 157 float textPos() const; // returns the x position relative to the left start of the text line. 158 159 public: 160 virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const; 161 virtual float positionForOffset(int offset) const; 162 163 bool containsCaretOffset(int offset) const; // false for offset after line break 164 165 // Fills a vector with the pixel width of each character. 166 void characterWidths(Vector<float>&) const; 167 168 private: 169 InlineTextBox* m_prevTextBox; // The previous box that also uses our RenderObject 170 InlineTextBox* m_nextTextBox; // The next box that also uses our RenderObject 171 172 int m_start; 173 unsigned short m_len; 174 175 unsigned short m_truncation; // Where to truncate when text overflow is applied. We use special constants to 176 // denote no truncation (the whole run paints) and full truncation (nothing paints at all). 177 178 protected: 179 void paintCompositionBackground(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, int startPos, int endPos); 180 void paintDocumentMarkers(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, bool background); 181 void paintCompositionUnderline(GraphicsContext*, const FloatPoint& boxOrigin, const CompositionUnderline&); 182 183 private: 184 void paintDecoration(GraphicsContext*, const FloatPoint& boxOrigin, TextDecoration, TextDecorationStyle, const ShadowList*); 185 void paintSelection(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, Color textColor); 186 void paintDocumentMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&, bool grammar); 187 void paintTextMatchMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&); 188 189 TextRun::ExpansionBehavior expansionBehavior() const 190 { 191 return (canHaveLeadingExpansion() ? TextRun::AllowLeadingExpansion : TextRun::ForbidLeadingExpansion) 192 | (expansion() && nextLeafChild() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion); 193 } 194 }; 195 196 DEFINE_INLINE_BOX_TYPE_CASTS(InlineTextBox); 197 198 inline RenderText* InlineTextBox::textRenderer() const 199 { 200 return toRenderText(renderer()); 201 } 202 203 void alignSelectionRectToDevicePixels(FloatRect&); 204 205 inline AffineTransform InlineTextBox::rotation(const FloatRect& boxRect, RotationDirection rotationDirection) 206 { 207 return rotationDirection == Clockwise ? AffineTransform(0, 1, -1, 0, boxRect.x() + boxRect.maxY(), boxRect.maxY() - boxRect.x()) 208 : AffineTransform(0, -1, 1, 0, boxRect.x() - boxRect.maxY(), boxRect.x() + boxRect.maxY()); 209 } 210 211 } // namespace WebCore 212 213 #endif // InlineTextBox_h 214