1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsHTMLReflowMetrics.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,333 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* struct containing the output from nsIFrame::Reflow */ 1.10 + 1.11 +#ifndef nsHTMLReflowMetrics_h___ 1.12 +#define nsHTMLReflowMetrics_h___ 1.13 + 1.14 +#include "nsRect.h" 1.15 +#include "nsBoundingMetrics.h" 1.16 +#include "WritingModes.h" 1.17 + 1.18 +//---------------------------------------------------------------------- 1.19 + 1.20 +class nsHTMLReflowState; 1.21 + 1.22 +// Option flags 1.23 +#define NS_REFLOW_CALC_BOUNDING_METRICS 0x0001 1.24 + 1.25 +/** 1.26 + * When we store overflow areas as an array of scrollable and visual 1.27 + * overflow, we use these indices. 1.28 + * 1.29 + * eOverflowType_LENGTH is needed (for gcc 4.5.*, at least) to ensure 1.30 + * that 2 is a valid value of nsOverflowType for use in 1.31 + * NS_FOR_FRAME_OVERFLOW_TYPES. 1.32 + */ 1.33 +enum nsOverflowType { eVisualOverflow, eScrollableOverflow, 1.34 + eOverflowType_LENGTH }; 1.35 + 1.36 +#define NS_FOR_FRAME_OVERFLOW_TYPES(var_) \ 1.37 + for (nsOverflowType var_ = nsOverflowType(0); var_ < 2; \ 1.38 + var_ = nsOverflowType(var_ + 1)) 1.39 + 1.40 +struct nsOverflowAreas { 1.41 +private: 1.42 + nsRect mRects[2]; 1.43 +public: 1.44 + nsRect& Overflow(size_t aIndex) { 1.45 + NS_ASSERTION(aIndex < 2, "index out of range"); 1.46 + return mRects[aIndex]; 1.47 + } 1.48 + const nsRect& Overflow(size_t aIndex) const { 1.49 + NS_ASSERTION(aIndex < 2, "index out of range"); 1.50 + return mRects[aIndex]; 1.51 + } 1.52 + 1.53 + nsRect& VisualOverflow() { return mRects[eVisualOverflow]; } 1.54 + const nsRect& VisualOverflow() const { return mRects[eVisualOverflow]; } 1.55 + 1.56 + nsRect& ScrollableOverflow() { return mRects[eScrollableOverflow]; } 1.57 + const nsRect& ScrollableOverflow() const { return mRects[eScrollableOverflow]; } 1.58 + 1.59 + nsOverflowAreas() { 1.60 + // default-initializes to zero due to nsRect's default constructor 1.61 + } 1.62 + 1.63 + nsOverflowAreas(const nsRect& aVisualOverflow, 1.64 + const nsRect& aScrollableOverflow) 1.65 + { 1.66 + mRects[eVisualOverflow] = aVisualOverflow; 1.67 + mRects[eScrollableOverflow] = aScrollableOverflow; 1.68 + } 1.69 + 1.70 + nsOverflowAreas(const nsOverflowAreas& aOther) { 1.71 + *this = aOther; 1.72 + } 1.73 + 1.74 + nsOverflowAreas& operator=(const nsOverflowAreas& aOther) { 1.75 + mRects[0] = aOther.mRects[0]; 1.76 + mRects[1] = aOther.mRects[1]; 1.77 + return *this; 1.78 + } 1.79 + 1.80 + bool operator==(const nsOverflowAreas& aOther) const { 1.81 + // Scrollable overflow is a point-set rectangle and visual overflow 1.82 + // is a pixel-set rectangle. 1.83 + return VisualOverflow().IsEqualInterior(aOther.VisualOverflow()) && 1.84 + ScrollableOverflow().IsEqualEdges(aOther.ScrollableOverflow()); 1.85 + } 1.86 + 1.87 + bool operator!=(const nsOverflowAreas& aOther) const { 1.88 + return !(*this == aOther); 1.89 + } 1.90 + 1.91 + nsOverflowAreas operator+(const nsPoint& aPoint) const { 1.92 + nsOverflowAreas result(*this); 1.93 + result += aPoint; 1.94 + return result; 1.95 + } 1.96 + 1.97 + nsOverflowAreas& operator+=(const nsPoint& aPoint) { 1.98 + mRects[0] += aPoint; 1.99 + mRects[1] += aPoint; 1.100 + return *this; 1.101 + } 1.102 + 1.103 + void Clear() { 1.104 + mRects[0].SetRect(0, 0, 0, 0); 1.105 + mRects[1].SetRect(0, 0, 0, 0); 1.106 + } 1.107 + 1.108 + // Mutates |this| by unioning both overflow areas with |aOther|. 1.109 + void UnionWith(const nsOverflowAreas& aOther); 1.110 + 1.111 + // Mutates |this| by unioning both overflow areas with |aRect|. 1.112 + void UnionAllWith(const nsRect& aRect); 1.113 + 1.114 + // Mutates |this| by setting both overflow areas to |aRect|. 1.115 + void SetAllTo(const nsRect& aRect); 1.116 +}; 1.117 + 1.118 +/** 1.119 + * An nsCollapsingMargin represents a vertical collapsing margin between 1.120 + * blocks as described in section 8.3.1 of CSS2, 1.121 + * <URL: http://www.w3.org/TR/REC-CSS2/box.html#collapsing-margins >. 1.122 + * 1.123 + * All adjacent vertical margins collapse, and the resulting margin is 1.124 + * the sum of the largest positive margin included and the smallest (most 1.125 + * negative) negative margin included. 1.126 + */ 1.127 +struct nsCollapsingMargin { 1.128 + private: 1.129 + nscoord mMostPos; // the largest positive margin included 1.130 + nscoord mMostNeg; // the smallest negative margin included 1.131 + 1.132 + public: 1.133 + nsCollapsingMargin() 1.134 + : mMostPos(0), 1.135 + mMostNeg(0) 1.136 + { 1.137 + } 1.138 + 1.139 + nsCollapsingMargin(const nsCollapsingMargin& aOther) 1.140 + : mMostPos(aOther.mMostPos), 1.141 + mMostNeg(aOther.mMostNeg) 1.142 + { 1.143 + } 1.144 + 1.145 + bool operator==(const nsCollapsingMargin& aOther) 1.146 + { 1.147 + return mMostPos == aOther.mMostPos && 1.148 + mMostNeg == aOther.mMostNeg; 1.149 + } 1.150 + 1.151 + bool operator!=(const nsCollapsingMargin& aOther) 1.152 + { 1.153 + return !(*this == aOther); 1.154 + } 1.155 + 1.156 + nsCollapsingMargin& operator=(const nsCollapsingMargin& aOther) 1.157 + { 1.158 + mMostPos = aOther.mMostPos; 1.159 + mMostNeg = aOther.mMostNeg; 1.160 + return *this; 1.161 + } 1.162 + 1.163 + void Include(nscoord aCoord) 1.164 + { 1.165 + if (aCoord > mMostPos) 1.166 + mMostPos = aCoord; 1.167 + else if (aCoord < mMostNeg) 1.168 + mMostNeg = aCoord; 1.169 + } 1.170 + 1.171 + void Include(const nsCollapsingMargin& aOther) 1.172 + { 1.173 + if (aOther.mMostPos > mMostPos) 1.174 + mMostPos = aOther.mMostPos; 1.175 + if (aOther.mMostNeg < mMostNeg) 1.176 + mMostNeg = aOther.mMostNeg; 1.177 + } 1.178 + 1.179 + void Zero() 1.180 + { 1.181 + mMostPos = 0; 1.182 + mMostNeg = 0; 1.183 + } 1.184 + 1.185 + bool IsZero() const 1.186 + { 1.187 + return (mMostPos == 0) && (mMostNeg == 0); 1.188 + } 1.189 + 1.190 + nscoord get() const 1.191 + { 1.192 + return mMostPos + mMostNeg; 1.193 + } 1.194 +}; 1.195 + 1.196 +/** 1.197 + * Reflow metrics used to return the frame's desired size and alignment 1.198 + * information. 1.199 + * 1.200 + * @see #Reflow() 1.201 + */ 1.202 +class nsHTMLReflowMetrics { 1.203 +public: 1.204 + // XXXldb Should |aFlags| generally be passed from parent to child? 1.205 + // Some places do it, and some don't. |aFlags| should perhaps go away 1.206 + // entirely. 1.207 + // XXX width/height/ascent are OUT parameters and so they shouldn't 1.208 + // have to be initialized, but there are some bad frame classes that 1.209 + // aren't properly setting them when returning from Reflow()... 1.210 + nsHTMLReflowMetrics(mozilla::WritingMode aWritingMode, uint32_t aFlags = 0) 1.211 + : mISize(0) 1.212 + , mBSize(0) 1.213 + , mBlockStartAscent(ASK_FOR_BASELINE) 1.214 + , mFlags(aFlags) 1.215 + , mWritingMode(aWritingMode) 1.216 + {} 1.217 + 1.218 + nsHTMLReflowMetrics(const nsHTMLReflowState& aState, uint32_t aFlags = 0); 1.219 + 1.220 + // ISize and BSize are logical-coordinate dimensions: 1.221 + // ISize is the size in the writing mode's inline direction (which equates to 1.222 + // width in horizontal writing modes, height in vertical ones), and BSize is 1.223 + // the size in the block-progression direction. 1.224 + nscoord ISize() const { return mISize; } 1.225 + nscoord BSize() const { return mBSize; } 1.226 + 1.227 + nscoord& ISize() { return mISize; } 1.228 + nscoord& BSize() { return mBSize; } 1.229 + 1.230 + // Width and Height are physical dimensions, independent of writing mode. 1.231 + // Accessing these is slightly more expensive than accessing the logical 1.232 + // dimensions (once vertical writing mode support is enabled); as far as 1.233 + // possible, client code should work purely with logical dimensions. 1.234 + nscoord Width() const { return mWritingMode.IsVertical() ? mBSize : mISize; } 1.235 + nscoord Height() const { return mWritingMode.IsVertical() ? mISize : mBSize; } 1.236 + 1.237 + // It's only meaningful to consider "ascent" on the block-start side of the 1.238 + // frame; asking for the "ascent" on any other side will just return zero. 1.239 + nscoord TopAscent() const 1.240 + { 1.241 + return mWritingMode.IsVertical() ? 0 : mBlockStartAscent; 1.242 + } 1.243 + nscoord LeftAscent() const 1.244 + { 1.245 + return mWritingMode.IsVertical() && mWritingMode.IsVerticalLR() ? 1.246 + mBlockStartAscent : 0; 1.247 + } 1.248 + nscoord RightAscent() const 1.249 + { 1.250 + return mWritingMode.IsVertical() && !mWritingMode.IsVerticalLR() ? 1.251 + mBlockStartAscent : 0; 1.252 + } 1.253 + 1.254 + nscoord& Width() { return mWritingMode.IsVertical() ? mBSize : mISize; } 1.255 + nscoord& Height() { return mWritingMode.IsVertical() ? mISize : mBSize; } 1.256 + 1.257 + // To set the ascent value, we must be sure we're working with the correct 1.258 + // writing mode, so either pass it to the logical setter... 1.259 + void SetBlockStartAscent(mozilla::WritingMode aWritingMode, nscoord aAscent) 1.260 + { 1.261 + NS_ASSERTION(aWritingMode == mWritingMode, "writing mode mismatch"); 1.262 + mBlockStartAscent = aAscent; 1.263 + } 1.264 + // ...or call the appropriate physical setter (these will probably be removed 1.265 + // eventually). 1.266 + void SetTopAscent(nscoord aAscent) 1.267 + { 1.268 + NS_ASSERTION(!mWritingMode.IsVertical(), "writing mode mismatch"); 1.269 + mBlockStartAscent = aAscent; 1.270 + } 1.271 + void SetLeftAscent(nscoord aAscent) 1.272 + { 1.273 + NS_ASSERTION(mWritingMode.IsVertical() && mWritingMode.IsVerticalLR(), 1.274 + "writing mode mismatch"); 1.275 + mBlockStartAscent = aAscent; 1.276 + } 1.277 + void SetRightAscent(nscoord aAscent) 1.278 + { 1.279 + NS_ASSERTION(mWritingMode.IsVertical() && !mWritingMode.IsVerticalLR(), 1.280 + "writing mode mismatch"); 1.281 + mBlockStartAscent = aAscent; 1.282 + } 1.283 + 1.284 + enum { ASK_FOR_BASELINE = nscoord_MAX }; 1.285 + 1.286 + // Metrics that _exactly_ enclose the text to allow precise MathML placements. 1.287 + // If the NS_REFLOW_CALC_BOUNDING_METRICS flag is set, then the caller is 1.288 + // requesting that you also compute additional details about your inner 1.289 + // bounding box and italic correction. For example, the bounding box of 1.290 + // msup is the smallest rectangle that _exactly_ encloses both the text 1.291 + // of the base and the text of the superscript. 1.292 + nsBoundingMetrics mBoundingMetrics; // [OUT] 1.293 + 1.294 + // Carried out bottom margin values. This is the collapsed 1.295 + // (generational) bottom margin value. 1.296 + nsCollapsingMargin mCarriedOutBottomMargin; 1.297 + 1.298 + // For frames that have content that overflow their content area 1.299 + // (HasOverflowAreas() is true) these rectangles represent the total 1.300 + // area of the frame including visible overflow, i.e., don't include 1.301 + // overflowing content that is hidden. The rects are in the local 1.302 + // coordinate space of the frame, and should be at least as big as the 1.303 + // desired size. If there is no content that overflows, then the 1.304 + // overflow area is identical to the desired size and should be {0, 0, 1.305 + // width, height}. 1.306 + nsOverflowAreas mOverflowAreas; 1.307 + 1.308 + nsRect& VisualOverflow() 1.309 + { return mOverflowAreas.VisualOverflow(); } 1.310 + const nsRect& VisualOverflow() const 1.311 + { return mOverflowAreas.VisualOverflow(); } 1.312 + nsRect& ScrollableOverflow() 1.313 + { return mOverflowAreas.ScrollableOverflow(); } 1.314 + const nsRect& ScrollableOverflow() const 1.315 + { return mOverflowAreas.ScrollableOverflow(); } 1.316 + 1.317 + // Set all of mOverflowAreas to (0, 0, width, height). 1.318 + void SetOverflowAreasToDesiredBounds(); 1.319 + 1.320 + // Union all of mOverflowAreas with (0, 0, width, height). 1.321 + void UnionOverflowAreasWithDesiredBounds(); 1.322 + 1.323 + mozilla::WritingMode GetWritingMode() const { return mWritingMode; } 1.324 + 1.325 +private: 1.326 + nscoord mISize, mBSize; // [OUT] desired width and height (border-box) 1.327 + nscoord mBlockStartAscent; // [OUT] baseline (in Block direction), or ASK_FOR_BASELINE 1.328 + 1.329 +public: 1.330 + uint32_t mFlags; 1.331 + 1.332 +private: 1.333 + mozilla::WritingMode mWritingMode; 1.334 +}; 1.335 + 1.336 +#endif /* nsHTMLReflowMetrics_h___ */