예제 #1
0
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();
}
예제 #6
0
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);
}
예제 #7
0
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;
}
예제 #11
0
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;
}
예제 #12
0
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
}
예제 #13
0
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;
}