Bumping manifests a=b2g-bump
[gecko.git] / layout / generic / TextOverflow.h
blob3708f7e2f8490a1b996aca5974845436b31cfa8a
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef TextOverflow_h_
8 #define TextOverflow_h_
10 #include "nsDisplayList.h"
11 #include "nsTHashtable.h"
12 #include "mozilla/Likely.h"
13 #include <algorithm>
15 class nsIScrollableFrame;
16 class gfxTextRun;
17 class nsLineBox;
19 namespace mozilla {
20 namespace css {
22 /**
23 * A class for rendering CSS3 text-overflow.
24 * Usage:
25 * 1. allocate an object using WillProcessLines
26 * 2. then call ProcessLine for each line you are building display lists for
28 class TextOverflow {
29 public:
30 /**
31 * Allocate an object for text-overflow processing.
32 * @return nullptr if no processing is necessary. The caller owns the object.
34 static TextOverflow* WillProcessLines(nsDisplayListBuilder* aBuilder,
35 nsIFrame* aBlockFrame);
36 /**
37 * Analyze the display lists for text overflow and what kind of item is at
38 * the content edges. Add display items for text-overflow markers as needed
39 * and remove or clip items that would overlap a marker.
41 void ProcessLine(const nsDisplayListSet& aLists, nsLineBox* aLine);
43 /**
44 * Get the resulting text-overflow markers (the list may be empty).
45 * @return a DisplayList containing any text-overflow markers.
47 nsDisplayList& GetMarkers() { return mMarkerList; }
49 /**
50 * @return true if aBlockFrmae has text-overflow:clip on both sides.
52 static bool HasClippedOverflow(nsIFrame* aBlockFrame);
53 /**
54 * @return true if aBlockFrame needs analysis for text overflow.
56 static bool CanHaveTextOverflow(nsDisplayListBuilder* aBuilder,
57 nsIFrame* aBlockFrame);
59 typedef nsTHashtable<nsPtrHashKey<nsIFrame> > FrameHashtable;
61 protected:
62 TextOverflow() {}
63 void Init(nsDisplayListBuilder* aBuilder,
64 nsIFrame* aBlockFrame);
66 struct AlignmentEdges {
67 AlignmentEdges() : mAssigned(false) {}
68 void Accumulate(const nsRect& aRect) {
69 if (MOZ_LIKELY(mAssigned)) {
70 x = std::min(x, aRect.X());
71 xmost = std::max(xmost, aRect.XMost());
72 } else {
73 x = aRect.X();
74 xmost = aRect.XMost();
75 mAssigned = true;
78 nscoord Width() { return xmost - x; }
79 nscoord x;
80 nscoord xmost;
81 bool mAssigned;
84 struct InnerClipEdges {
85 InnerClipEdges() : mAssignedLeft(false), mAssignedRight(false) {}
86 void AccumulateLeft(const nsRect& aRect) {
87 if (MOZ_LIKELY(mAssignedLeft)) {
88 mLeft = std::max(mLeft, aRect.X());
89 } else {
90 mLeft = aRect.X();
91 mAssignedLeft = true;
94 void AccumulateRight(const nsRect& aRect) {
95 if (MOZ_LIKELY(mAssignedRight)) {
96 mRight = std::min(mRight, aRect.XMost());
97 } else {
98 mRight = aRect.XMost();
99 mAssignedRight = true;
102 nscoord mLeft;
103 nscoord mRight;
104 bool mAssignedLeft;
105 bool mAssignedRight;
109 * Examines frames on the line to determine whether we should draw a left
110 * and/or right marker, and if so, which frames should be completely hidden
111 * and the bounds of what will be displayed between the markers.
112 * @param aLine the line we're processing
113 * @param aFramesToHide frames that should have their display items removed
114 * @param aAlignmentEdges the outermost edges of all text and atomic
115 * inline-level frames that are inside the area between the markers
117 void ExamineLineFrames(nsLineBox* aLine,
118 FrameHashtable* aFramesToHide,
119 AlignmentEdges* aAlignmentEdges);
122 * LineHasOverflowingText calls this to analyze edges, both the block's
123 * content edges and the hypothetical marker edges aligned at the block edges.
124 * @param aFrame the descendant frame of mBlock that we're analyzing
125 * @param aContentArea the block's content area
126 * @param aInsideMarkersArea the rectangle between the markers
127 * @param aFramesToHide frames that should have their display items removed
128 * @param aAlignmentEdges the outermost edges of all text and atomic
129 * inline-level frames that are inside the area between the markers
130 * @param aFoundVisibleTextOrAtomic is set to true if a text or atomic
131 * inline-level frame is visible between the marker edges
132 * @param aClippedMarkerEdges the innermost edges of all text and atomic
133 * inline-level frames that are clipped by the current marker width
135 void ExamineFrameSubtree(nsIFrame* aFrame,
136 const nsRect& aContentArea,
137 const nsRect& aInsideMarkersArea,
138 FrameHashtable* aFramesToHide,
139 AlignmentEdges* aAlignmentEdges,
140 bool* aFoundVisibleTextOrAtomic,
141 InnerClipEdges* aClippedMarkerEdges);
144 * ExamineFrameSubtree calls this to analyze a frame against the hypothetical
145 * marker edges (aInsideMarkersArea) for text frames and atomic inline-level
146 * elements. A text frame adds its extent inside aInsideMarkersArea where
147 * grapheme clusters are fully visible. An atomic adds its border box if
148 * it's fully inside aInsideMarkersArea, otherwise the frame is added to
149 * aFramesToHide.
150 * @param aFrame the descendant frame of mBlock that we're analyzing
151 * @param aFrameType aFrame's frame type
152 * @param aInsideMarkersArea the rectangle between the markers
153 * @param aFramesToHide frames that should have their display items removed
154 * @param aAlignmentEdges the outermost edges of all text and atomic
155 * inline-level frames that are inside the area between the markers
156 * inside aInsideMarkersArea
157 * @param aFoundVisibleTextOrAtomic is set to true if a text or atomic
158 * inline-level frame is visible between the marker edges
159 * @param aClippedMarkerEdges the innermost edges of all text and atomic
160 * inline-level frames that are clipped by the current marker width
162 void AnalyzeMarkerEdges(nsIFrame* aFrame,
163 const nsIAtom* aFrameType,
164 const nsRect& aInsideMarkersArea,
165 FrameHashtable* aFramesToHide,
166 AlignmentEdges* aAlignmentEdges,
167 bool* aFoundVisibleTextOrAtomic,
168 InnerClipEdges* aClippedMarkerEdges);
171 * Clip or remove items given the final marker edges. ("clip" here just means
172 * assigning mLeftEdge/mRightEdge for any nsCharClipDisplayItem that needs it,
173 * see nsDisplayList.h for a description of that item).
174 * @param aFramesToHide remove display items for these frames
175 * @param aInsideMarkersArea is the area inside the markers
177 void PruneDisplayListContents(nsDisplayList* aList,
178 const FrameHashtable& aFramesToHide,
179 const nsRect& aInsideMarkersArea);
182 * ProcessLine calls this to create display items for the markers and insert
183 * them into mMarkerList.
184 * @param aLine the line we're processing
185 * @param aCreateLeft if true, create a marker on the left side
186 * @param aCreateRight if true, create a marker on the right side
187 * @param aInsideMarkersArea is the area inside the markers
189 void CreateMarkers(const nsLineBox* aLine,
190 bool aCreateLeft,
191 bool aCreateRight,
192 const nsRect& aInsideMarkersArea);
194 nsRect mContentArea;
195 nsDisplayListBuilder* mBuilder;
196 nsIFrame* mBlock;
197 nsIScrollableFrame* mScrollableFrame;
198 nsDisplayList mMarkerList;
199 bool mBlockIsRTL;
200 bool mCanHaveHorizontalScrollbar;
201 bool mAdjustForPixelSnapping;
203 class Marker {
204 public:
205 void Init(const nsStyleTextOverflowSide& aStyle) {
206 mInitialized = false;
207 mWidth = 0;
208 mStyle = &aStyle;
212 * Setup the marker string and calculate its size, if not done already.
214 void SetupString(nsIFrame* aFrame);
216 bool IsNeeded() const {
217 return mHasOverflow;
219 void Reset() {
220 mHasOverflow = false;
223 // The current width of the marker, the range is [0 .. mIntrinsicISize].
224 nscoord mWidth;
225 // The intrinsic width of the marker.
226 nscoord mIntrinsicISize;
227 // The style for this side.
228 const nsStyleTextOverflowSide* mStyle;
229 // True if there is visible overflowing inline content on this side.
230 bool mHasOverflow;
231 // True if mMarkerString and mWidth have been setup from style.
232 bool mInitialized;
233 // True if the style is text-overflow:clip on this side and the marker
234 // won't cause the line to become empty.
235 bool mActive;
238 Marker mLeft; // the horizontal left marker
239 Marker mRight; // the horizontal right marker
242 } // namespace css
243 } // namespace mozilla
245 #endif /* !defined(TextOverflow_h_) */