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"
15 class nsIScrollableFrame
;
23 * A class for rendering CSS3 text-overflow.
25 * 1. allocate an object using WillProcessLines
26 * 2. then call ProcessLine for each line you are building display lists for
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
);
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
);
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
; }
50 * @return true if aBlockFrmae has text-overflow:clip on both sides.
52 static bool HasClippedOverflow(nsIFrame
* aBlockFrame
);
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
;
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());
74 xmost
= aRect
.XMost();
78 nscoord
Width() { return xmost
- x
; }
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());
94 void AccumulateRight(const nsRect
& aRect
) {
95 if (MOZ_LIKELY(mAssignedRight
)) {
96 mRight
= std::min(mRight
, aRect
.XMost());
98 mRight
= aRect
.XMost();
99 mAssignedRight
= true;
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
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
,
192 const nsRect
& aInsideMarkersArea
);
195 nsDisplayListBuilder
* mBuilder
;
197 nsIScrollableFrame
* mScrollableFrame
;
198 nsDisplayList mMarkerList
;
200 bool mCanHaveHorizontalScrollbar
;
201 bool mAdjustForPixelSnapping
;
205 void Init(const nsStyleTextOverflowSide
& aStyle
) {
206 mInitialized
= false;
212 * Setup the marker string and calculate its size, if not done already.
214 void SetupString(nsIFrame
* aFrame
);
216 bool IsNeeded() const {
220 mHasOverflow
= false;
223 // The current width of the marker, the range is [0 .. mIntrinsicISize].
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.
231 // True if mMarkerString and mWidth have been setup from style.
233 // True if the style is text-overflow:clip on this side and the marker
234 // won't cause the line to become empty.
238 Marker mLeft
; // the horizontal left marker
239 Marker mRight
; // the horizontal right marker
243 } // namespace mozilla
245 #endif /* !defined(TextOverflow_h_) */