void AsyncPanZoomController::ScaleWithFocus(float aScale, const nsIntPoint& aFocus) { FrameMetrics metrics(mFrameMetrics); // Don't set the scale to the inputted value, but rather multiply it in. float scaleFactor = aScale / metrics.mResolution.width; // The page rect is the css page rect scaled by the current zoom. gfx::Rect cssPageSize = metrics.mCSSContentRect; cssPageSize.x *= aScale; cssPageSize.y *= aScale; cssPageSize.width *= aScale; cssPageSize.height *= aScale; metrics.mContentRect = nsIntRect(NS_lround(cssPageSize.x), NS_lround(cssPageSize.y), NS_lround(cssPageSize.width), NS_lround(cssPageSize.height)); // To account for focus, offset the page by the focus point scaled. nsIntPoint scrollOffset = metrics.mViewportScrollOffset, originalOffset = scrollOffset; scrollOffset.x += aFocus.x + (scaleFactor < 1 ? 1 : -1) * originalOffset.x / aScale; scrollOffset.y += aFocus.y + (scaleFactor < 1 ? 1 : -1) * originalOffset.y / aScale; scrollOffset.x *= scaleFactor; scrollOffset.y *= scaleFactor; scrollOffset.x -= aFocus.x + (scaleFactor < 1 ? 1 : -1) * originalOffset.x / aScale; scrollOffset.y -= aFocus.y + (scaleFactor < 1 ? 1 : -1) * originalOffset.y / aScale; metrics.mViewportScrollOffset = scrollOffset; metrics.mResolution.width = metrics.mResolution.height = aScale; SetFrameMetrics(metrics); }
void AudioBufferSourceNode::SendLoopParametersToStream() { // Don't compute and set the loop parameters unnecessarily if (mLoop && mBuffer) { float rate = mBuffer->SampleRate(); double length = (double(mBuffer->Length()) / mBuffer->SampleRate()); double actualLoopStart, actualLoopEnd; if (((mLoopStart != 0.0) || (mLoopEnd != 0.0)) && mLoopStart >= 0.0 && mLoopEnd > 0.0 && mLoopStart < mLoopEnd) { actualLoopStart = (mLoopStart > length) ? 0.0 : mLoopStart; actualLoopEnd = std::min(mLoopEnd, length); } else { actualLoopStart = 0.0; actualLoopEnd = length; } int32_t loopStartTicks = NS_lround(actualLoopStart * rate); int32_t loopEndTicks = NS_lround(actualLoopEnd * rate); if (loopStartTicks < loopEndTicks) { SendInt32ParameterToStream(LOOPSTART, loopStartTicks); SendInt32ParameterToStream(LOOPEND, loopEndTicks); SendInt32ParameterToStream(LOOP, 1); } } else if (!mLoop) { SendInt32ParameterToStream(LOOP, 0); } }
void AudioBufferSourceNode::SendLoopParametersToStream() { // Don't compute and set the loop parameters unnecessarily if (mLoop && mBuffer) { float rate = mBuffer->SampleRate(); double length = (double(mBuffer->Length()) / mBuffer->SampleRate()); double actualLoopStart, actualLoopEnd; if (mLoopStart >= 0.0 && mLoopEnd > 0.0 && mLoopStart < mLoopEnd) { MOZ_ASSERT(mLoopStart != 0.0 || mLoopEnd != 0.0); actualLoopStart = (mLoopStart > length) ? 0.0 : mLoopStart; actualLoopEnd = std::min(mLoopEnd, length); } else { actualLoopStart = 0.0; actualLoopEnd = length; } int32_t loopStartTicks = NS_lround(actualLoopStart * rate); int32_t loopEndTicks = NS_lround(actualLoopEnd * rate); if (loopStartTicks < loopEndTicks) { SendInt32ParameterToStream(LOOPSTART, loopStartTicks); SendInt32ParameterToStream(LOOPEND, loopEndTicks); SendInt32ParameterToStream(LOOP, 1); } else { // Be explicit about looping not happening if the offsets make // looping impossible. SendInt32ParameterToStream(LOOP, 0); } } else if (!mLoop) { SendInt32ParameterToStream(LOOP, 0); } }
gfxRect ThebesLayerComposite::GetCompositionBounds() { // Walk up the tree, looking for a display-port - if we find one, we know // that this layer represents a content node and we can use its first // scrollable child, in conjunction with its content area and viewport offset // to establish the screen coordinates to which the content area will be // rendered. gfxRect compositionBounds; ContainerLayer* scrollableLayer = nullptr; for (ContainerLayer* parent = GetParent(); parent; parent = parent->GetParent()) { const FrameMetrics& parentMetrics = parent->GetFrameMetrics(); if (parentMetrics.IsScrollable()) scrollableLayer = parent; if (!parentMetrics.mDisplayPort.IsEmpty() && scrollableLayer) { // Get the composition bounds, so as not to waste rendering time. compositionBounds = gfxRect(parentMetrics.mCompositionBounds.x, parentMetrics.mCompositionBounds.y, parentMetrics.mCompositionBounds.width, parentMetrics.mCompositionBounds.height); // Calculate the scale transform applied to the root layer to determine // the content resolution. Layer* rootLayer = Manager()->GetRoot(); const gfx3DMatrix& rootTransform = rootLayer->GetTransform(); LayerToCSSScale scale(rootTransform.GetXScale(), rootTransform.GetYScale()); // Get the content document bounds, in screen-space. const FrameMetrics& metrics = scrollableLayer->GetFrameMetrics(); const LayerIntRect content = RoundedToInt(metrics.mScrollableRect / scale); // !!! WTF. this code is just wrong. See bug 881451. gfx::Point scrollOffset = gfx::Point((metrics.mScrollOffset.x * metrics.LayersPixelsPerCSSPixel().scale) / scale.scale, (metrics.mScrollOffset.y * metrics.LayersPixelsPerCSSPixel().scale) / scale.scale); const nsIntPoint contentOrigin( content.x - NS_lround(scrollOffset.x), content.y - NS_lround(scrollOffset.y)); gfxRect contentRect = gfxRect(contentOrigin.x, contentOrigin.y, content.width, content.height); gfxRect contentBounds = scrollableLayer->GetEffectiveTransform(). TransformBounds(contentRect); // Clip the composition bounds to the content bounds compositionBounds.IntersectRect(compositionBounds, contentBounds); break; } } return compositionBounds; }
void AudioBufferSourceNode::SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream) { NS_ASSERTION(mBuffer && mStartCalled, "Only call this when we have a buffer and start() has been called"); float rate = mBuffer->SampleRate(); aStream->SetInt32Parameter(SAMPLE_RATE, rate); int32_t bufferEnd = mBuffer->Length(); int32_t offsetSamples = std::max(0, NS_lround(mOffset * rate)); // Don't set parameter unnecessarily if (offsetSamples > 0) { aStream->SetInt32Parameter(BUFFERSTART, offsetSamples); } if (mDuration != std::numeric_limits<double>::min()) { MOZ_ASSERT(mDuration >= 0.0); // provided by Start() MOZ_ASSERT(rate >= 0.0f); // provided by AudioBuffer::Create() static_assert(std::numeric_limits<double>::digits >= std::numeric_limits<decltype(bufferEnd)>::digits, "bufferEnd should be represented exactly by double"); // + 0.5 rounds mDuration to nearest sample when assigned to bufferEnd. bufferEnd = std::min<double>(bufferEnd, offsetSamples + mDuration * rate + 0.5); } aStream->SetInt32Parameter(BUFFEREND, bufferEnd); MarkActive(); }
PRInt32 gfxFT2FontBase::GetGlyphWidth(gfxContext *aCtx, PRUint16 aGID) { cairo_text_extents_t extents; GetGlyphExtents(aGID, &extents); // convert to 16.16 fixed point return NS_lround(0x10000 * extents.x_advance); }
float Axis::ScaleWillOverscrollAmount(float aScale, int32_t aFocus) { float originAfterScale = (GetOrigin() + aFocus) * aScale - aFocus; switch (ScaleWillOverscroll(aScale, aFocus)) { case OVERSCROLL_MINUS: return originAfterScale - GetPageStart() * aScale; case OVERSCROLL_PLUS: return (originAfterScale + GetCompositionLength()) - NS_lround(GetPageEnd() * aScale); // Don't handle OVERSCROLL_BOTH. Client code is expected to deal with it. default: return 0; } }
nsresult SVGIntegerPairSMILType::Interpolate(const nsSMILValue& aStartVal, const nsSMILValue& aEndVal, double aUnitDistance, nsSMILValue& aResult) const { NS_PRECONDITION(aStartVal.mType == aEndVal.mType, "Trying to interpolate different types"); NS_PRECONDITION(aStartVal.mType == this, "Unexpected types for interpolation"); NS_PRECONDITION(aResult.mType == this, "Unexpected result type"); double currentVal[2]; currentVal[0] = aStartVal.mU.mIntPair[0] + (aEndVal.mU.mIntPair[0] - aStartVal.mU.mIntPair[0]) * aUnitDistance; currentVal[1] = aStartVal.mU.mIntPair[1] + (aEndVal.mU.mIntPair[1] - aStartVal.mU.mIntPair[1]) * aUnitDistance; aResult.mU.mIntPair[0] = NS_lround(currentVal[0]); aResult.mU.mIntPair[1] = NS_lround(currentVal[1]); return NS_OK; }
void AudioBufferSourceNode::SendOffsetAndDurationParametersToStream(AudioNodeStream* aStream) { NS_ASSERTION(mBuffer && mStartCalled, "Only call this when we have a buffer and start() has been called"); float rate = mBuffer->SampleRate(); int32_t bufferEnd = mBuffer->Length(); int32_t offsetSamples = std::max(0, NS_lround(mOffset * rate)); // Don't set parameter unnecessarily if (offsetSamples > 0) { aStream->SetInt32Parameter(BUFFERSTART, offsetSamples); } if (mDuration != std::numeric_limits<double>::min()) { bufferEnd = std::min(bufferEnd, offsetSamples + NS_lround(mDuration * rate)); } aStream->SetInt32Parameter(BUFFEREND, bufferEnd); MarkActive(); }
nsresult CanvasRenderingContextHelper::ParseParams(JSContext* aCx, const nsAString& aType, const JS::Value& aEncoderOptions, nsAString& outParams, bool* const outUsingCustomParseOptions) { // Quality parameter is only valid for the image/jpeg MIME type if (aType.EqualsLiteral("image/jpeg")) { if (aEncoderOptions.isNumber()) { double quality = aEncoderOptions.toNumber(); // Quality must be between 0.0 and 1.0, inclusive if (quality >= 0.0 && quality <= 1.0) { outParams.AppendLiteral("quality="); outParams.AppendInt(NS_lround(quality * 100.0)); } } } // If we haven't parsed the aParams check for proprietary options. // The proprietary option -moz-parse-options will take a image lib encoder // parse options string as is and pass it to the encoder. *outUsingCustomParseOptions = false; if (outParams.Length() == 0 && aEncoderOptions.isString()) { NS_NAMED_LITERAL_STRING(mozParseOptions, "-moz-parse-options:"); nsAutoJSString paramString; if (!paramString.init(aCx, aEncoderOptions.toString())) { return NS_ERROR_FAILURE; } if (StringBeginsWith(paramString, mozParseOptions)) { nsDependentSubstring parseOptions = Substring(paramString, mozParseOptions.Length(), paramString.Length() - mozParseOptions.Length()); outParams.Append(parseOptions); *outUsingCustomParseOptions = true; } } return NS_OK; }
void nsFontSizeTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue) { // Convert from nscoord to pt. // // Note: according to IA2, "The conversion doesn't have to be exact. // The intent is to give the user a feel for the size of the text." // // ATK does not specify a unit and will likely follow IA2 here. // // XXX todo: consider sharing this code with layout module? (bug 474621) float px = NSAppUnitsToFloatPixels(aValue, nsDeviceContext::AppUnitsPerCSSPixel()); // Each pt is 4/3 of a CSS pixel. int pts = NS_lround(px*3/4); nsAutoString value; value.AppendInt(pts); value.Append(NS_LITERAL_STRING("pt")); aFormattedValue = value; }
const nsIntRect AsyncPanZoomController::CalculatePendingDisplayPort() { float scale = mFrameMetrics.mResolution.width; nsIntRect viewport = mFrameMetrics.mViewport; viewport.ScaleRoundIn(1 / scale); #ifdef USE_LARGER_DISPLAYPORT const float SIZE_MULTIPLIER = 2.0f; nsIntPoint scrollOffset = mFrameMetrics.mViewportScrollOffset; gfx::Rect contentRect = mFrameMetrics.mCSSContentRect; // Paint a larger portion of the screen than just what we can see. This makes // it less likely that we'll checkerboard when panning around and Gecko hasn't // repainted yet. float desiredWidth = viewport.width * SIZE_MULTIPLIER, desiredHeight = viewport.height * SIZE_MULTIPLIER; // The displayport is relative to the current scroll offset. Here's a little // diagram to make it easier to see: // // - - - - // | | // ************* // * | | * // - -*- @------ -*- - // | * |=====| * | // * |=====| * // | * |=====| * | // - -*- ------- -*- - // * | | * // ************* // | | // - - - - // // The full --- area with === inside it is the actual viewport rect, the *** area // is the displayport, and the - - - area is an imaginary additional page on all 4 // borders of the actual page. Notice that the displayport intersects half-way with // each of the imaginary extra pages. The @ symbol at the top left of the // viewport marks the current scroll offset. From the @ symbol to the far left // and far top, it is clear that this distance is 1/4 of the displayport's // height/width dimension. gfx::Rect displayPort(-desiredWidth / 4, -desiredHeight / 4, desiredWidth, desiredHeight); // Check if the desired boundaries go over the CSS page rect along the top or // left. If they do, shift them to the right or down. float oldDisplayPortX = displayPort.x, oldDisplayPortY = displayPort.y; if (displayPort.X() + scrollOffset.x < contentRect.X()) displayPort.x = contentRect.X() - scrollOffset.x; if (displayPort.Y() + scrollOffset.y < contentRect.Y()) displayPort.y = contentRect.Y() - scrollOffset.y; // We don't need to paint the extra area that was going to overlap with the // content rect. Subtract out this extra width or height. displayPort.width -= displayPort.x - oldDisplayPortX; displayPort.height -= displayPort.y - oldDisplayPortY; // Check if the desired boundaries go over the CSS page rect along the right // or bottom. If they do, subtract out some height or width such that they // perfectly align with the end of the CSS page rect. if (displayPort.XMost() + scrollOffset.x > contentRect.XMost()) displayPort.width = NS_MAX(0.0f, contentRect.XMost() - (displayPort.X() + scrollOffset.x)); if (displayPort.YMost() + scrollOffset.y > contentRect.YMost()) displayPort.height = NS_MAX(0.0f, contentRect.YMost() - (displayPort.Y() + scrollOffset.y)); return nsIntRect(NS_lround(displayPort.X()), NS_lround(displayPort.Y()), NS_lround(displayPort.Width()), NS_lround(displayPort.Height())); #else return nsIntRect(0, 0, NS_lround(viewport.Width()), NS_lround(viewport.Height())); #endif }
nsresult nsThebesDeviceContext::SetDPI() { float dpi = -1.0f; // PostScript, PDF and Mac (when printing) all use 72 dpi // Use a printing DC to determine the other dpi values if (mPrintingSurface) { switch (mPrintingSurface->GetType()) { case gfxASurface::SurfaceTypePDF: case gfxASurface::SurfaceTypePS: case gfxASurface::SurfaceTypeQuartz: dpi = 72.0f; break; #ifdef XP_WIN case gfxASurface::SurfaceTypeWin32: case gfxASurface::SurfaceTypeWin32Printing: { PRInt32 OSVal = GetDeviceCaps(GetPrintHDC(), LOGPIXELSY); dpi = 144.0f; mPrintingScale = float(OSVal) / dpi; break; } #endif #ifdef XP_OS2 case gfxASurface::SurfaceTypeOS2: LONG lDPI; if (DevQueryCaps(GetPrintHDC(), CAPS_VERTICAL_FONT_RES, 1, &lDPI)) dpi = lDPI; break; #endif default: NS_NOTREACHED("Unexpected printing surface type"); break; } mAppUnitsPerDevNotScaledPixel = NS_lround((AppUnitsPerCSSPixel() * 96) / dpi); } else { nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID); // A value of -1 means use the maximum of 96 and the system DPI. // A value of 0 means use the system DPI. A positive value is used as the DPI. // This sets the physical size of a device pixel and thus controls the // interpretation of physical units. PRInt32 prefDPI = -1; if (prefs) { nsresult rv = prefs->GetIntPref("layout.css.dpi", &prefDPI); if (NS_FAILED(rv)) { prefDPI = -1; } } if (prefDPI > 0) { dpi = prefDPI; } else if (mWidget) { dpi = mWidget->GetDPI(); if (prefDPI < 0) { dpi = PR_MAX(96.0f, dpi); } } else { dpi = 96.0f; } // The number of device pixels per CSS pixel. A value <= 0 means choose // automatically based on the DPI. A positive value is used as-is. This effectively // controls the size of a CSS "px". float devPixelsPerCSSPixel = -1.0; if (prefs) { nsXPIDLCString prefString; nsresult rv = prefs->GetCharPref("layout.css.devPixelsPerPx", getter_Copies(prefString)); if (NS_SUCCEEDED(rv) && !prefString.IsEmpty()) { devPixelsPerCSSPixel = static_cast<float>(atof(prefString)); } } if (devPixelsPerCSSPixel <= 0) { if (mWidget) { devPixelsPerCSSPixel = mWidget->GetDefaultScale(); } else { devPixelsPerCSSPixel = 1.0; } } mAppUnitsPerDevNotScaledPixel = PR_MAX(1, NS_lround(AppUnitsPerCSSPixel() / devPixelsPerCSSPixel)); } NS_ASSERTION(dpi != -1.0, "no dpi set"); mAppUnitsPerPhysicalInch = NS_lround(dpi * mAppUnitsPerDevNotScaledPixel); UpdateScaledAppUnits(); return NS_OK; }