static void AdjustRangeForSelection(nsIContent* aRoot, nsINode** aNode, PRInt32* aOffset) { nsINode* node = *aNode; PRInt32 offset = *aOffset; if (aRoot != node && node->GetParent() && !node->IsNodeOfType(nsINode::eTEXT)) { node = node->GetParent(); offset = node->IndexOf(*aNode) + (offset ? 1 : 0); } nsIContent* brContent = node->GetChildAt(offset - 1); while (brContent && brContent->IsHTML()) { if (brContent->Tag() != nsGkAtoms::br || IsContentBR(brContent)) break; brContent = node->GetChildAt(--offset - 1); } *aNode = node; *aOffset = NS_MAX(offset, 0); }
PRBool nsAttrValue::ParseIntWithBounds(const nsAString& aString, PRInt32 aMin, PRInt32 aMax) { NS_PRECONDITION(aMin < aMax, "bad boundaries"); ResetIfSet(); PRInt32 ec; PRBool strict; PRInt32 originalVal = StringToInteger(aString, &strict, &ec); if (NS_FAILED(ec)) { return PR_FALSE; } PRInt32 val = NS_MAX(originalVal, aMin); val = NS_MIN(val, aMax); strict = strict && (originalVal == val); SetIntValueAndType(val, eInteger, strict ? nsnull : &aString); return PR_TRUE; }
nsresult FileManager::Load(mozIStorageConnection* aConnection) { NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); nsCOMPtr<mozIStorageStatement> stmt; nsresult rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT id, refcount " "FROM file" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); bool hasResult; while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) { PRInt64 id; rv = stmt->GetInt64(0, &id); NS_ENSURE_SUCCESS(rv, rv); PRInt32 refcount; rv = stmt->GetInt32(1, &refcount); NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(refcount, "This shouldn't happen!"); nsRefPtr<FileInfo> fileInfo = FileInfo::Create(this, id); fileInfo->mDBRefCnt = refcount; if (!mFileInfos.Put(id, fileInfo)) { NS_WARNING("Out of memory?"); return NS_ERROR_OUT_OF_MEMORY; } mLastFileId = NS_MAX(id, mLastFileId); } mLoaded = true; return NS_OK; }
NS_IMETHODIMP nsListBoxBodyFrame::DoLayout(nsBoxLayoutState& aBoxLayoutState) { if (mScrolling) aBoxLayoutState.SetPaintingDisabled(true); nsresult rv = nsBoxFrame::DoLayout(aBoxLayoutState); // determine the real height for the scrollable area from the total number // of rows, since non-visible rows don't yet have frames nsRect rect(nsPoint(0, 0), GetSize()); nsOverflowAreas overflow(rect, rect); if (mLayoutManager) { nsIFrame* childFrame = mFrames.FirstChild(); while (childFrame) { ConsiderChildOverflow(overflow, childFrame); childFrame = childFrame->GetNextSibling(); } nsSize prefSize = mLayoutManager->GetPrefSize(this, aBoxLayoutState); NS_FOR_FRAME_OVERFLOW_TYPES(otype) { nsRect& o = overflow.Overflow(otype); o.height = NS_MAX(o.height, prefSize.height); } } FinishAndStoreOverflow(overflow, GetSize()); if (mScrolling) aBoxLayoutState.SetPaintingDisabled(false); // if we are scrolled and the row height changed // make sure we are scrolled to a correct index. if (mAdjustScroll) PostReflowCallback(); return rv; }
void nsDOMWorkerTimeout::Suspend() { AutoSpinlock lock(this); NS_ASSERTION(!IsSuspendedNoLock(), "Bad state!"); mIsSuspended = PR_TRUE; mSuspendedRef = this; if (!mStarted) { mSuspendedBeforeStart = PR_TRUE; return; } mTimer->Cancel(); mSuspendInterval = NS_MAX(0, PRInt32(mTargetTime - PR_Now())) / (PRTime)PR_USEC_PER_MSEC; LOG(("Worker [0x%p] suspending timeout [0x%p] with id %u (interval = %u)", static_cast<void*>(mWorker.get()), static_cast<void*>(this), mId, mSuspendInterval)); }
// exported routine that both munder and msub share. // munder uses this when movablelimits is set. nsresult nsMathMLmsubFrame::PlaceSubScript (nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, bool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize, nsMathMLContainerFrame* aFrame, nscoord aUserSubScriptShift, nscoord aScriptSpace) { // force the scriptSpace to be atleast 1 pixel aScriptSpace = NS_MAX(nsPresContext::CSSPixelsToAppUnits(1), aScriptSpace); //////////////////////////////////// // Get the children's desired sizes nsBoundingMetrics bmBase, bmSubScript; nsHTMLReflowMetrics baseSize; nsHTMLReflowMetrics subScriptSize; nsIFrame* baseFrame = aFrame->GetFirstPrincipalChild(); nsIFrame* subScriptFrame = nullptr; if (baseFrame) subScriptFrame = baseFrame->GetNextSibling(); if (!baseFrame || !subScriptFrame || subScriptFrame->GetNextSibling()) { // report an error, encourage people to get their markups in order if (aPlaceOrigin) { aFrame->ReportChildCountError(); } return aFrame->ReflowError(aRenderingContext, aDesiredSize); } GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); // get the subdrop from the subscript font nscoord subDrop; GetSubDropFromChild(subScriptFrame, subDrop); // parameter v, Rule 18a, App. G, TeXbook nscoord minSubScriptShift = bmBase.descent + subDrop; ////////////////// // Place Children // get min subscript shift limit from x-height // = h(x) - 4/5 * sigma_5, Rule 18b, App. G, TeXbook nscoord xHeight = 0; nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(baseFrame, getter_AddRefs(fm)); xHeight = fm->XHeight(); nscoord minShiftFromXHeight = (nscoord) (bmSubScript.ascent - (4.0f/5.0f) * xHeight); // subScriptShift // = minimum amount to shift the subscript down set by user or from the font // = sub1 in TeX // = subscriptshift attribute * x-height nscoord subScriptShift, dummy; // get subScriptShift default from font GetSubScriptShifts (fm, subScriptShift, dummy); subScriptShift = NS_MAX(subScriptShift, aUserSubScriptShift); // get actual subscriptshift to be used // Rule 18b, App. G, TeXbook nscoord actualSubScriptShift = NS_MAX(minSubScriptShift,NS_MAX(subScriptShift,minShiftFromXHeight)); // get bounding box for base + subscript nsBoundingMetrics boundingMetrics; boundingMetrics.ascent = NS_MAX(bmBase.ascent, bmSubScript.ascent - actualSubScriptShift); boundingMetrics.descent = NS_MAX(bmBase.descent, bmSubScript.descent + actualSubScriptShift); // add aScriptSpace to the subscript's width boundingMetrics.width = bmBase.width + bmSubScript.width + aScriptSpace; boundingMetrics.leftBearing = bmBase.leftBearing; boundingMetrics.rightBearing = NS_MAX(bmBase.rightBearing, bmBase.width + NS_MAX(bmSubScript.width + aScriptSpace, bmSubScript.rightBearing)); aFrame->SetBoundingMetrics (boundingMetrics); // reflow metrics aDesiredSize.ascent = NS_MAX(baseSize.ascent, subScriptSize.ascent - actualSubScriptShift); aDesiredSize.height = aDesiredSize.ascent + NS_MAX(baseSize.height - baseSize.ascent, subScriptSize.height - subScriptSize.ascent + actualSubScriptShift); aDesiredSize.width = boundingMetrics.width; aDesiredSize.mBoundingMetrics = boundingMetrics; aFrame->SetReference(nsPoint(0, aDesiredSize.ascent)); if (aPlaceOrigin) { nscoord dx, dy; // now place the base ... dx = aFrame->MirrorIfRTL(aDesiredSize.width, baseSize.width, 0); dy = aDesiredSize.ascent - baseSize.ascent; FinishReflowChild (baseFrame, aPresContext, nullptr, baseSize, dx, dy, 0); // ... and subscript dx = aFrame->MirrorIfRTL(aDesiredSize.width, subScriptSize.width, bmBase.width); dy = aDesiredSize.ascent - (subScriptSize.ascent - actualSubScriptShift); FinishReflowChild (subScriptFrame, aPresContext, nullptr, subScriptSize, dx, dy, 0); } return NS_OK; }
float Axis::GetAccelerationFactor() { return powf(ACCELERATION_MULTIPLIER, NS_MAX(0, (mAcceleration - 4) * 3)); }
NS_IMETHODIMP nsMathMLmrootFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { nsresult rv = NS_OK; nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); nsReflowStatus childStatus; aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = 0; nsBoundingMetrics bmSqr, bmBase, bmIndex; nsRenderingContext& renderingContext = *aReflowState.rendContext; ////////////////// // Reflow Children PRInt32 count = 0; nsIFrame* baseFrame = nsnull; nsIFrame* indexFrame = nsnull; nsHTMLReflowMetrics baseSize; nsHTMLReflowMetrics indexSize; nsIFrame* childFrame = mFrames.FirstChild(); while (childFrame) { // ask our children to compute their bounding metrics nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS); nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize); rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, childStatus); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); if (NS_FAILED(rv)) { // Call DidReflow() for the child frames we successfully did reflow. DidReflowChildren(mFrames.FirstChild(), childFrame); return rv; } if (0 == count) { // base baseFrame = childFrame; baseSize = childDesiredSize; bmBase = childDesiredSize.mBoundingMetrics; } else if (1 == count) { // index indexFrame = childFrame; indexSize = childDesiredSize; bmIndex = childDesiredSize.mBoundingMetrics; } count++; childFrame = childFrame->GetNextSibling(); } if (2 != count) { // report an error, encourage people to get their markups in order rv = ReflowError(renderingContext, aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); // Call DidReflow() for the child frames we successfully did reflow. DidReflowChildren(mFrames.FirstChild(), childFrame); return rv; } //////////// // Prepare the radical symbol and the overline bar renderingContext.SetFont(GetStyleFont()->mFont, aPresContext->GetUserFontSet()); nsFontMetrics* fm = renderingContext.FontMetrics(); // For radical glyphs from TeX fonts and some of the radical glyphs from // Mathematica fonts, the thickness of the overline can be obtained from the // ascent of the glyph. Most fonts however have radical glyphs above the // baseline so no assumption can be made about the meaning of the ascent. nscoord ruleThickness, leading, em; GetRuleThickness(renderingContext, fm, ruleThickness); PRUnichar one = '1'; nsBoundingMetrics bmOne = renderingContext.GetBoundingMetrics(&one, 1); // get the leading to be left at the top of the resulting frame // this seems more reliable than using fm->GetLeading() on suspicious fonts GetEmHeight(fm, em); leading = nscoord(0.2f * em); // Rule 11, App. G, TeXbook // psi = clearance between rule and content nscoord phi = 0, psi = 0; if (NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) phi = fm->XHeight(); else phi = ruleThickness; psi = ruleThickness + phi/4; // built-in: adjust clearance psi to emulate \mathstrut using '1' (TexBook, p.131) if (bmOne.ascent > bmBase.ascent) psi += bmOne.ascent - bmBase.ascent; // make sure that the rule appears on on screen nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1); if (ruleThickness < onePixel) { ruleThickness = onePixel; } // adjust clearance psi to get an exact number of pixels -- this // gives a nicer & uniform look on stacked radicals (bug 130282) nscoord delta = psi % onePixel; if (delta) psi += onePixel - delta; // round up // Stretch the radical symbol to the appropriate height if it is not big enough. nsBoundingMetrics contSize = bmBase; contSize.descent = bmBase.ascent + bmBase.descent + psi; contSize.ascent = ruleThickness; // height(radical) should be >= height(base) + psi + ruleThickness nsBoundingMetrics radicalSize; mSqrChar.Stretch(aPresContext, renderingContext, NS_STRETCH_DIRECTION_VERTICAL, contSize, radicalSize, NS_STRETCH_LARGER); // radicalSize have changed at this point, and should match with // the bounding metrics of the char mSqrChar.GetBoundingMetrics(bmSqr); // Update the desired size for the container (like msqrt, index is not yet included) // the baseline will be that of the base. mBoundingMetrics.ascent = bmBase.ascent + psi + ruleThickness; mBoundingMetrics.descent = NS_MAX(bmBase.descent, (bmSqr.ascent + bmSqr.descent - mBoundingMetrics.ascent)); mBoundingMetrics.width = bmSqr.width + bmBase.width; mBoundingMetrics.leftBearing = bmSqr.leftBearing; mBoundingMetrics.rightBearing = bmSqr.width + NS_MAX(bmBase.width, bmBase.rightBearing); // take also care of the rule aDesiredSize.ascent = mBoundingMetrics.ascent + leading; aDesiredSize.height = aDesiredSize.ascent + NS_MAX(baseSize.height - baseSize.ascent, mBoundingMetrics.descent + ruleThickness); aDesiredSize.width = mBoundingMetrics.width; ///////////// // Re-adjust the desired size to include the index. // the index is raised by some fraction of the height // of the radical, see \mroot macro in App. B, TexBook nscoord raiseIndexDelta = NSToCoordRound(0.6f * (bmSqr.ascent + bmSqr.descent)); nscoord indexRaisedAscent = mBoundingMetrics.ascent // top of radical - (bmSqr.ascent + bmSqr.descent) // to bottom of radical + raiseIndexDelta + bmIndex.ascent + bmIndex.descent; // to top of raised index nscoord indexClearance = 0; if (mBoundingMetrics.ascent < indexRaisedAscent) { indexClearance = indexRaisedAscent - mBoundingMetrics.ascent; // excess gap introduced by a tall index mBoundingMetrics.ascent = indexRaisedAscent; nscoord descent = aDesiredSize.height - aDesiredSize.ascent; aDesiredSize.ascent = mBoundingMetrics.ascent + leading; aDesiredSize.height = aDesiredSize.ascent + descent; } nscoord dxIndex, dxSqr; GetRadicalXOffsets(bmIndex.width, bmSqr.width, fm, &dxIndex, &dxSqr); // place the index nscoord dx = dxIndex; nscoord dy = aDesiredSize.ascent - (indexRaisedAscent + indexSize.ascent - bmIndex.ascent); FinishReflowChild(indexFrame, aPresContext, nsnull, indexSize, dx, dy, 0); // place the radical symbol and the radical bar dx = dxSqr; dy = indexClearance + leading; // leave a leading at the top mSqrChar.SetRect(nsRect(dx, dy, bmSqr.width, bmSqr.ascent + bmSqr.descent)); dx += bmSqr.width; mBarRect.SetRect(dx, dy, bmBase.width, ruleThickness); // place the base dy = aDesiredSize.ascent - baseSize.ascent; FinishReflowChild(baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0); mReference.x = 0; mReference.y = aDesiredSize.ascent; mBoundingMetrics.width = dx + bmBase.width; mBoundingMetrics.leftBearing = NS_MIN(dxIndex + bmIndex.leftBearing, dxSqr + bmSqr.leftBearing); mBoundingMetrics.rightBearing = dx + NS_MAX(bmBase.width, bmBase.rightBearing); aDesiredSize.width = mBoundingMetrics.width; aDesiredSize.mBoundingMetrics = mBoundingMetrics; GatherAndStoreOverflow(&aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
nsSize nsBox::BoundsCheckMinMax(const nsSize& aMinSize, const nsSize& aMaxSize) { return nsSize(NS_MAX(aMaxSize.width, aMinSize.width), NS_MAX(aMaxSize.height, aMinSize.height)); }
void gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics, PRUint32* aSpaceGlyph) { NS_PRECONDITION(aMetrics != NULL, "aMetrics must not be NULL"); NS_PRECONDITION(aSpaceGlyph != NULL, "aSpaceGlyph must not be NULL"); if (NS_UNLIKELY(!mFace)) { // No face. This unfortunate situation might happen if the font // file is (re)moved at the wrong time. aMetrics->emHeight = mGfxFont->GetStyle()->size; aMetrics->emAscent = 0.8 * aMetrics->emHeight; aMetrics->emDescent = 0.2 * aMetrics->emHeight; aMetrics->maxAscent = aMetrics->emAscent; aMetrics->maxDescent = aMetrics->maxDescent; aMetrics->maxHeight = aMetrics->emHeight; aMetrics->internalLeading = 0.0; aMetrics->externalLeading = 0.2 * aMetrics->emHeight; aSpaceGlyph = 0; aMetrics->spaceWidth = 0.5 * aMetrics->emHeight; aMetrics->maxAdvance = aMetrics->spaceWidth; aMetrics->aveCharWidth = aMetrics->spaceWidth; aMetrics->zeroOrAveCharWidth = aMetrics->spaceWidth; aMetrics->xHeight = 0.5 * aMetrics->emHeight; aMetrics->underlineSize = aMetrics->emHeight / 14.0; aMetrics->underlineOffset = -aMetrics->underlineSize; aMetrics->strikeoutOffset = 0.25 * aMetrics->emHeight; aMetrics->strikeoutSize = aMetrics->underlineSize; aMetrics->superscriptOffset = aMetrics->xHeight; aMetrics->subscriptOffset = aMetrics->xHeight; return; } const FT_Size_Metrics& ftMetrics = mFace->size->metrics; gfxFloat emHeight; // Scale for vertical design metric conversion: pixels per design unit. gfxFloat yScale; if (FT_IS_SCALABLE(mFace)) { // Prefer FT_Size_Metrics::x_scale to x_ppem as x_ppem does not // have subpixel accuracy. // // FT_Size_Metrics::y_scale is in 16.16 fixed point format. Its // (fractional) value is a factor that converts vertical metrics from // design units to units of 1/64 pixels, so that the result may be // interpreted as pixels in 26.6 fixed point format. yScale = FLOAT_FROM_26_6(FLOAT_FROM_16_16(ftMetrics.y_scale)); emHeight = mFace->units_per_EM * yScale; } else { // Not scalable. // FT_Size_Metrics doc says x_scale is "only relevant for scalable // font formats". gfxFloat emUnit = mFace->units_per_EM; emHeight = ftMetrics.y_ppem; yScale = emHeight / emUnit; } TT_OS2 *os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(mFace, ft_sfnt_os2)); aMetrics->maxAscent = FLOAT_FROM_26_6(ftMetrics.ascender); aMetrics->maxDescent = -FLOAT_FROM_26_6(ftMetrics.descender); aMetrics->maxAdvance = FLOAT_FROM_26_6(ftMetrics.max_advance); gfxFloat lineHeight; if (os2 && os2->sTypoAscender) { aMetrics->emAscent = os2->sTypoAscender * yScale; aMetrics->emDescent = -os2->sTypoDescender * yScale; FT_Short typoHeight = os2->sTypoAscender - os2->sTypoDescender + os2->sTypoLineGap; lineHeight = typoHeight * yScale; // maxAscent/maxDescent get used for frame heights, and some fonts // don't have the HHEA table ascent/descent set (bug 279032). if (aMetrics->emAscent > aMetrics->maxAscent) aMetrics->maxAscent = aMetrics->emAscent; if (aMetrics->emDescent > aMetrics->maxDescent) aMetrics->maxDescent = aMetrics->emDescent; } else { aMetrics->emAscent = aMetrics->maxAscent; aMetrics->emDescent = aMetrics->maxDescent; lineHeight = FLOAT_FROM_26_6(ftMetrics.height); } cairo_text_extents_t extents; *aSpaceGlyph = GetCharExtents(' ', &extents); if (*aSpaceGlyph) { aMetrics->spaceWidth = extents.x_advance; } else { aMetrics->spaceWidth = aMetrics->maxAdvance; // guess } aMetrics->zeroOrAveCharWidth = 0.0; if (GetCharExtents('0', &extents)) { aMetrics->zeroOrAveCharWidth = extents.x_advance; } // Prefering a measured x over sxHeight because sxHeight doesn't consider // hinting, but maybe the x extents are not quite right in some fancy // script fonts. CSS 2.1 suggests possibly using the height of an "o", // which would have a more consistent glyph across fonts. if (GetCharExtents('x', &extents) && extents.y_bearing < 0.0) { aMetrics->xHeight = -extents.y_bearing; aMetrics->aveCharWidth = extents.x_advance; } else { if (os2 && os2->sxHeight) { aMetrics->xHeight = os2->sxHeight * yScale; } else { // CSS 2.1, section 4.3.2 Lengths: "In the cases where it is // impossible or impractical to determine the x-height, a value of // 0.5em should be used." aMetrics->xHeight = 0.5 * emHeight; } aMetrics->aveCharWidth = 0.0; // updated below } // aveCharWidth is used for the width of text input elements so be // liberal rather than conservative in the estimate. if (os2 && os2->xAvgCharWidth) { // Round to pixels as this is compared with maxAdvance to guess // whether this is a fixed width font. gfxFloat avgCharWidth = ScaleRoundDesignUnits(os2->xAvgCharWidth, ftMetrics.x_scale); aMetrics->aveCharWidth = NS_MAX(aMetrics->aveCharWidth, avgCharWidth); } aMetrics->aveCharWidth = NS_MAX(aMetrics->aveCharWidth, aMetrics->zeroOrAveCharWidth); if (aMetrics->aveCharWidth == 0.0) { aMetrics->aveCharWidth = aMetrics->spaceWidth; } if (aMetrics->zeroOrAveCharWidth == 0.0) { aMetrics->zeroOrAveCharWidth = aMetrics->aveCharWidth; } // Apparently hinting can mean that max_advance is not always accurate. aMetrics->maxAdvance = NS_MAX(aMetrics->maxAdvance, aMetrics->aveCharWidth); // gfxFont::Metrics::underlineOffset is the position of the top of the // underline. // // FT_FaceRec documentation describes underline_position as "the // center of the underlining stem". This was the original definition // of the PostScript metric, but in the PostScript table of OpenType // fonts the metric is "the top of the underline" // (http://www.microsoft.com/typography/otspec/post.htm), and FreeType // (up to version 2.3.7) doesn't make any adjustment. // // Therefore get the underline position directly from the table // ourselves when this table exists. Use FreeType's metrics for // other (including older PostScript) fonts. if (mFace->underline_position && mFace->underline_thickness) { aMetrics->underlineSize = mFace->underline_thickness * yScale; TT_Postscript *post = static_cast<TT_Postscript*> (FT_Get_Sfnt_Table(mFace, ft_sfnt_post)); if (post && post->underlinePosition) { aMetrics->underlineOffset = post->underlinePosition * yScale; } else { aMetrics->underlineOffset = mFace->underline_position * yScale + 0.5 * aMetrics->underlineSize; } } else { // No underline info. // Imitate Pango. aMetrics->underlineSize = emHeight / 14.0; aMetrics->underlineOffset = -aMetrics->underlineSize; } if (os2 && os2->yStrikeoutSize && os2->yStrikeoutPosition) { aMetrics->strikeoutSize = os2->yStrikeoutSize * yScale; aMetrics->strikeoutOffset = os2->yStrikeoutPosition * yScale; } else { // No strikeout info. aMetrics->strikeoutSize = aMetrics->underlineSize; // Use OpenType spec's suggested position for Roman font. aMetrics->strikeoutOffset = emHeight * 409.0 / 2048.0 + 0.5 * aMetrics->strikeoutSize; } SnapLineToPixels(aMetrics->strikeoutOffset, aMetrics->strikeoutSize); if (os2 && os2->ySuperscriptYOffset) { gfxFloat val = ScaleRoundDesignUnits(os2->ySuperscriptYOffset, ftMetrics.y_scale); aMetrics->superscriptOffset = NS_MAX(1.0, val); } else { aMetrics->superscriptOffset = aMetrics->xHeight; } if (os2 && os2->ySubscriptYOffset) { gfxFloat val = ScaleRoundDesignUnits(os2->ySubscriptYOffset, ftMetrics.y_scale); // some fonts have the incorrect sign. val = fabs(val); aMetrics->subscriptOffset = NS_MAX(1.0, val); } else { aMetrics->subscriptOffset = aMetrics->xHeight; } aMetrics->maxHeight = aMetrics->maxAscent + aMetrics->maxDescent; // Make the line height an integer number of pixels so that lines will be // equally spaced (rather than just being snapped to pixels, some up and // some down). Layout calculates line height from the emHeight + // internalLeading + externalLeading, but first each of these is rounded // to layout units. To ensure that the result is an integer number of // pixels, round each of the components to pixels. aMetrics->emHeight = NS_floor(emHeight + 0.5); // maxHeight will normally be an integer, but round anyway in case // FreeType is configured differently. aMetrics->internalLeading = NS_floor(aMetrics->maxHeight - aMetrics->emHeight + 0.5); // Text input boxes currently don't work well with lineHeight // significantly less than maxHeight (with Verdana, for example). lineHeight = NS_floor(NS_MAX(lineHeight, aMetrics->maxHeight) + 0.5); aMetrics->externalLeading = lineHeight - aMetrics->internalLeading - aMetrics->emHeight; // Ensure emAscent + emDescent == emHeight gfxFloat sum = aMetrics->emAscent + aMetrics->emDescent; aMetrics->emAscent = sum > 0.0 ? aMetrics->emAscent * aMetrics->emHeight / sum : 0.0; aMetrics->emDescent = aMetrics->emHeight - aMetrics->emAscent; }
NS_IMETHODIMP nsMathMLmfencedFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { nsresult rv; aDesiredSize.width = aDesiredSize.height = 0; aDesiredSize.ascent = 0; aDesiredSize.mBoundingMetrics = nsBoundingMetrics(); PRInt32 i; const nsStyleFont* font = GetStyleFont(); nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); aReflowState.rendContext->SetFont(fm); nscoord axisHeight, em; GetAxisHeight(*aReflowState.rendContext, fm, axisHeight); GetEmHeight(fm, em); // leading to be left at the top and the bottom of stretched chars nscoord leading = NSToCoordRound(0.2f * em); ///////////// // Reflow children // Asking each child to cache its bounding metrics // Note that we don't use the base method nsMathMLContainerFrame::Reflow() // because we want to stretch our fences, separators and stretchy frames using // the *same* initial aDesiredSize.mBoundingMetrics. If we were to use the base // method here, our stretchy frames will be stretched and placed, and we may // end up stretching our fences/separators with a different aDesiredSize. // XXX The above decision was revisited in bug 121748 and this code can be // refactored to use nsMathMLContainerFrame::Reflow() at some stage. nsReflowStatus childStatus; nsSize availSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE); nsIFrame* firstChild = GetFirstChild(nsnull); nsIFrame* childFrame = firstChild; nscoord ascent = 0, descent = 0; if (firstChild || mOpenChar || mCloseChar || mSeparatorsCount > 0) { // We use the ASCII metrics to get our minimum height. This way, // if we have borders or a background, they will fit better with // other elements on the line. ascent = fm->MaxAscent(); descent = fm->MaxDescent(); } while (childFrame) { nsHTMLReflowMetrics childDesiredSize(aDesiredSize.mFlags | NS_REFLOW_CALC_BOUNDING_METRICS); nsHTMLReflowState childReflowState(aPresContext, aReflowState, childFrame, availSize); rv = ReflowChild(childFrame, aPresContext, childDesiredSize, childReflowState, childStatus); //NS_ASSERTION(NS_FRAME_IS_COMPLETE(childStatus), "bad status"); if (NS_FAILED(rv)) { // Call DidReflow() for the child frames we successfully did reflow. DidReflowChildren(firstChild, childFrame); return rv; } SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; if (descent < childDescent) descent = childDescent; if (ascent < childDesiredSize.ascent) ascent = childDesiredSize.ascent; childFrame = childFrame->GetNextSibling(); } ///////////// // Ask stretchy children to stretch themselves nsBoundingMetrics containerSize; nsStretchDirection stretchDir = NS_STRETCH_DIRECTION_VERTICAL; GetPreferredStretchSize(*aReflowState.rendContext, 0, /* i.e., without embellishments */ stretchDir, containerSize); childFrame = firstChild; while (childFrame) { nsIMathMLFrame* mathmlChild = do_QueryFrame(childFrame); if (mathmlChild) { nsHTMLReflowMetrics childDesiredSize; // retrieve the metrics that was stored at the previous pass GetReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); mathmlChild->Stretch(*aReflowState.rendContext, stretchDir, containerSize, childDesiredSize); // store the updated metrics SaveReflowAndBoundingMetricsFor(childFrame, childDesiredSize, childDesiredSize.mBoundingMetrics); nscoord childDescent = childDesiredSize.height - childDesiredSize.ascent; if (descent < childDescent) descent = childDescent; if (ascent < childDesiredSize.ascent) ascent = childDesiredSize.ascent; } childFrame = childFrame->GetNextSibling(); } // bug 121748: for surrounding fences & separators, use a size that covers everything GetPreferredStretchSize(*aReflowState.rendContext, STRETCH_CONSIDER_EMBELLISHMENTS, stretchDir, containerSize); ////////////////////////////////////////// // Prepare the opening fence, separators, and closing fence, and // adjust the origin of children. // we need to center around the axis nscoord delta = NS_MAX(containerSize.ascent - axisHeight, containerSize.descent + axisHeight); containerSize.ascent = delta + axisHeight; containerSize.descent = delta - axisHeight; ///////////////// // opening fence ... ReflowChar(aPresContext, *aReflowState.rendContext, mOpenChar, NS_MATHML_OPERATOR_FORM_PREFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); ///////////////// // separators ... for (i = 0; i < mSeparatorsCount; i++) { ReflowChar(aPresContext, *aReflowState.rendContext, &mSeparatorsChar[i], NS_MATHML_OPERATOR_FORM_INFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); } ///////////////// // closing fence ... ReflowChar(aPresContext, *aReflowState.rendContext, mCloseChar, NS_MATHML_OPERATOR_FORM_POSTFIX, font->mScriptLevel, axisHeight, leading, em, containerSize, ascent, descent); ////////////////// // Adjust the origins of each child. // and update our bounding metrics i = 0; nscoord dx = 0; nsBoundingMetrics bm; PRBool firstTime = PR_TRUE; if (mOpenChar) { PlaceChar(mOpenChar, ascent, bm, dx); aDesiredSize.mBoundingMetrics = bm; firstTime = PR_FALSE; } childFrame = firstChild; while (childFrame) { nsHTMLReflowMetrics childSize; GetReflowAndBoundingMetricsFor(childFrame, childSize, bm); if (firstTime) { firstTime = PR_FALSE; aDesiredSize.mBoundingMetrics = bm; } else aDesiredSize.mBoundingMetrics += bm; FinishReflowChild(childFrame, aPresContext, nsnull, childSize, dx, ascent - childSize.ascent, 0); dx += childSize.width; if (i < mSeparatorsCount) { PlaceChar(&mSeparatorsChar[i], ascent, bm, dx); aDesiredSize.mBoundingMetrics += bm; } i++; childFrame = childFrame->GetNextSibling(); } if (mCloseChar) { PlaceChar(mCloseChar, ascent, bm, dx); if (firstTime) aDesiredSize.mBoundingMetrics = bm; else aDesiredSize.mBoundingMetrics += bm; } aDesiredSize.width = aDesiredSize.mBoundingMetrics.width; aDesiredSize.height = ascent + descent; aDesiredSize.ascent = ascent; SetBoundingMetrics(aDesiredSize.mBoundingMetrics); SetReference(nsPoint(0, aDesiredSize.ascent)); // see if we should fix the spacing FixInterFrameSpacing(aDesiredSize); // Finished with these: ClearSavedChildMetrics(); // Set our overflow area GatherAndStoreOverflow(&aDesiredSize); aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
nsresult nsAbsoluteContainingBlock::ReflowAbsoluteFrame(nsIFrame* aDelegatingFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nscoord aContainingBlockWidth, nscoord aContainingBlockHeight, PRBool aConstrainHeight, nsIFrame* aKidFrame, nsReflowStatus& aStatus, nsOverflowAreas* aOverflowAreas) { #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent); printf("abs pos "); if (aKidFrame) { nsAutoString name; aKidFrame->GetFrameName(name); printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); } char width[16]; char height[16]; PrettyUC(aReflowState.availableWidth, width); PrettyUC(aReflowState.availableHeight, height); printf(" a=%s,%s ", width, height); PrettyUC(aReflowState.ComputedWidth(), width); PrettyUC(aReflowState.ComputedHeight(), height); printf("c=%s,%s \n", width, height); } AutoNoisyIndenter indent(nsBlockFrame::gNoisy); #endif // DEBUG // Store position and overflow rect so taht we can invalidate the correct // area if the position changes nsRect oldOverflowRect(aKidFrame->GetVisualOverflowRect() + aKidFrame->GetPosition()); nsRect oldRect = aKidFrame->GetRect(); nsresult rv; // Get the border values const nsMargin& border = aReflowState.mStyleBorder->GetActualBorder(); nscoord availWidth = aContainingBlockWidth; if (availWidth == -1) { NS_ASSERTION(aReflowState.ComputedWidth() != NS_UNCONSTRAINEDSIZE, "Must have a useful width _somewhere_"); availWidth = aReflowState.ComputedWidth() + aReflowState.mComputedPadding.LeftRight(); } nsHTMLReflowMetrics kidDesiredSize; nsHTMLReflowState kidReflowState(aPresContext, aReflowState, aKidFrame, nsSize(availWidth, NS_UNCONSTRAINEDSIZE), aContainingBlockWidth, aContainingBlockHeight); // Send the WillReflow() notification and position the frame aKidFrame->WillReflow(aPresContext); PRBool constrainHeight = (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) && aConstrainHeight // Don't split if told not to (e.g. for fixed frames) && (aDelegatingFrame->GetType() != nsGkAtoms::positionedInlineFrame) //XXX we don't handle splitting frames for inline absolute containing blocks yet && (aKidFrame->GetRect().y <= aReflowState.availableHeight); // Don't split things below the fold. (Ideally we shouldn't *have* // anything totally below the fold, but we can't position frames // across next-in-flow breaks yet. if (constrainHeight) { kidReflowState.availableHeight = aReflowState.availableHeight - border.top - kidReflowState.mComputedMargin.top; if (NS_AUTOOFFSET != kidReflowState.mComputedOffsets.top) kidReflowState.availableHeight -= kidReflowState.mComputedOffsets.top; } // Do the reflow rv = aKidFrame->Reflow(aPresContext, kidDesiredSize, kidReflowState, aStatus); // If we're solving for 'left' or 'top', then compute it now that we know the // width/height if ((NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) || (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.top)) { if (-1 == aContainingBlockWidth) { // Get the containing block width/height kidReflowState.ComputeContainingBlockRectangle(aPresContext, &aReflowState, aContainingBlockWidth, aContainingBlockHeight); } if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.left) { NS_ASSERTION(NS_AUTOOFFSET != kidReflowState.mComputedOffsets.right, "Can't solve for both left and right"); kidReflowState.mComputedOffsets.left = aContainingBlockWidth - kidReflowState.mComputedOffsets.right - kidReflowState.mComputedMargin.right - kidDesiredSize.width - kidReflowState.mComputedMargin.left; } if (NS_AUTOOFFSET == kidReflowState.mComputedOffsets.top) { kidReflowState.mComputedOffsets.top = aContainingBlockHeight - kidReflowState.mComputedOffsets.bottom - kidReflowState.mComputedMargin.bottom - kidDesiredSize.height - kidReflowState.mComputedMargin.top; } } // Position the child relative to our padding edge nsRect rect(border.left + kidReflowState.mComputedOffsets.left + kidReflowState.mComputedMargin.left, border.top + kidReflowState.mComputedOffsets.top + kidReflowState.mComputedMargin.top, kidDesiredSize.width, kidDesiredSize.height); aKidFrame->SetRect(rect); nsIView* view = aKidFrame->GetView(); if (view) { // Size and position the view and set its opacity, visibility, content // transparency, and clip nsContainerFrame::SyncFrameViewAfterReflow(aPresContext, aKidFrame, view, kidDesiredSize.VisualOverflow()); } else { nsContainerFrame::PositionChildViews(aKidFrame); } if (oldRect.TopLeft() != rect.TopLeft() || (aDelegatingFrame->GetStateBits() & NS_FRAME_FIRST_REFLOW)) { // The frame moved aKidFrame->GetParent()->Invalidate(oldOverflowRect); aKidFrame->InvalidateFrameSubtree(); } else if (oldRect.Size() != rect.Size()) { // Invalidate the area where the frame changed size. nscoord innerWidth = NS_MIN(oldRect.width, rect.width); nscoord innerHeight = NS_MIN(oldRect.height, rect.height); nscoord outerWidth = NS_MAX(oldRect.width, rect.width); nscoord outerHeight = NS_MAX(oldRect.height, rect.height); aKidFrame->GetParent()->Invalidate( nsRect(rect.x + innerWidth, rect.y, outerWidth - innerWidth, outerHeight)); // Invalidate the horizontal strip aKidFrame->GetParent()->Invalidate( nsRect(rect.x, rect.y + innerHeight, outerWidth, outerHeight - innerHeight)); } aKidFrame->DidReflow(aPresContext, &kidReflowState, NS_FRAME_REFLOW_FINISHED); #ifdef DEBUG if (nsBlockFrame::gNoisyReflow) { nsFrame::IndentBy(stdout,nsBlockFrame::gNoiseIndent - 1); printf("abs pos "); if (aKidFrame) { nsAutoString name; aKidFrame->GetFrameName(name); printf("%s ", NS_LossyConvertUTF16toASCII(name).get()); } printf("%p rect=%d,%d,%d,%d\n", static_cast<void*>(aKidFrame), rect.x, rect.y, rect.width, rect.height); } #endif if (aOverflowAreas) { aOverflowAreas->UnionWith(kidDesiredSize.mOverflowAreas + rect.TopLeft()); } return rv; }
NS_IMETHODIMP nsSimplePageSequenceFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { NS_PRECONDITION(aPresContext->IsRootPaginatedDocument(), "A Page Sequence is only for real pages"); DO_GLOBAL_REFLOW_COUNT("nsSimplePageSequenceFrame"); DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus); NS_FRAME_TRACE_REFLOW_IN("nsSimplePageSequenceFrame::Reflow"); aStatus = NS_FRAME_COMPLETE; // we're always complete // Don't do incremental reflow until we've taught tables how to do // it right in paginated mode. if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) { // Return our desired size aDesiredSize.height = mSize.height * PresContext()->GetPrintPreviewScale(); aDesiredSize.width = mSize.width * PresContext()->GetPrintPreviewScale(); aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); return NS_OK; } PRBool isPrintPreview = aPresContext->Type() == nsPresContext::eContext_PrintPreview; // See if we can get a Print Settings from the Context if (!mPageData->mPrintSettings && aPresContext->Medium() == nsGkAtoms::print) { mPageData->mPrintSettings = aPresContext->GetPrintSettings(); } // now get out margins & edges if (mPageData->mPrintSettings) { nsIntMargin unwriteableTwips; mPageData->mPrintSettings->GetUnwriteableMarginInTwips(unwriteableTwips); NS_ASSERTION(unwriteableTwips.left >= 0 && unwriteableTwips.top >= 0 && unwriteableTwips.right >= 0 && unwriteableTwips.bottom >= 0, "Unwriteable twips should be non-negative"); nsIntMargin marginTwips; mPageData->mPrintSettings->GetMarginInTwips(marginTwips); mMargin = aPresContext->CSSTwipsToAppUnits(marginTwips + unwriteableTwips); PRInt16 printType; mPageData->mPrintSettings->GetPrintRange(&printType); mPrintRangeType = printType; nsIntMargin edgeTwips; mPageData->mPrintSettings->GetEdgeInTwips(edgeTwips); // sanity check the values. three inches are sometimes needed PRInt32 inchInTwips = NS_INCHES_TO_INT_TWIPS(3.0); edgeTwips.top = NS_MIN(NS_MAX(edgeTwips.top, 0), inchInTwips); edgeTwips.bottom = NS_MIN(NS_MAX(edgeTwips.bottom, 0), inchInTwips); edgeTwips.left = NS_MIN(NS_MAX(edgeTwips.left, 0), inchInTwips); edgeTwips.right = NS_MIN(NS_MAX(edgeTwips.right, 0), inchInTwips); mPageData->mEdgePaperMargin = aPresContext->CSSTwipsToAppUnits(edgeTwips + unwriteableTwips); } // *** Special Override *** // If this is a sub-sdoc (meaning it doesn't take the whole page) // and if this Document is in the upper left hand corner // we need to suppress the top margin or it will reflow too small nsSize pageSize = aPresContext->GetPageSize(); mPageData->mReflowSize = pageSize; // If we're printing a selection, we need to reflow with // unconstrained height, to make sure we'll get to the selection // even if it's beyond the first page of content. if (nsIPrintSettings::kRangeSelection == mPrintRangeType) { mPageData->mReflowSize.height = NS_UNCONSTRAINEDSIZE; } mPageData->mReflowMargin = mMargin; // Compute the size of each page and the x coordinate that each page will // be placed at nscoord extraThreshold = NS_MAX(pageSize.width, pageSize.height)/10; PRInt32 gapInTwips = nsContentUtils::GetIntPref("print.print_extra_margin"); gapInTwips = NS_MAX(0, gapInTwips); nscoord extraGap = aPresContext->CSSTwipsToAppUnits(gapInTwips); extraGap = NS_MIN(extraGap, extraThreshold); // clamp to 1/10 of the largest dim of the page nscoord deadSpaceGap = 0; if (isPrintPreview) { GetDeadSpaceValue(&gapInTwips); deadSpaceGap = aPresContext->CSSTwipsToAppUnits(gapInTwips); } nsMargin extraMargin(0,0,0,0); nsSize shadowSize(0,0); if (aPresContext->IsScreen()) { extraMargin.SizeTo(extraGap, extraGap, extraGap, extraGap); nscoord fourPixels = nsPresContext::CSSPixelsToAppUnits(4); shadowSize.SizeTo(fourPixels, fourPixels); } mPageData->mShadowSize = shadowSize; mPageData->mExtraMargin = extraMargin; const nscoord x = deadSpaceGap; nscoord y = deadSpaceGap;// Running y-offset for each page nsSize availSize(pageSize.width + shadowSize.width + extraMargin.LeftRight(), pageSize.height + shadowSize.height + extraMargin.TopBottom()); // Tile the pages vertically nsHTMLReflowMetrics kidSize; for (nsIFrame* kidFrame = mFrames.FirstChild(); nsnull != kidFrame; ) { // Set the shared data into the page frame before reflow nsPageFrame * pf = static_cast<nsPageFrame*>(kidFrame); pf->SetSharedPageData(mPageData); // Reflow the page nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame, availSize); nsReflowStatus status; kidReflowState.SetComputedWidth(kidReflowState.availableWidth); //kidReflowState.SetComputedHeight(kidReflowState.availableHeight); PR_PL(("AV W: %d H: %d\n", kidReflowState.availableWidth, kidReflowState.availableHeight)); // Place and size the page. If the page is narrower than our // max width then center it horizontally ReflowChild(kidFrame, aPresContext, kidSize, kidReflowState, x, y, 0, status); FinishReflowChild(kidFrame, aPresContext, nsnull, kidSize, x, y, 0); y += kidSize.height; // Leave a slight gap between the pages y += deadSpaceGap; // Is the page complete? nsIFrame* kidNextInFlow = kidFrame->GetNextInFlow(); if (NS_FRAME_IS_FULLY_COMPLETE(status)) { NS_ASSERTION(!kidNextInFlow, "bad child flow list"); } else if (!kidNextInFlow) { // The page isn't complete and it doesn't have a next-in-flow, so // create a continuing page. nsIFrame* continuingPage; nsresult rv = aPresContext->PresShell()->FrameConstructor()-> CreateContinuingFrame(aPresContext, kidFrame, this, &continuingPage); if (NS_FAILED(rv)) { break; } // Add it to our child list mFrames.InsertFrame(nsnull, kidFrame, continuingPage); } // Get the next page kidFrame = kidFrame->GetNextSibling(); } // Get Total Page Count nsIFrame* page; PRInt32 pageTot = 0; for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) { pageTot++; } // Set Page Number Info PRInt32 pageNum = 1; for (page = mFrames.FirstChild(); page; page = page->GetNextSibling()) { nsPageFrame * pf = static_cast<nsPageFrame*>(page); if (pf != nsnull) { pf->SetPageNumInfo(pageNum, pageTot); } pageNum++; } // Create current Date/Time String if (!mDateFormatter) mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID); NS_ENSURE_TRUE(mDateFormatter, NS_ERROR_FAILURE); nsAutoString formattedDateString; time_t ltime; time( <ime ); if (NS_SUCCEEDED(mDateFormatter->FormatTime(nsnull /* nsILocale* locale */, kDateFormatShort, kTimeFormatNoSeconds, ltime, formattedDateString))) { PRUnichar * uStr = ToNewUnicode(formattedDateString); SetDateTimeStr(uStr); // memory will be freed } // Return our desired size // Adjustr the reflow size by PrintPreviewScale so the scrollbars end up the // correct size nscoord w = (x + availSize.width + deadSpaceGap); aDesiredSize.height = y * PresContext()->GetPrintPreviewScale(); // includes page heights and dead space aDesiredSize.width = w * PresContext()->GetPrintPreviewScale(); aDesiredSize.SetOverflowAreasToDesiredBounds(); FinishAndStoreOverflow(&aDesiredSize); // cache the size so we can set the desired size // for the other reflows that happen mSize.width = w; mSize.height = y; NS_FRAME_TRACE_REFLOW_OUT("nsSimplePageSequeceFrame::Reflow", aStatus); NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); return NS_OK; }
/* virtual */ nsresult nsMathMLmoverFrame::Place(nsIRenderingContext& aRenderingContext, PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { if ( NS_MATHML_EMBELLISH_IS_MOVABLELIMITS(mEmbellishData.flags) && !NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags)) { // place like superscript return nsMathMLmsupFrame::PlaceSuperScript(PresContext(), aRenderingContext, aPlaceOrigin, aDesiredSize, this, 0, nsPresContext::CSSPointsToAppUnits(0.5f)); } //////////////////////////////////// // Get the children's desired sizes nsBoundingMetrics bmBase, bmOver; nsHTMLReflowMetrics baseSize; nsHTMLReflowMetrics overSize; nsIFrame* overFrame = nsnull; nsIFrame* baseFrame = mFrames.FirstChild(); if (baseFrame) overFrame = baseFrame->GetNextSibling(); if (!baseFrame || !overFrame || overFrame->GetNextSibling()) { // report an error, encourage people to get their markups in order return ReflowError(aRenderingContext, aDesiredSize); } GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver); nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1); //////////////////// // Place Children aRenderingContext.SetFont(GetStyleFont()->mFont, PresContext()->GetUserFontSet()); nsCOMPtr<nsIFontMetrics> fm; aRenderingContext.GetFontMetrics(*getter_AddRefs(fm)); nscoord xHeight = 0; fm->GetXHeight (xHeight); nscoord ruleThickness; GetRuleThickness (aRenderingContext, fm, ruleThickness); // there are 2 different types of placement depending on // whether we want an accented overscript or not nscoord correction = 0; GetItalicCorrection (bmBase, correction); nscoord delta1 = 0; // gap between base and overscript nscoord delta2 = 0; // extra space above overscript if (!NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) { // Rule 13a, App. G, TeXbook nscoord bigOpSpacing1, bigOpSpacing3, bigOpSpacing5, dummy; GetBigOpSpacings (fm, bigOpSpacing1, dummy, bigOpSpacing3, dummy, bigOpSpacing5); delta1 = NS_MAX(bigOpSpacing1, (bigOpSpacing3 - bmOver.descent)); delta2 = bigOpSpacing5; // XXX This is not a TeX rule... // delta1 (as computed above) can become really big when bmOver.descent is // negative, e.g., if the content is &OverBar. In such case, we use the height if (bmOver.descent < 0) delta1 = NS_MAX(bigOpSpacing1, (bigOpSpacing3 - (bmOver.ascent + bmOver.descent))); } else { // Rule 12, App. G, TeXbook // We are going to modify this rule to make it more general. // The idea behind Rule 12 in the TeXBook is to keep the accent // as close to the base as possible, while ensuring that the // distance between the *baseline* of the accent char and // the *baseline* of the base is atleast x-height. // The idea is that for normal use, we would like all the accents // on a line to line up atleast x-height above the baseline // if possible. // When the ascent of the base is >= x-height, // the baseline of the accent char is placed just above the base // (specifically, the baseline of the accent char is placed // above the baseline of the base by the ascent of the base). // For ease of implementation, // this assumes that the font-designer designs accents // in such a way that the bottom of the accent is atleast x-height // above its baseline, otherwise there will be collisions // with the base. Also there should be proper padding between // the bottom of the accent char and its baseline. // The above rule may not be obvious from a first // reading of rule 12 in the TeXBook !!! // The mathml <mover> tag can use accent chars that // do not follow this convention. So we modify TeX's rule // so that TeX's rule gets subsumed for accents that follow // TeX's convention, // while also allowing accents that do not follow the convention : // we try to keep the *bottom* of the accent char atleast x-height // from the baseline of the base char. we also slap on an extra // padding between the accent and base chars. delta1 = ruleThickness + onePixel/2; // we have at least the padding if (bmBase.ascent < xHeight) { // also ensure at least x-height above the baseline of the base delta1 += xHeight - bmBase.ascent; } delta2 = ruleThickness; } // empty over? if (!(bmOver.ascent + bmOver.descent)) delta1 = 0; nscoord dxBase, dxOver = 0; // Ad-hoc - This is to override fonts which have ready-made _accent_ // glyphs with negative lbearing and rbearing. We want to position // the overscript ourselves nscoord overWidth = bmOver.width; if (!overWidth && (bmOver.rightBearing - bmOver.leftBearing > 0)) { overWidth = bmOver.rightBearing - bmOver.leftBearing; dxOver = -bmOver.leftBearing; } if (NS_MATHML_EMBELLISH_IS_ACCENTOVER(mEmbellishData.flags)) { mBoundingMetrics.width = bmBase.width; dxOver += correction + (mBoundingMetrics.width - overWidth)/2; } else { mBoundingMetrics.width = NS_MAX(bmBase.width, overWidth); dxOver += correction/2 + (mBoundingMetrics.width - overWidth)/2; } dxBase = (mBoundingMetrics.width - bmBase.width) / 2; mBoundingMetrics.ascent = bmOver.ascent + bmOver.descent + delta1 + bmBase.ascent; mBoundingMetrics.descent = bmBase.descent; mBoundingMetrics.leftBearing = NS_MIN(dxBase + bmBase.leftBearing, dxOver + bmOver.leftBearing); mBoundingMetrics.rightBearing = NS_MAX(dxBase + bmBase.rightBearing, dxOver + bmOver.rightBearing); aDesiredSize.ascent = NS_MAX(mBoundingMetrics.ascent + delta2, overSize.ascent + bmOver.descent + delta1 + bmBase.ascent); aDesiredSize.height = aDesiredSize.ascent + baseSize.height - baseSize.ascent; aDesiredSize.width = mBoundingMetrics.width; aDesiredSize.mBoundingMetrics = mBoundingMetrics; mReference.x = 0; mReference.y = aDesiredSize.ascent; if (aPlaceOrigin) { // place base nscoord dy = aDesiredSize.ascent - baseSize.ascent; FinishReflowChild (baseFrame, PresContext(), nsnull, baseSize, dxBase, dy, 0); // place overscript dy = aDesiredSize.ascent - mBoundingMetrics.ascent + bmOver.ascent - overSize.ascent; FinishReflowChild (overFrame, PresContext(), nsnull, overSize, dxOver, dy, 0); } return NS_OK; }
nsresult FileManager::Init(nsIFile* aDirectory, mozIStorageConnection* aConnection) { NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aDirectory, "Null directory!"); NS_ASSERTION(aConnection, "Null connection!"); mFileInfos.Init(); bool exists; nsresult rv = aDirectory->Exists(&exists); NS_ENSURE_SUCCESS(rv, rv); if (exists) { bool isDirectory; rv = aDirectory->IsDirectory(&isDirectory); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE); } else { rv = aDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755); NS_ENSURE_SUCCESS(rv, rv); } rv = aDirectory->GetPath(mDirectoryPath); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIFile> journalDirectory; rv = aDirectory->Clone(getter_AddRefs(journalDirectory)); NS_ENSURE_SUCCESS(rv, rv); rv = journalDirectory->Append(NS_LITERAL_STRING(JOURNAL_DIRECTORY_NAME)); NS_ENSURE_SUCCESS(rv, rv); rv = journalDirectory->Exists(&exists); NS_ENSURE_SUCCESS(rv, rv); if (exists) { bool isDirectory; rv = journalDirectory->IsDirectory(&isDirectory); NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_TRUE(isDirectory, NS_ERROR_FAILURE); } rv = journalDirectory->GetPath(mJournalDirectoryPath); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<mozIStorageStatement> stmt; rv = aConnection->CreateStatement(NS_LITERAL_CSTRING( "SELECT id, refcount " "FROM file" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, rv); bool hasResult; while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) { int64_t id; rv = stmt->GetInt64(0, &id); NS_ENSURE_SUCCESS(rv, rv); int32_t refcount; rv = stmt->GetInt32(1, &refcount); NS_ENSURE_SUCCESS(rv, rv); NS_ASSERTION(refcount, "This shouldn't happen!"); nsRefPtr<FileInfo> fileInfo = FileInfo::Create(this, id); fileInfo->mDBRefCnt = refcount; mFileInfos.Put(id, fileInfo); mLastFileId = NS_MAX(id, mLastFileId); } return NS_OK; }
static void InflateRight(nsRect* aRect, nscoord aDelta) { aRect->width = NS_MAX(aRect->width + aDelta, 0); }
float Axis::GetAccelerationFactor() { return powf(gAccelerationMultiplier, NS_MAX(0, (mAcceleration - 4) * 3)); }
// exported routine that both munderover and msubsup share. // munderover uses this when movablelimits is set. nsresult nsMathMLmsubsupFrame::PlaceSubSupScript(nsPresContext* aPresContext, nsRenderingContext& aRenderingContext, PRBool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize, nsMathMLContainerFrame* aFrame, nscoord aUserSubScriptShift, nscoord aUserSupScriptShift, nscoord aScriptSpace) { // force the scriptSpace to be atleast 1 pixel nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1); aScriptSpace = NS_MAX(onePixel, aScriptSpace); //////////////////////////////////// // Get the children's desired sizes nsHTMLReflowMetrics baseSize; nsHTMLReflowMetrics subScriptSize; nsHTMLReflowMetrics supScriptSize; nsBoundingMetrics bmBase, bmSubScript, bmSupScript; nsIFrame* subScriptFrame = nsnull; nsIFrame* supScriptFrame = nsnull; nsIFrame* baseFrame = aFrame->GetFirstPrincipalChild(); if (baseFrame) subScriptFrame = baseFrame->GetNextSibling(); if (subScriptFrame) supScriptFrame = subScriptFrame->GetNextSibling(); if (!baseFrame || !subScriptFrame || !supScriptFrame || supScriptFrame->GetNextSibling()) { // report an error, encourage people to get their markups in order return aFrame->ReflowError(aRenderingContext, aDesiredSize); } GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); // get the subdrop from the subscript font nscoord subDrop; GetSubDropFromChild(subScriptFrame, subDrop); // parameter v, Rule 18a, App. G, TeXbook nscoord minSubScriptShift = bmBase.descent + subDrop; // get the supdrop from the supscript font nscoord supDrop; GetSupDropFromChild(supScriptFrame, supDrop); // parameter u, Rule 18a, App. G, TeXbook nscoord minSupScriptShift = bmBase.ascent - supDrop; ////////////////// // Place Children ////////////////// ////////////////////////////////////////////////// // Get subscript shift // slightly different from nsMathMLmsubFrame.cpp ////////////////////////////////////////////////// // subScriptShift{1,2} // = minimum amount to shift the subscript down // = sub{1,2} in TeXbook // subScriptShift1 = subscriptshift attribute * x-height nscoord subScriptShift1, subScriptShift2; nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(baseFrame, getter_AddRefs(fm)); aRenderingContext.SetFont(fm); // get x-height (an ex) nscoord xHeight = fm->XHeight(); nscoord ruleSize; GetRuleThickness (aRenderingContext, fm, ruleSize); // Get subScriptShift{1,2} default from font GetSubScriptShifts (fm, subScriptShift1, subScriptShift2); if (0 < aUserSubScriptShift) { // the user has set the subscriptshift attribute float scaler = ((float) subScriptShift2) / subScriptShift1; subScriptShift1 = NS_MAX(subScriptShift1, aUserSubScriptShift); subScriptShift2 = NSToCoordRound(scaler * subScriptShift1); } // get a tentative value for subscriptshift // Rule 18d, App. G, TeXbook nscoord subScriptShift = NS_MAX(minSubScriptShift,NS_MAX(subScriptShift1,subScriptShift2)); ////////////////////////////////////////////////// // Get supscript shift // same code from nsMathMLmsupFrame.cpp ////////////////////////////////////////////////// // get min supscript shift limit from x-height // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook nscoord minShiftFromXHeight = (nscoord) (bmSupScript.descent + (1.0f/4.0f) * xHeight); // supScriptShift{1,2,3} // = minimum amount to shift the supscript up // = sup{1,2,3} in TeX // supScriptShift1 = superscriptshift attribute * x-height // Note that there are THREE values for supscript shifts depending // on the current style nscoord supScriptShift1, supScriptShift2, supScriptShift3; // Set supScriptShift{1,2,3} default from font GetSupScriptShifts (fm, supScriptShift1, supScriptShift2, supScriptShift3); if (0 < aUserSupScriptShift) { // the user has set the superscriptshift attribute float scaler2 = ((float) supScriptShift2) / supScriptShift1; float scaler3 = ((float) supScriptShift3) / supScriptShift1; supScriptShift1 = NS_MAX(supScriptShift1, aUserSupScriptShift); supScriptShift2 = NSToCoordRound(scaler2 * supScriptShift1); supScriptShift3 = NSToCoordRound(scaler3 * supScriptShift1); } // get sup script shift depending on current script level and display style // Rule 18c, App. G, TeXbook nscoord supScriptShift; nsPresentationData presentationData; aFrame->GetPresentationData(presentationData); if ( aFrame->GetStyleFont()->mScriptLevel == 0 && NS_MATHML_IS_DISPLAYSTYLE(presentationData.flags) && !NS_MATHML_IS_COMPRESSED(presentationData.flags)) { // Style D in TeXbook supScriptShift = supScriptShift1; } else if (NS_MATHML_IS_COMPRESSED(presentationData.flags)) { // Style C' in TeXbook = D',T',S',SS' supScriptShift = supScriptShift3; } else { // everything else = T,S,SS supScriptShift = supScriptShift2; } // get tentative value for superscriptshift // Rule 18c, App. G, TeXbook supScriptShift = NS_MAX(minSupScriptShift,NS_MAX(supScriptShift,minShiftFromXHeight)); ////////////////////////////////////////////////// // Negotiate between supScriptShift and subScriptShift // so that there will be enough gap between them // Rule 18e, App. G, TeXbook ////////////////////////////////////////////////// nscoord gap = (supScriptShift - bmSupScript.descent) - (bmSubScript.ascent - subScriptShift); if (gap < 4.0f * ruleSize) { // adjust subScriptShift to get a gap of (4.0 * ruleSize) subScriptShift += NSToCoordRound ((4.0f * ruleSize) - gap); } // next we want to ensure that the bottom of the superscript // will be > (4/5) * x-height above baseline gap = NSToCoordRound ((4.0f/5.0f) * xHeight - (supScriptShift - bmSupScript.descent)); if (gap > 0) { supScriptShift += gap; subScriptShift -= gap; } ////////////////////////////////////////////////// // Do the Placing ////////////////////////////////////////////////// // get bounding box for base + subscript + superscript nsBoundingMetrics boundingMetrics; boundingMetrics.ascent = NS_MAX(bmBase.ascent, (bmSupScript.ascent + supScriptShift)); boundingMetrics.descent = NS_MAX(bmBase.descent, (bmSubScript.descent + subScriptShift)); // leave aScriptSpace after both super/subscript // add italicCorrection between base and superscript // add "a little to spare" as well (see TeXbook Ch.11, p.64), as we // estimate the italic creation ourselves and it isn't the same as TeX nscoord italicCorrection; GetItalicCorrection(bmBase, italicCorrection); italicCorrection += onePixel; boundingMetrics.width = bmBase.width + aScriptSpace + NS_MAX((italicCorrection + bmSupScript.width), bmSubScript.width); boundingMetrics.leftBearing = bmBase.leftBearing; boundingMetrics.rightBearing = bmBase.width + NS_MAX((italicCorrection + bmSupScript.rightBearing), bmSubScript.rightBearing); aFrame->SetBoundingMetrics(boundingMetrics); // reflow metrics aDesiredSize.ascent = NS_MAX(baseSize.ascent, NS_MAX(subScriptSize.ascent - subScriptShift, supScriptSize.ascent + supScriptShift)); aDesiredSize.height = aDesiredSize.ascent + NS_MAX(baseSize.height - baseSize.ascent, NS_MAX(subScriptSize.height - subScriptSize.ascent + subScriptShift, supScriptSize.height - subScriptSize.ascent - supScriptShift)); aDesiredSize.width = boundingMetrics.width; aDesiredSize.mBoundingMetrics = boundingMetrics; aFrame->SetReference(nsPoint(0, aDesiredSize.ascent)); if (aPlaceOrigin) { nscoord dx, dy; // now place the base ... dx = 0; dy = aDesiredSize.ascent - baseSize.ascent; FinishReflowChild(baseFrame, aPresContext, nsnull, baseSize, dx, dy, 0); // ... and subscript dx = bmBase.width; dy = aDesiredSize.ascent - (subScriptSize.ascent - subScriptShift); FinishReflowChild(subScriptFrame, aPresContext, nsnull, subScriptSize, dx, dy, 0); // ... and the superscript dx = bmBase.width + italicCorrection; dy = aDesiredSize.ascent - (supScriptSize.ascent + supScriptShift); FinishReflowChild(supScriptFrame, aPresContext, nsnull, supScriptSize, dx, dy, 0); } return NS_OK; }
/** * Box blur involves looking at one pixel, and setting its value to the average * of its neighbouring pixels. * @param aInput The input buffer. * @param aOutput The output buffer. * @param aLeftLobe The number of pixels to blend on the left. * @param aRightLobe The number of pixels to blend on the right. * @param aWidth The number of columns in the buffers. * @param aRows The number of rows in the buffers. * @param aSkipRect An area to skip blurring in. * XXX shouldn't we pass stride in separately here? */ static void BoxBlurHorizontal(unsigned char* aInput, unsigned char* aOutput, PRInt32 aLeftLobe, PRInt32 aRightLobe, PRInt32 aWidth, PRInt32 aRows, const nsIntRect& aSkipRect) { NS_ASSERTION(aWidth > 0, "Can't handle zero width here"); PRInt32 boxSize = aLeftLobe + aRightLobe + 1; PRBool skipRectCoversWholeRow = 0 >= aSkipRect.x && aWidth <= aSkipRect.XMost(); for (PRInt32 y = 0; y < aRows; y++) { // Check whether the skip rect intersects this row. If the skip // rect covers the whole surface in this row, we can avoid // this row entirely (and any others along the skip rect). PRBool inSkipRectY = y >= aSkipRect.y && y < aSkipRect.YMost(); if (inSkipRectY && skipRectCoversWholeRow) { y = aSkipRect.YMost() - 1; continue; } PRInt32 alphaSum = 0; for (PRInt32 i = 0; i < boxSize; i++) { PRInt32 pos = i - aLeftLobe; // See assertion above; if aWidth is zero, then we would have no // valid position to clamp to. pos = NS_MAX(pos, 0); pos = NS_MIN(pos, aWidth - 1); alphaSum += aInput[aWidth * y + pos]; } for (PRInt32 x = 0; x < aWidth; x++) { // Check whether we are within the skip rect. If so, go // to the next point outside the skip rect. if (inSkipRectY && x >= aSkipRect.x && x < aSkipRect.XMost()) { x = aSkipRect.XMost(); if (x >= aWidth) break; // Recalculate the neighbouring alpha values for // our new point on the surface. alphaSum = 0; for (PRInt32 i = 0; i < boxSize; i++) { PRInt32 pos = x + i - aLeftLobe; // See assertion above; if aWidth is zero, then we would have no // valid position to clamp to. pos = NS_MAX(pos, 0); pos = NS_MIN(pos, aWidth - 1); alphaSum += aInput[aWidth * y + pos]; } } PRInt32 tmp = x - aLeftLobe; PRInt32 last = NS_MAX(tmp, 0); PRInt32 next = NS_MIN(tmp + boxSize, aWidth - 1); aOutput[aWidth * y + x] = alphaSum/boxSize; alphaSum += aInput[aWidth * y + next] - aInput[aWidth * y + last]; } } }
nsresult nsTableOuterFrame::GetCaptionOrigin(PRUint32 aCaptionSide, const nsSize& aContainBlockSize, const nsSize& aInnerSize, const nsMargin& aInnerMargin, const nsSize& aCaptionSize, nsMargin& aCaptionMargin, nsPoint& aOrigin) { aOrigin.x = aOrigin.y = 0; if ((NS_UNCONSTRAINEDSIZE == aInnerSize.width) || (NS_UNCONSTRAINEDSIZE == aInnerSize.height) || (NS_UNCONSTRAINEDSIZE == aCaptionSize.width) || (NS_UNCONSTRAINEDSIZE == aCaptionSize.height)) { return NS_OK; } if (mCaptionFrames.IsEmpty()) return NS_OK; NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.left, "The computed caption margin is auto?"); NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.top, "The computed caption margin is auto?"); NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.bottom, "The computed caption margin is auto?"); // horizontal computation switch(aCaptionSide) { case NS_STYLE_CAPTION_SIDE_BOTTOM: case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: { // FIXME: Position relative to right edge for RTL. (Based on table // direction or table parent direction?) aOrigin.x = aCaptionMargin.left; if (aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) { // We placed the caption using only the table's width as available // width, and we should position it this way as well. aOrigin.x += aInnerMargin.left; } } break; case NS_STYLE_CAPTION_SIDE_LEFT: { aOrigin.x = aCaptionMargin.left; } break; case NS_STYLE_CAPTION_SIDE_RIGHT: { aOrigin.x = aInnerMargin.left + aInnerSize.width + aCaptionMargin.left; } break; default: { // top NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP || aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE, "unexpected caption side"); // FIXME: Position relative to right edge for RTL. (Based on table // direction or table parent direction?) aOrigin.x = aCaptionMargin.left; if (aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP) { // We placed the caption using only the table's width as available // width, and we should position it this way as well. aOrigin.x += aInnerMargin.left; } } break; } // vertical computation switch (aCaptionSide) { case NS_STYLE_CAPTION_SIDE_RIGHT: case NS_STYLE_CAPTION_SIDE_LEFT: aOrigin.y = aInnerMargin.top; switch (GetCaptionVerticalAlign()) { case NS_STYLE_VERTICAL_ALIGN_MIDDLE: aOrigin.y = NS_MAX(0, aInnerMargin.top + ((aInnerSize.height - aCaptionSize.height) / 2)); break; case NS_STYLE_VERTICAL_ALIGN_BOTTOM: aOrigin.y = NS_MAX(0, aInnerMargin.top + aInnerSize.height - aCaptionSize.height); break; default: break; } break; case NS_STYLE_CAPTION_SIDE_BOTTOM: { aOrigin.y = aInnerMargin.top + aInnerSize.height + aCaptionMargin.top; } break; case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: { nsCollapsingMargin marg; marg.Include(aCaptionMargin.top); marg.Include(aInnerMargin.bottom); nscoord collapseMargin = marg.get(); aOrigin.y = aInnerMargin.top + aInnerSize.height + collapseMargin; } break; case NS_STYLE_CAPTION_SIDE_TOP: { aOrigin.y = aInnerMargin.top + aCaptionMargin.top; } break; case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: { aOrigin.y = aCaptionMargin.top; } break; default: NS_NOTREACHED("Unknown caption alignment type"); break; } return NS_OK; }
nsresult OpenDatabaseHelper::DoDatabaseWork() { #ifdef DEBUG { bool correctThread; NS_ASSERTION(NS_SUCCEEDED(IndexedDatabaseManager::Get()->IOThread()-> IsOnCurrentThread(&correctThread)) && correctThread, "Running on the wrong thread!"); } #endif mState = eFiringEvents; // In case we fail somewhere along the line. if (IndexedDatabaseManager::IsShuttingDown()) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } nsCOMPtr<nsIFile> dbFile; nsresult rv = GetDatabaseFile(mASCIIOrigin, mName, getter_AddRefs(dbFile)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); rv = dbFile->GetPath(mDatabaseFilePath); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsCOMPtr<nsIFile> dbDirectory; rv = dbFile->GetParent(getter_AddRefs(dbDirectory)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); bool exists; rv = dbDirectory->Exists(&exists); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (exists) { bool isDirectory; rv = dbDirectory->IsDirectory(&isDirectory); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); NS_ENSURE_TRUE(isDirectory, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } else { rv = dbDirectory->Create(nsIFile::DIRECTORY_TYPE, 0755); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); } IndexedDatabaseManager* mgr = IndexedDatabaseManager::Get(); NS_ASSERTION(mgr, "This should never be null!"); rv = mgr->EnsureQuotaManagementForDirectory(dbDirectory); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); nsCOMPtr<mozIStorageConnection> connection; rv = CreateDatabaseConnection(mName, dbFile, getter_AddRefs(connection)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); // Get the data version. nsCOMPtr<mozIStorageStatement> stmt; rv = connection->CreateStatement(NS_LITERAL_CSTRING( "SELECT dataVersion " "FROM database" ), getter_AddRefs(stmt)); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); bool hasResult; rv = stmt->ExecuteStep(&hasResult); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (!hasResult) { NS_ERROR("Database has no dataVersion!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } PRInt64 dataVersion; rv = stmt->GetInt64(0, &dataVersion); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); if (dataVersion > JS_STRUCTURED_CLONE_VERSION) { NS_ERROR("Bad data version!"); return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } if (dataVersion < JS_STRUCTURED_CLONE_VERSION) { // Need to upgrade the database, here, before returning to the main thread. NS_NOTYETIMPLEMENTED("Implement me!"); } rv = IDBFactory::LoadDatabaseInformation(connection, mDatabaseId, &mCurrentVersion, mObjectStores); NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); for (PRUint32 i = 0; i < mObjectStores.Length(); i++) { nsAutoPtr<ObjectStoreInfo>& objectStoreInfo = mObjectStores[i]; for (PRUint32 j = 0; j < objectStoreInfo->indexes.Length(); j++) { IndexInfo& indexInfo = objectStoreInfo->indexes[j]; mLastIndexId = NS_MAX(indexInfo.id, mLastIndexId); } mLastObjectStoreId = NS_MAX(objectStoreInfo->id, mLastObjectStoreId); } // See if we need to do a VERSION_CHANGE transaction // Optional version semantics. if (!mRequestedVersion) { // If the requested version was not specified and the database was created, // treat it as if version 1 were requested. if (mCurrentVersion == 0) { mRequestedVersion = 1; } else { // Otherwise, treat it as if the current version were requested. mRequestedVersion = mCurrentVersion; } } if (mCurrentVersion > mRequestedVersion) { return NS_ERROR_DOM_INDEXEDDB_VERSION_ERR; } if (mCurrentVersion != mRequestedVersion) { mState = eSetVersionPending; } return NS_OK; }
nsresult nsTableOuterFrame::GetInnerOrigin(PRUint32 aCaptionSide, const nsSize& aContainBlockSize, const nsSize& aCaptionSize, const nsMargin& aCaptionMargin, const nsSize& aInnerSize, nsMargin& aInnerMargin, nsPoint& aOrigin) { NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.left, "The computed caption margin is auto?"); NS_ASSERTION(NS_AUTOMARGIN != aCaptionMargin.right, "The computed caption margin is auto?"); NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.left, "The computed inner margin is auto?"); NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.right, "The computed inner margin is auto?"); NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.top, "The computed inner margin is auto?"); NS_ASSERTION(NS_AUTOMARGIN != aInnerMargin.bottom, "The computed inner margin is auto?"); aOrigin.x = aOrigin.y = 0; if ((NS_UNCONSTRAINEDSIZE == aInnerSize.width) || (NS_UNCONSTRAINEDSIZE == aInnerSize.height) || (NS_UNCONSTRAINEDSIZE == aCaptionSize.width) || (NS_UNCONSTRAINEDSIZE == aCaptionSize.height)) { return NS_OK; } nscoord minCapWidth = aCaptionSize.width; minCapWidth += aCaptionMargin.left; minCapWidth += aCaptionMargin.right; // horizontal computation switch (aCaptionSide) { case NS_STYLE_CAPTION_SIDE_LEFT: { if (aInnerMargin.left < minCapWidth) { // shift the inner table to get some place for the caption aInnerMargin.right += aInnerMargin.left - minCapWidth; aInnerMargin.right = NS_MAX(0, aInnerMargin.right); aInnerMargin.left = minCapWidth; } aOrigin.x = aInnerMargin.left; } break; default: { NS_ASSERTION(aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP || aCaptionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE || aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM || aCaptionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE || aCaptionSide == NS_STYLE_CAPTION_SIDE_RIGHT || aCaptionSide == NO_SIDE, "unexpected caption side"); aOrigin.x = aInnerMargin.left; } break; } // vertical computation switch (aCaptionSide) { case NS_STYLE_CAPTION_SIDE_BOTTOM: case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: { aOrigin.y = aInnerMargin.top; } break; case NS_STYLE_CAPTION_SIDE_LEFT: case NS_STYLE_CAPTION_SIDE_RIGHT: { aOrigin.y = aInnerMargin.top; switch (GetCaptionVerticalAlign()) { case NS_STYLE_VERTICAL_ALIGN_MIDDLE: aOrigin.y = NS_MAX(aInnerMargin.top, (aCaptionSize.height - aInnerSize.height) / 2); break; case NS_STYLE_VERTICAL_ALIGN_BOTTOM: aOrigin.y = NS_MAX(aInnerMargin.top, aCaptionSize.height - aInnerSize.height); break; default: break; } } break; case NO_SIDE: case NS_STYLE_CAPTION_SIDE_TOP: { aOrigin.y = aInnerMargin.top + aCaptionMargin.top + aCaptionSize.height + aCaptionMargin.bottom; } break; case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: { nsCollapsingMargin marg; marg.Include(aCaptionMargin.bottom); marg.Include(aInnerMargin.top); nscoord collapseMargin = marg.get(); aOrigin.y = aCaptionMargin.top + aCaptionSize.height + collapseMargin; } break; default: NS_NOTREACHED("Unknown caption alignment type"); break; } return NS_OK; }
/* virtual */ nsresult nsMathMLmpaddedFrame::Place(nsRenderingContext& aRenderingContext, bool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { nsresult rv = nsMathMLContainerFrame::Place(aRenderingContext, false, aDesiredSize); if (NS_MATHML_HAS_ERROR(mPresentationData.flags) || NS_FAILED(rv)) { DidReflowChildren(GetFirstPrincipalChild()); return rv; } nscoord height = mBoundingMetrics.ascent; nscoord depth = mBoundingMetrics.descent; // The REC says: // // "The lspace attribute ('leading' space) specifies the horizontal location // of the positioning point of the child content with respect to the // positioning point of the mpadded element. By default they coincide, and // therefore absolute values for lspace have the same effect as relative // values." // // "MathML renderers should ensure that, except for the effects of the // attributes, the relative spacing between the contents of the mpadded // element and surrounding MathML elements would not be modified by replacing // an mpadded element with an mrow element with the same content, even if // linebreaking occurs within the mpadded element." // // (http://www.w3.org/TR/MathML/chapter3.html#presm.mpadded) // // "In those discussions, the terms leading and trailing are used to specify // a side of an object when which side to use depends on the directionality; // ie. leading means left in LTR but right in RTL." // (http://www.w3.org/TR/MathML/chapter3.html#presm.bidi.math) nscoord lspace = 0; // In MathML3, "width" will be the bounding box width and "advancewidth" will // refer "to the horizontal distance between the positioning point of the // mpadded and the positioning point for the following content". MathML2 // doesn't make the distinction. nscoord width = mBoundingMetrics.width; nscoord voffset = 0; int32_t pseudoUnit; nscoord initialWidth = width; // update width pseudoUnit = (mWidthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF) ? NS_MATHML_PSEUDO_UNIT_WIDTH : mWidthPseudoUnit; UpdateValue(mWidthSign, pseudoUnit, mWidth, mBoundingMetrics, width); width = NS_MAX(0, width); // update "height" (this is the ascent in the terminology of the REC) pseudoUnit = (mHeightPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF) ? NS_MATHML_PSEUDO_UNIT_HEIGHT : mHeightPseudoUnit; UpdateValue(mHeightSign, pseudoUnit, mHeight, mBoundingMetrics, height); height = NS_MAX(0, height); // update "depth" (this is the descent in the terminology of the REC) pseudoUnit = (mDepthPseudoUnit == NS_MATHML_PSEUDO_UNIT_ITSELF) ? NS_MATHML_PSEUDO_UNIT_DEPTH : mDepthPseudoUnit; UpdateValue(mDepthSign, pseudoUnit, mDepth, mBoundingMetrics, depth); depth = NS_MAX(0, depth); // update lspace if (mLeadingSpacePseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) { pseudoUnit = mLeadingSpacePseudoUnit; UpdateValue(mLeadingSpaceSign, pseudoUnit, mLeadingSpace, mBoundingMetrics, lspace); } // update voffset if (mVerticalOffsetPseudoUnit != NS_MATHML_PSEUDO_UNIT_ITSELF) { pseudoUnit = mVerticalOffsetPseudoUnit; UpdateValue(mVerticalOffsetSign, pseudoUnit, mVerticalOffset, mBoundingMetrics, voffset); } // do the padding now that we have everything // The idea here is to maintain the invariant that <mpadded>...</mpadded> (i.e., // with no attributes) looks the same as <mrow>...</mrow>. But when there are // attributes, tweak our metrics and move children to achieve the desired visual // effects. if ((NS_MATHML_IS_RTL(mPresentationData.flags) ? mWidthSign : mLeadingSpaceSign) != NS_MATHML_SIGN_INVALID) { // there was padding on the left. dismiss the left italic correction now // (so that our parent won't correct us) mBoundingMetrics.leftBearing = 0; } if ((NS_MATHML_IS_RTL(mPresentationData.flags) ? mLeadingSpaceSign : mWidthSign) != NS_MATHML_SIGN_INVALID) { // there was padding on the right. dismiss the right italic correction now // (so that our parent won't correct us) mBoundingMetrics.width = width; mBoundingMetrics.rightBearing = mBoundingMetrics.width; } nscoord dy = height - mBoundingMetrics.ascent; nscoord dx = NS_MATHML_IS_RTL(mPresentationData.flags) ? width - initialWidth - lspace : lspace; aDesiredSize.ascent += dy; aDesiredSize.width = mBoundingMetrics.width; aDesiredSize.height += dy + depth - mBoundingMetrics.descent; mBoundingMetrics.ascent = height; mBoundingMetrics.descent = depth; aDesiredSize.mBoundingMetrics = mBoundingMetrics; mReference.x = 0; mReference.y = aDesiredSize.ascent; if (aPlaceOrigin) { // Finish reflowing child frames, positioning their origins. PositionRowChildFrames(dx, aDesiredSize.ascent - voffset); } return NS_OK; }
NS_METHOD nsTableOuterFrame::Reflow(nsPresContext* aPresContext, nsHTMLReflowMetrics& aDesiredSize, const nsHTMLReflowState& aOuterRS, nsReflowStatus& aStatus) { DO_GLOBAL_REFLOW_COUNT("nsTableOuterFrame"); DISPLAY_REFLOW(aPresContext, this, aOuterRS, aDesiredSize, aStatus); nsresult rv = NS_OK; PRUint8 captionSide = GetCaptionSide(); // Initialize out parameters aDesiredSize.width = aDesiredSize.height = 0; aStatus = NS_FRAME_COMPLETE; if (!(GetStateBits() & NS_FRAME_FIRST_REFLOW)) { // Set up our kids. They're already present, on an overflow list, // or there are none so we'll create them now MoveOverflowToChildList(aPresContext); } // Use longs to get more-aligned space. #define LONGS_IN_HTMLRS \ ((sizeof(nsHTMLReflowState) + sizeof(long) - 1) / sizeof(long)) long captionRSSpace[LONGS_IN_HTMLRS]; nsHTMLReflowState *captionRS = static_cast<nsHTMLReflowState*>((void*)captionRSSpace); long innerRSSpace[LONGS_IN_HTMLRS]; nsHTMLReflowState *innerRS = static_cast<nsHTMLReflowState*>((void*) innerRSSpace); nsRect origInnerRect = InnerTableFrame()->GetRect(); nsRect origInnerVisualOverflow = InnerTableFrame()->GetVisualOverflowRect(); PRBool innerFirstReflow = (InnerTableFrame()->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0; nsRect origCaptionRect; nsRect origCaptionVisualOverflow; PRBool captionFirstReflow; if (mCaptionFrames.NotEmpty()) { origCaptionRect = mCaptionFrames.FirstChild()->GetRect(); origCaptionVisualOverflow = mCaptionFrames.FirstChild()->GetVisualOverflowRect(); captionFirstReflow = (mCaptionFrames.FirstChild()->GetStateBits() & NS_FRAME_FIRST_REFLOW) != 0; } // ComputeAutoSize has to match this logic. if (captionSide == NO_SIDE) { // We don't have a caption. OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS, innerRSSpace, aOuterRS.ComputedWidth()); } else if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT || captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) { // nsTableCaptionFrame::ComputeAutoSize takes care of making side // captions small. Compute the caption's size first, and tell the // table to fit in what's left. OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS, captionRSSpace, aOuterRS.ComputedWidth()); nscoord innerAvailWidth = aOuterRS.ComputedWidth() - (captionRS->ComputedWidth() + captionRS->mComputedMargin.LeftRight() + captionRS->mComputedBorderPadding.LeftRight()); OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS, innerRSSpace, innerAvailWidth); } else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP || captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) { // Compute the table's size first, and then prevent the caption from // being wider unless it has to be. // // Note that CSS 2.1 (but not 2.0) says: // The width of the anonymous box is the border-edge width of the // table box inside it // We don't actually make our anonymous box that width (if we did, // it would break 'auto' margins), but this effectively does that. OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS, innerRSSpace, aOuterRS.ComputedWidth()); // It's good that CSS 2.1 says not to include margins, since we // can't, since they already been converted so they exactly // fill the available width (ignoring the margin on one side if // neither are auto). (We take advantage of that later when we call // GetCaptionOrigin, though.) nscoord innerBorderWidth = innerRS->ComputedWidth() + innerRS->mComputedBorderPadding.LeftRight(); OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS, captionRSSpace, innerBorderWidth); } else { NS_ASSERTION(captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE || captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE, "unexpected caption-side"); // Size the table and the caption independently. OuterBeginReflowChild(aPresContext, mCaptionFrames.FirstChild(), aOuterRS, captionRSSpace, aOuterRS.ComputedWidth()); OuterBeginReflowChild(aPresContext, InnerTableFrame(), aOuterRS, innerRSSpace, aOuterRS.ComputedWidth()); } // First reflow the caption. nsHTMLReflowMetrics captionMet; nsSize captionSize; nsMargin captionMargin; if (mCaptionFrames.NotEmpty()) { nsReflowStatus capStatus; // don't let the caption cause incomplete rv = OuterDoReflowChild(aPresContext, mCaptionFrames.FirstChild(), *captionRS, captionMet, capStatus); if (NS_FAILED(rv)) return rv; captionSize.width = captionMet.width; captionSize.height = captionMet.height; captionMargin = captionRS->mComputedMargin; // Now that we know the height of the caption, reduce the available height // for the table frame if we are height constrained and the caption is above // or below the inner table. if (NS_UNCONSTRAINEDSIZE != aOuterRS.availableHeight) { nscoord captionHeight = 0; switch (captionSide) { case NS_STYLE_CAPTION_SIDE_TOP: case NS_STYLE_CAPTION_SIDE_BOTTOM: { captionHeight = captionSize.height + captionMargin.TopBottom(); break; } case NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE: { nsCollapsingMargin belowCaptionMargin; belowCaptionMargin.Include(captionMargin.bottom); belowCaptionMargin.Include(innerRS->mComputedMargin.top); captionHeight = captionSize.height + captionMargin.top + belowCaptionMargin.get(); break; } case NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE: { nsCollapsingMargin aboveCaptionMargin; aboveCaptionMargin.Include(captionMargin.top); aboveCaptionMargin.Include(innerRS->mComputedMargin.bottom); captionHeight = captionSize.height + captionMargin.bottom + aboveCaptionMargin.get(); break; } } innerRS->availableHeight = NS_MAX(0, innerRS->availableHeight - captionHeight); } } else { captionSize.SizeTo(0,0); captionMargin.SizeTo(0,0,0,0); } // Then, now that we know how much to reduce the width of the inner // table to account for side captions, reflow the inner table. nsHTMLReflowMetrics innerMet; rv = OuterDoReflowChild(aPresContext, InnerTableFrame(), *innerRS, innerMet, aStatus); if (NS_FAILED(rv)) return rv; nsSize innerSize; innerSize.width = innerMet.width; innerSize.height = innerMet.height; nsMargin innerMargin = innerRS->mComputedMargin; nsSize containSize = GetContainingBlockSize(aOuterRS); // Now that we've reflowed both we can place them. // XXXldb Most of the input variables here are now uninitialized! // XXX Need to recompute inner table's auto margins for the case of side // captions. (Caption's are broken too, but that should be fixed earlier.) if (mCaptionFrames.NotEmpty()) { nsPoint captionOrigin; GetCaptionOrigin(captionSide, containSize, innerSize, innerMargin, captionSize, captionMargin, captionOrigin); FinishReflowChild(mCaptionFrames.FirstChild(), aPresContext, captionRS, captionMet, captionOrigin.x, captionOrigin.y, 0); captionRS->~nsHTMLReflowState(); } // XXX If the height is constrained then we need to check whether // everything still fits... nsPoint innerOrigin; GetInnerOrigin(captionSide, containSize, captionSize, captionMargin, innerSize, innerMargin, innerOrigin); FinishReflowChild(InnerTableFrame(), aPresContext, innerRS, innerMet, innerOrigin.x, innerOrigin.y, 0); innerRS->~nsHTMLReflowState(); nsTableFrame::InvalidateFrame(InnerTableFrame(), origInnerRect, origInnerVisualOverflow, innerFirstReflow); if (mCaptionFrames.NotEmpty()) { nsTableFrame::InvalidateFrame(mCaptionFrames.FirstChild(), origCaptionRect, origCaptionVisualOverflow, captionFirstReflow); } UpdateReflowMetrics(captionSide, aDesiredSize, innerMargin, captionMargin); // Return our desired rect NS_FRAME_SET_TRUNCATION(aStatus, aOuterRS, aDesiredSize); return rv; }
nsresult nsTextControlFrame::CalcIntrinsicSize(nsRenderingContext* aRenderingContext, nsSize& aIntrinsicSize) { // Get leading and the Average/MaxAdvance char width nscoord lineHeight = 0; nscoord charWidth = 0; nscoord charMaxAdvance = 0; nsRefPtr<nsFontMetrics> fontMet; nsresult rv = nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); NS_ENSURE_SUCCESS(rv, rv); aRenderingContext->SetFont(fontMet); lineHeight = nsHTMLReflowState::CalcLineHeight(GetStyleContext(), NS_AUTOHEIGHT); charWidth = fontMet->AveCharWidth(); charMaxAdvance = fontMet->MaxAdvance(); // Set the width equal to the width in characters PRInt32 cols = GetCols(); aIntrinsicSize.width = cols * charWidth; // To better match IE, take the maximum character width(in twips) and remove // 4 pixels add this on as additional padding(internalPadding). But only do // this if charMaxAdvance != charWidth; if they are equal, this is almost // certainly a fixed-width font. if (charWidth != charMaxAdvance) { nscoord internalPadding = NS_MAX(0, charMaxAdvance - nsPresContext::CSSPixelsToAppUnits(4)); nscoord t = nsPresContext::CSSPixelsToAppUnits(1); // Round to a multiple of t nscoord rest = internalPadding % t; if (rest < t - rest) { internalPadding -= rest; } else { internalPadding += t - rest; } // Now add the extra padding on (so that small input sizes work well) aIntrinsicSize.width += internalPadding; } else { // This is to account for the anonymous <br> having a 1 twip width // in Full Standards mode, see BRFrame::Reflow and bug 228752. if (PresContext()->CompatibilityMode() == eCompatibility_FullStandards) { aIntrinsicSize.width += 1; } // Also add in the padding of our value div child. Note that it hasn't // been reflowed yet, so we can't get its used padding, but it shouldn't be // using percentage padding anyway. nsMargin childPadding; nsIFrame* firstChild = GetFirstChild(nsnull); if (firstChild && firstChild->GetStylePadding()->GetPadding(childPadding)) { aIntrinsicSize.width += childPadding.LeftRight(); } else { NS_ERROR("Percentage padding on value div?"); } } // Increment width with cols * letter-spacing. { const nsStyleCoord& lsCoord = GetStyleText()->mLetterSpacing; if (eStyleUnit_Coord == lsCoord.GetUnit()) { nscoord letterSpacing = lsCoord.GetCoordValue(); if (letterSpacing != 0) { aIntrinsicSize.width += cols * letterSpacing; } } } // Set the height equal to total number of rows (times the height of each // line, of course) aIntrinsicSize.height = lineHeight * GetRows(); // Add in the size of the scrollbars for textarea if (IsTextArea()) { nsIFrame* first = GetFirstChild(nsnull); nsIScrollableFrame *scrollableFrame = do_QueryFrame(first); NS_ASSERTION(scrollableFrame, "Child must be scrollable"); if (scrollableFrame) { nsMargin scrollbarSizes = scrollableFrame->GetDesiredScrollbarSizes(PresContext(), aRenderingContext); aIntrinsicSize.width += scrollbarSizes.LeftRight(); aIntrinsicSize.height += scrollbarSizes.TopBottom();; } } return NS_OK; }
void nsGridRowLeafLayout::PopulateBoxSizes(nsIBox* aBox, nsBoxLayoutState& aState, nsBoxSize*& aBoxSizes, nscoord& aMinSize, nscoord& aMaxSize, PRInt32& aFlexes) { PRInt32 index = 0; nsGrid* grid = GetGrid(aBox, &index); PRBool isHorizontal = IsHorizontal(aBox); // Our base class SprocketLayout is giving us a chance to change the box sizes before layout // If we are a row lets change the sizes to match our columns. If we are a column then do the opposite // and make them match or rows. if (grid) { nsGridRow* column; PRInt32 count = grid->GetColumnCount(isHorizontal); nsBoxSize* start = nsnull; nsBoxSize* last = nsnull; nsBoxSize* current = nsnull; nsIBox* child = aBox->GetChildBox(); for (int i=0; i < count; i++) { column = grid->GetColumnAt(i,isHorizontal); // make sure the value was computed before we use it. // !isHorizontal is passed in to invert the behavior of these methods. nscoord pref = grid->GetPrefRowHeight(aState, i, !isHorizontal); // GetPrefColumnWidth nscoord min = grid->GetMinRowHeight(aState, i, !isHorizontal); // GetMinColumnWidth nscoord max = grid->GetMaxRowHeight(aState, i, !isHorizontal); // GetMaxColumnWidth nscoord flex = grid->GetRowFlex(aState, i, !isHorizontal); // GetColumnFlex nscoord left = 0; nscoord right = 0; grid->GetRowOffsets(aState, i, left, right, !isHorizontal); // GetColumnOffsets nsIBox* box = column->GetBox(); PRBool collapsed = PR_FALSE; nscoord topMargin = column->mTopMargin; nscoord bottomMargin = column->mBottomMargin; if (box) collapsed = box->IsCollapsed(aState); pref = pref - (left + right); if (pref < 0) pref = 0; // if this is the first or last column. Take into account that // our row could have a border that could affect our left or right // padding from our columns. If the row has padding subtract it. // would should always be able to garentee that our margin is smaller // or equal to our left or right PRInt32 firstIndex = 0; PRInt32 lastIndex = 0; nsGridRow* firstRow = nsnull; nsGridRow* lastRow = nsnull; grid->GetFirstAndLastRow(aState, firstIndex, lastIndex, firstRow, lastRow, !isHorizontal); if (i == firstIndex || i == lastIndex) { nsMargin offset = GetTotalMargin(aBox, isHorizontal); nsMargin border(0,0,0,0); // can't call GetBorderPadding we will get into recursion aBox->GetBorder(border); offset += border; aBox->GetPadding(border); offset += border; // subtract from out left and right if (i == firstIndex) { if (isHorizontal) left -= offset.left; else left -= offset.top; } if (i == lastIndex) { if (isHorizontal) right -= offset.right; else right -= offset.bottom; } } // initialize the box size here max = NS_MAX(min, max); pref = nsBox::BoundsCheck(min, pref, max); current = new (aState) nsBoxSize(); current->pref = pref; current->min = min; current->max = max; current->flex = flex; current->bogus = column->mIsBogus; current->left = left + topMargin; current->right = right + bottomMargin; current->collapsed = collapsed; if (!start) { start = current; last = start; } else { last->next = current; last = current; } if (child && !column->mIsBogus) child = child->GetNextBox(); } aBoxSizes = start; } nsSprocketLayout::PopulateBoxSizes(aBox, aState, aBoxSizes, aMinSize, aMaxSize, aFlexes); }
void nsProgressFrame::ReflowBarFrame(nsIFrame* aBarFrame, nsPresContext* aPresContext, const nsHTMLReflowState& aReflowState, nsReflowStatus& aStatus) { bool vertical = GetStyleDisplay()->mOrient == NS_STYLE_ORIENT_VERTICAL; nsHTMLReflowState reflowState(aPresContext, aReflowState, aBarFrame, nsSize(aReflowState.ComputedWidth(), NS_UNCONSTRAINEDSIZE)); nscoord size = vertical ? aReflowState.ComputedHeight() : aReflowState.ComputedWidth(); nscoord xoffset = aReflowState.mComputedBorderPadding.left; nscoord yoffset = aReflowState.mComputedBorderPadding.top; double position; nsCOMPtr<nsIDOMHTMLProgressElement> progressElement = do_QueryInterface(mContent); progressElement->GetPosition(&position); // Force the bar's size to match the current progress. // When indeterminate, the progress' size will be 100%. if (position >= 0.0) { size *= position; } if (!vertical && GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { xoffset += aReflowState.ComputedWidth() - size; } // The bar size is fixed in these cases: // - the progress position is determined: the bar size is fixed according // to it's value. // - the progress position is indeterminate and the bar appearance should be // shown as native: the bar size is forced to 100%. // Otherwise (when the progress is indeterminate and the bar appearance isn't // native), the bar size isn't fixed and can be set by the author. if (position != -1 || ShouldUseNativeStyle()) { if (vertical) { // We want the bar to begin at the bottom. yoffset += aReflowState.ComputedHeight() - size; size -= reflowState.mComputedMargin.TopBottom() + reflowState.mComputedBorderPadding.TopBottom(); size = NS_MAX(size, 0); reflowState.SetComputedHeight(size); } else { size -= reflowState.mComputedMargin.LeftRight() + reflowState.mComputedBorderPadding.LeftRight(); size = NS_MAX(size, 0); reflowState.SetComputedWidth(size); } } else if (vertical) { // For vertical progress bars, we need to position the bar specificly when // the width isn't constrained (position == -1 and !ShouldUseNativeStyle()) // because aReflowState.ComputedHeight() - size == 0. yoffset += aReflowState.ComputedHeight() - reflowState.ComputedHeight(); } xoffset += reflowState.mComputedMargin.left; yoffset += reflowState.mComputedMargin.top; nsHTMLReflowMetrics barDesiredSize; ReflowChild(aBarFrame, aPresContext, barDesiredSize, reflowState, xoffset, yoffset, 0, aStatus); FinishReflowChild(aBarFrame, aPresContext, &reflowState, barDesiredSize, xoffset, yoffset, 0); }
/* virtual */ nsresult nsMathMLmmultiscriptsFrame::Place(nsRenderingContext& aRenderingContext, bool aPlaceOrigin, nsHTMLReflowMetrics& aDesiredSize) { //////////////////////////////////// // Get the children's desired sizes nscoord minShiftFromXHeight, subDrop, supDrop; //////////////////////////////////////// // Initialize super/sub shifts that // depend only on the current font //////////////////////////////////////// ProcessAttributes(); // get x-height (an ex) const nsStyleFont* font = GetStyleFont(); nsRefPtr<nsFontMetrics> fm; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fm)); aRenderingContext.SetFont(fm); nscoord xHeight = fm->XHeight(); nscoord ruleSize; GetRuleThickness (aRenderingContext, fm, ruleSize); // scriptspace from TeX for extra spacing after sup/subscript (0.5pt in plain TeX) // forced to be at least 1 pixel here nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1); nscoord scriptSpace = NS_MAX(nsPresContext::CSSPointsToAppUnits(0.5f), onePixel); ///////////////////////////////////// // first the shift for the subscript // subScriptShift{1,2} // = minimum amount to shift the subscript down // = sub{1,2} in TeXbook // subScriptShift1 = subscriptshift attribute * x-height nscoord subScriptShift1, subScriptShift2; // Get subScriptShift{1,2} default from font GetSubScriptShifts (fm, subScriptShift1, subScriptShift2); if (0 < mSubScriptShift) { // the user has set the subscriptshift attribute float scaler = ((float) subScriptShift2) / subScriptShift1; subScriptShift1 = NS_MAX(subScriptShift1, mSubScriptShift); subScriptShift2 = NSToCoordRound(scaler * subScriptShift1); } // the font dependent shift nscoord subScriptShift = NS_MAX(subScriptShift1,subScriptShift2); ///////////////////////////////////// // next the shift for the superscript // supScriptShift{1,2,3} // = minimum amount to shift the supscript up // = sup{1,2,3} in TeX // supScriptShift1 = superscriptshift attribute * x-height // Note that there are THREE values for supscript shifts depending // on the current style nscoord supScriptShift1, supScriptShift2, supScriptShift3; // Set supScriptShift{1,2,3} default from font GetSupScriptShifts (fm, supScriptShift1, supScriptShift2, supScriptShift3); if (0 < mSupScriptShift) { // the user has set the superscriptshift attribute float scaler2 = ((float) supScriptShift2) / supScriptShift1; float scaler3 = ((float) supScriptShift3) / supScriptShift1; supScriptShift1 = NS_MAX(supScriptShift1, mSupScriptShift); supScriptShift2 = NSToCoordRound(scaler2 * supScriptShift1); supScriptShift3 = NSToCoordRound(scaler3 * supScriptShift1); } // get sup script shift depending on current script level and display style // Rule 18c, App. G, TeXbook nscoord supScriptShift; if ( font->mScriptLevel == 0 && NS_MATHML_IS_DISPLAYSTYLE(mPresentationData.flags) && !NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style D in TeXbook supScriptShift = supScriptShift1; } else if (NS_MATHML_IS_COMPRESSED(mPresentationData.flags)) { // Style C' in TeXbook = D',T',S',SS' supScriptShift = supScriptShift3; } else { // everything else = T,S,SS supScriptShift = supScriptShift2; } //////////////////////////////////// // Get the children's sizes //////////////////////////////////// nscoord width = 0, prescriptsWidth = 0, rightBearing = 0; nsIFrame* mprescriptsFrame = nsnull; // frame of <mprescripts/>, if there. bool isSubScript = false; nscoord minSubScriptShift = 0, minSupScriptShift = 0; nscoord trySubScriptShift = subScriptShift; nscoord trySupScriptShift = supScriptShift; nscoord maxSubScriptShift = subScriptShift; nscoord maxSupScriptShift = supScriptShift; PRInt32 count = 0; nsHTMLReflowMetrics baseSize; nsHTMLReflowMetrics subScriptSize; nsHTMLReflowMetrics supScriptSize; nsIFrame* baseFrame = nsnull; nsIFrame* subScriptFrame = nsnull; nsIFrame* supScriptFrame = nsnull; bool firstPrescriptsPair = false; nsBoundingMetrics bmBase, bmSubScript, bmSupScript; nscoord italicCorrection = 0; mBoundingMetrics.width = 0; mBoundingMetrics.ascent = mBoundingMetrics.descent = -0x7FFFFFFF; nscoord ascent = -0x7FFFFFFF, descent = -0x7FFFFFFF; aDesiredSize.width = aDesiredSize.height = 0; nsIFrame* childFrame = mFrames.FirstChild(); while (childFrame) { if (childFrame->GetContent()->Tag() == nsGkAtoms::mprescripts_) { if (mprescriptsFrame) { // duplicate <mprescripts/> found // report an error, encourage people to get their markups in order return ReflowError(aRenderingContext, aDesiredSize); } mprescriptsFrame = childFrame; firstPrescriptsPair = true; } else { if (0 == count) { // base baseFrame = childFrame; GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase); GetItalicCorrection(bmBase, italicCorrection); // for the superscript, we always add "a little to spare" italicCorrection += onePixel; // we update mBoundingMetrics.{ascent,descent} with that // of the baseFrame only after processing all the sup/sub pairs // XXX need italic correction only *if* there are postscripts ? mBoundingMetrics.width = bmBase.width + italicCorrection; mBoundingMetrics.rightBearing = bmBase.rightBearing; mBoundingMetrics.leftBearing = bmBase.leftBearing; // until overwritten } else { // super/subscript block if (isSubScript) { // subscript subScriptFrame = childFrame; GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); // get the subdrop from the subscript font GetSubDropFromChild (subScriptFrame, subDrop); // parameter v, Rule 18a, App. G, TeXbook minSubScriptShift = bmBase.descent + subDrop; trySubScriptShift = NS_MAX(minSubScriptShift,subScriptShift); mBoundingMetrics.descent = NS_MAX(mBoundingMetrics.descent,bmSubScript.descent); descent = NS_MAX(descent,subScriptSize.height - subScriptSize.ascent); width = bmSubScript.width + scriptSpace; rightBearing = bmSubScript.rightBearing; } else { // supscript supScriptFrame = childFrame; GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); // get the supdrop from the supscript font GetSupDropFromChild (supScriptFrame, supDrop); // parameter u, Rule 18a, App. G, TeXbook minSupScriptShift = bmBase.ascent - supDrop; // get min supscript shift limit from x-height // = d(x) + 1/4 * sigma_5, Rule 18c, App. G, TeXbook minShiftFromXHeight = NSToCoordRound ((bmSupScript.descent + (1.0f/4.0f) * xHeight)); trySupScriptShift = NS_MAX(minSupScriptShift,NS_MAX(minShiftFromXHeight,supScriptShift)); mBoundingMetrics.ascent = NS_MAX(mBoundingMetrics.ascent,bmSupScript.ascent); ascent = NS_MAX(ascent,supScriptSize.ascent); width = NS_MAX(width, bmSupScript.width + scriptSpace); rightBearing = NS_MAX(rightBearing, bmSupScript.rightBearing); if (!mprescriptsFrame) { // we are still looping over base & postscripts mBoundingMetrics.rightBearing = mBoundingMetrics.width + rightBearing; mBoundingMetrics.width += width; } else { prescriptsWidth += width; if (firstPrescriptsPair) { firstPrescriptsPair = false; mBoundingMetrics.leftBearing = NS_MIN(bmSubScript.leftBearing, bmSupScript.leftBearing); } } width = rightBearing = 0; // negotiate between the various shifts so that // there is enough gap between the sup and subscripts // Rule 18e, App. G, TeXbook nscoord gap = (trySupScriptShift - bmSupScript.descent) - (bmSubScript.ascent - trySubScriptShift); if (gap < 4.0f * ruleSize) { // adjust trySubScriptShift to get a gap of (4.0 * ruleSize) trySubScriptShift += NSToCoordRound ((4.0f * ruleSize) - gap); } // next we want to ensure that the bottom of the superscript // will be > (4/5) * x-height above baseline gap = NSToCoordRound ((4.0f/5.0f) * xHeight - (trySupScriptShift - bmSupScript.descent)); if (gap > 0.0f) { trySupScriptShift += gap; trySubScriptShift -= gap; } maxSubScriptShift = NS_MAX(maxSubScriptShift, trySubScriptShift); maxSupScriptShift = NS_MAX(maxSupScriptShift, trySupScriptShift); trySubScriptShift = subScriptShift; trySupScriptShift = supScriptShift; } } isSubScript = !isSubScript; } count++; childFrame = childFrame->GetNextSibling(); } // note: width=0 if all sup-sub pairs match correctly if ((0 != width) || !baseFrame || !subScriptFrame || !supScriptFrame) { // report an error, encourage people to get their markups in order return ReflowError(aRenderingContext, aDesiredSize); } // we left out the width of prescripts, so ... mBoundingMetrics.rightBearing += prescriptsWidth; mBoundingMetrics.width += prescriptsWidth; // we left out the base during our bounding box updates, so ... mBoundingMetrics.ascent = NS_MAX(mBoundingMetrics.ascent+maxSupScriptShift,bmBase.ascent); mBoundingMetrics.descent = NS_MAX(mBoundingMetrics.descent+maxSubScriptShift,bmBase.descent); // get the reflow metrics ... aDesiredSize.ascent = NS_MAX(ascent+maxSupScriptShift,baseSize.ascent); aDesiredSize.height = aDesiredSize.ascent + NS_MAX(descent+maxSubScriptShift,baseSize.height - baseSize.ascent); aDesiredSize.width = mBoundingMetrics.width; aDesiredSize.mBoundingMetrics = mBoundingMetrics; mReference.x = 0; mReference.y = aDesiredSize.ascent; ////////////////// // Place Children // Place prescripts, followed by base, and then postscripts. // The list of frames is in the order: {base} {postscripts} {prescripts} // We go over the list in a circular manner, starting at <prescripts/> if (aPlaceOrigin) { nscoord dx = 0, dy = 0; count = 0; childFrame = mprescriptsFrame; do { if (!childFrame) { // end of prescripts, // place the base ... childFrame = baseFrame; dy = aDesiredSize.ascent - baseSize.ascent; FinishReflowChild (baseFrame, PresContext(), nsnull, baseSize, MirrorIfRTL(aDesiredSize.width, baseSize.width, dx), dy, 0); dx += bmBase.width + italicCorrection; } else if (mprescriptsFrame != childFrame) { // process each sup/sub pair if (0 == count) { subScriptFrame = childFrame; count = 1; } else if (1 == count) { supScriptFrame = childFrame; count = 0; // get the ascent/descent of sup/subscripts stored in their rects // rect.x = descent, rect.y = ascent GetReflowAndBoundingMetricsFor(subScriptFrame, subScriptSize, bmSubScript); GetReflowAndBoundingMetricsFor(supScriptFrame, supScriptSize, bmSupScript); // center w.r.t. largest width width = NS_MAX(subScriptSize.width, supScriptSize.width); dy = aDesiredSize.ascent - subScriptSize.ascent + maxSubScriptShift; FinishReflowChild (subScriptFrame, PresContext(), nsnull, subScriptSize, MirrorIfRTL(aDesiredSize.width, subScriptSize.width, dx + (width-subScriptSize.width)/2), dy, 0); dy = aDesiredSize.ascent - supScriptSize.ascent - maxSupScriptShift; FinishReflowChild (supScriptFrame, PresContext(), nsnull, supScriptSize, MirrorIfRTL(aDesiredSize.width, supScriptSize.width, dx + (width-supScriptSize.width)/2), dy, 0); dx += width + scriptSpace; } } childFrame = childFrame->GetNextSibling(); } while (mprescriptsFrame != childFrame); } return NS_OK; }
// This method is called when there's more data available off the // network, but it's also called from our data pump when we're feeding // the plugin data that we already got off the network, but the plugin // was unable to consume it at the point it arrived. In the case when // the plugin pump calls this method, the input argument will be null, // and the length will be the number of bytes available in our // internal buffer. nsresult nsNPAPIPluginStreamListener::OnDataAvailable(nsPluginStreamListenerPeer* streamPeer, nsIInputStream* input, uint32_t length) { if (!length || !mInst || !mInst->CanFireNotifications()) return NS_ERROR_FAILURE; PluginDestructionGuard guard(mInst); // Just in case the caller switches plugin info on us. mStreamListenerPeer = streamPeer; nsNPAPIPlugin* plugin = mInst->GetPlugin(); if (!plugin || !plugin->GetLibrary()) return NS_ERROR_FAILURE; NPPluginFuncs* pluginFunctions = plugin->PluginFuncs(); // check out if plugin implements NPP_Write call if (!pluginFunctions->write) return NS_ERROR_FAILURE; // it'll cancel necko transaction if (!mStreamBuffer) { // To optimize the mem usage & performance we have to allocate // mStreamBuffer here in first ODA when length of data available // in input stream is known. mStreamBuffer will be freed in DTOR. // we also have to remember the size of that buff to make safe // consecutive Read() calls form input stream into our buff. uint32_t contentLength; streamPeer->GetLength(&contentLength); mStreamBufferSize = NS_MAX(length, contentLength); // Limit the size of the initial buffer to MAX_PLUGIN_NECKO_BUFFER // (16k). This buffer will grow if needed, as in the case where // we're getting data faster than the plugin can process it. mStreamBufferSize = NS_MIN(mStreamBufferSize, uint32_t(MAX_PLUGIN_NECKO_BUFFER)); mStreamBuffer = (char*) PR_Malloc(mStreamBufferSize); if (!mStreamBuffer) return NS_ERROR_OUT_OF_MEMORY; } // prepare NPP_ calls params NPP npp; mInst->GetNPP(&npp); int32_t streamPosition; streamPeer->GetStreamOffset(&streamPosition); int32_t streamOffset = streamPosition; if (input) { streamOffset += length; // Set new stream offset for the next ODA call regardless of how // following NPP_Write call will behave we pretend to consume all // data from the input stream. It's possible that current steam // position will be overwritten from NPP_RangeRequest call made // from NPP_Write, so we cannot call SetStreamOffset after // NPP_Write. // // Note: there is a special case when data flow should be // temporarily stopped if NPP_WriteReady returns 0 (bug #89270) streamPeer->SetStreamOffset(streamOffset); // set new end in case the content is compressed // initial end is less than end of decompressed stream // and some plugins (e.g. acrobat) can fail. if ((int32_t)mNPStreamWrapper->mNPStream.end < streamOffset) mNPStreamWrapper->mNPStream.end = streamOffset; } nsresult rv = NS_OK; while (NS_SUCCEEDED(rv) && length > 0) { if (input && length) { if (mStreamBufferSize < mStreamBufferByteCount + length && mIsSuspended) { // We're in the ::OnDataAvailable() call that we might get // after suspending a request, or we suspended the request // from within this ::OnDataAvailable() call while there's // still data in the input, and we don't have enough space to // store what we got off the network. Reallocate our internal // buffer. mStreamBufferSize = mStreamBufferByteCount + length; char *buf = (char*)PR_Realloc(mStreamBuffer, mStreamBufferSize); if (!buf) return NS_ERROR_OUT_OF_MEMORY; mStreamBuffer = buf; } uint32_t bytesToRead = NS_MIN(length, mStreamBufferSize - mStreamBufferByteCount); uint32_t amountRead = 0; rv = input->Read(mStreamBuffer + mStreamBufferByteCount, bytesToRead, &amountRead); NS_ENSURE_SUCCESS(rv, rv); if (amountRead == 0) { NS_NOTREACHED("input->Read() returns no data, it's almost impossible " "to get here"); break; } mStreamBufferByteCount += amountRead; length -= amountRead; } else { // No input, nothing to read. Set length to 0 so that we don't // keep iterating through this outer loop any more. length = 0; } // Temporary pointer to the beginning of the data we're writing as // we loop and feed the plugin data. char *ptrStreamBuffer = mStreamBuffer; // it is possible plugin's NPP_Write() returns 0 byte consumed. We // use zeroBytesWriteCount to count situation like this and break // the loop int32_t zeroBytesWriteCount = 0; // mStreamBufferByteCount tells us how many bytes there are in the // buffer. WriteReady returns to us how many bytes the plugin is // ready to handle. while (mStreamBufferByteCount > 0) { int32_t numtowrite; if (pluginFunctions->writeready) { NPPAutoPusher nppPusher(npp); NS_TRY_SAFE_CALL_RETURN(numtowrite, (*pluginFunctions->writeready)(npp, &mNPStreamWrapper->mNPStream), mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO); NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPP WriteReady called: this=%p, npp=%p, " "return(towrite)=%d, url=%s\n", this, npp, numtowrite, mNPStreamWrapper->mNPStream.url)); if (!mStreamStarted) { // The plugin called NPN_DestroyStream() from within // NPP_WriteReady(), kill the stream. return NS_BINDING_ABORTED; } // if WriteReady returned 0, the plugin is not ready to handle // the data, suspend the stream (if it isn't already // suspended). // // Also suspend the stream if the stream we're loading is not // a javascript: URL load that was initiated during plugin // initialization and there currently is such a stream // loading. This is done to work around a Windows Media Player // plugin bug where it can't deal with being fed data for // other streams while it's waiting for data from the // javascript: URL loads it requests during // initialization. See bug 386493 for more details. if (numtowrite <= 0 || (!mIsPluginInitJSStream && PluginInitJSLoadInProgress())) { if (!mIsSuspended) { SuspendRequest(); } // Break out of the inner loop, but keep going through the // outer loop in case there's more data to read from the // input stream. break; } numtowrite = NS_MIN(numtowrite, mStreamBufferByteCount); } else { // if WriteReady is not supported by the plugin, just write // the whole buffer numtowrite = mStreamBufferByteCount; } NPPAutoPusher nppPusher(npp); int32_t writeCount = 0; // bytes consumed by plugin instance NS_TRY_SAFE_CALL_RETURN(writeCount, (*pluginFunctions->write)(npp, &mNPStreamWrapper->mNPStream, streamPosition, numtowrite, ptrStreamBuffer), mInst, NS_PLUGIN_CALL_UNSAFE_TO_REENTER_GECKO); NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY, ("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, " "buf=%s, return(written)=%d, url=%s\n", this, npp, streamPosition, numtowrite, ptrStreamBuffer, writeCount, mNPStreamWrapper->mNPStream.url)); if (!mStreamStarted) { // The plugin called NPN_DestroyStream() from within // NPP_Write(), kill the stream. return NS_BINDING_ABORTED; } if (writeCount > 0) { NS_ASSERTION(writeCount <= mStreamBufferByteCount, "Plugin read past the end of the available data!"); writeCount = NS_MIN(writeCount, mStreamBufferByteCount); mStreamBufferByteCount -= writeCount; streamPosition += writeCount; zeroBytesWriteCount = 0; if (mStreamBufferByteCount > 0) { // This alignment code is most likely bogus, but we'll leave // it in for now in case it matters for some plugins on some // architectures. Who knows... if (writeCount % sizeof(intptr_t)) { // memmove will take care about alignment memmove(mStreamBuffer, ptrStreamBuffer + writeCount, mStreamBufferByteCount); ptrStreamBuffer = mStreamBuffer; } else { // if aligned we can use ptrStreamBuffer += to eliminate // memmove() ptrStreamBuffer += writeCount; } } } else if (writeCount == 0) { // if NPP_Write() returns writeCount == 0 lets say 3 times in // a row, suspend the request and continue feeding the plugin // the data we got so far. Once that data is consumed, we'll // resume the request. if (mIsSuspended || ++zeroBytesWriteCount == 3) { if (!mIsSuspended) { SuspendRequest(); } // Break out of the for loop, but keep going through the // while loop in case there's more data to read from the // input stream. break; } } else { // Something's really wrong, kill the stream. rv = NS_ERROR_FAILURE; break; } } // end of inner while loop if (mStreamBufferByteCount && mStreamBuffer != ptrStreamBuffer) { memmove(mStreamBuffer, ptrStreamBuffer, mStreamBufferByteCount); } } if (streamPosition != streamOffset) { // The plugin didn't consume all available data, or consumed some // of our cached data while we're pumping cached data. Adjust the // plugin info's stream offset to match reality, except if the // plugin info's stream offset was set by a re-entering // NPN_RequestRead() call. int32_t postWriteStreamPosition; streamPeer->GetStreamOffset(&postWriteStreamPosition); if (postWriteStreamPosition == streamOffset) { streamPeer->SetStreamOffset(streamPosition); } } return rv; }
/* * Given the simple progress for a paced animation, this method: * - determines which two elements of the values array we're in between * (returned as aFrom and aTo) * - determines where we are between them * (returned as aIntervalProgress) * * Returns NS_OK, or NS_ERROR_FAILURE if our values don't support distance * computation. */ nsresult nsSMILAnimationFunction::ComputePacedPosition(const nsSMILValueArray& aValues, double aSimpleProgress, double& aIntervalProgress, const nsSMILValue*& aFrom, const nsSMILValue*& aTo) { NS_ASSERTION(0.0f <= aSimpleProgress && aSimpleProgress < 1.0f, "aSimpleProgress is out of bounds"); NS_ASSERTION(GetCalcMode() == CALC_PACED, "Calling paced-specific function, but not in paced mode"); NS_ABORT_IF_FALSE(aValues.Length() >= 2, "Unexpected number of values"); // Trivial case: If we have just 2 values, then there's only one interval // for us to traverse, and our progress across that interval is the exact // same as our overall progress. if (aValues.Length() == 2) { aIntervalProgress = aSimpleProgress; aFrom = &aValues[0]; aTo = &aValues[1]; return NS_OK; } double totalDistance = ComputePacedTotalDistance(aValues); if (totalDistance == COMPUTE_DISTANCE_ERROR) return NS_ERROR_FAILURE; // total distance we should have moved at this point in time. // (called 'remainingDist' due to how it's used in loop below) double remainingDist = aSimpleProgress * totalDistance; // Must be satisfied, because totalDistance is a sum of (non-negative) // distances, and aSimpleProgress is non-negative NS_ASSERTION(remainingDist >= 0, "distance values must be non-negative"); // Find where remainingDist puts us in the list of values // Note: We could optimize this next loop by caching the // interval-distances in an array, but maybe that's excessive. for (PRUint32 i = 0; i < aValues.Length() - 1; i++) { // Note: The following assertion is valid because remainingDist should // start out non-negative, and this loop never shaves off more than its // current value. NS_ASSERTION(remainingDist >= 0, "distance values must be non-negative"); double curIntervalDist; nsresult rv = aValues[i].ComputeDistance(aValues[i+1], curIntervalDist); NS_ABORT_IF_FALSE(NS_SUCCEEDED(rv), "If we got through ComputePacedTotalDistance, we should " "be able to recompute each sub-distance without errors"); NS_ASSERTION(curIntervalDist >= 0, "distance values must be non-negative"); // Clamp distance value at 0, just in case ComputeDistance is evil. curIntervalDist = NS_MAX(curIntervalDist, 0.0); if (remainingDist >= curIntervalDist) { remainingDist -= curIntervalDist; } else { // NOTE: If we get here, then curIntervalDist necessarily is not 0. Why? // Because this clause is only hit when remainingDist < curIntervalDist, // and if curIntervalDist were 0, that would mean remainingDist would // have to be < 0. But that can't happen, because remainingDist (as // a distance) is non-negative by definition. NS_ASSERTION(curIntervalDist != 0, "We should never get here with this set to 0..."); // We found the right spot -- an interpolated position between // values i and i+1. aFrom = &aValues[i]; aTo = &aValues[i+1]; aIntervalProgress = remainingDist / curIntervalDist; return NS_OK; } } NS_NOTREACHED("shouldn't complete loop & get here -- if we do, " "then aSimpleProgress was probably out of bounds"); return NS_ERROR_FAILURE; }