static void
SampleValue(float aPortion, Animation& aAnimation, nsStyleAnimation::Value& aStart,
            nsStyleAnimation::Value& aEnd, Animatable* aValue)
{
  nsStyleAnimation::Value interpolatedValue;
  NS_ASSERTION(aStart.GetUnit() == aEnd.GetUnit() ||
               aStart.GetUnit() == nsStyleAnimation::eUnit_None ||
               aEnd.GetUnit() == nsStyleAnimation::eUnit_None, "Must have same unit");
  nsStyleAnimation::Interpolate(aAnimation.property(), aStart, aEnd,
                                aPortion, interpolatedValue);
  if (aAnimation.property() == eCSSProperty_opacity) {
    *aValue = interpolatedValue.GetFloatValue();
    return;
  }

  nsCSSValueList* interpolatedList = interpolatedValue.GetCSSValueListValue();

  TransformData& data = aAnimation.data().get_TransformData();
  nsPoint origin = data.origin();
  // we expect all our transform data to arrive in css pixels, so here we must
  // adjust to dev pixels.
  double cssPerDev = double(nsDeviceContext::AppUnitsPerCSSPixel())
                     / double(data.appUnitsPerDevPixel());
  gfxPoint3D mozOrigin = data.mozOrigin();
  mozOrigin.x = mozOrigin.x * cssPerDev;
  mozOrigin.y = mozOrigin.y * cssPerDev;
  gfxPoint3D perspectiveOrigin = data.perspectiveOrigin();
  perspectiveOrigin.x = perspectiveOrigin.x * cssPerDev;
  perspectiveOrigin.y = perspectiveOrigin.y * cssPerDev;
  nsDisplayTransform::FrameTransformProperties props(interpolatedList,
                                                     mozOrigin,
                                                     perspectiveOrigin,
                                                     data.perspective());
  gfx3DMatrix transform =
    nsDisplayTransform::GetResultingTransformMatrix(props, origin,
                                                    data.appUnitsPerDevPixel(),
                                                    &data.bounds());
  gfxPoint3D scaledOrigin =
    gfxPoint3D(NS_round(NSAppUnitsToFloatPixels(origin.x, data.appUnitsPerDevPixel())),
               NS_round(NSAppUnitsToFloatPixels(origin.y, data.appUnitsPerDevPixel())),
               0.0f);

  transform.Translate(scaledOrigin);

  InfallibleTArray<TransformFunction> functions;
  functions.AppendElement(TransformMatrix(transform));
  *aValue = functions;
}
Esempio n. 2
0
static int32_t ConditionDimension(float aValue)
{
  // This will exclude NaNs and too-big values.
  if (aValue > 1.0 && aValue <= INT32_MAX)
    return int32_t(NS_round(aValue));
  return 0;
}
Esempio n. 3
0
static PRInt32 ConditionDimension(float aValue, PRInt32 aDefault)
{
  // This will exclude NaNs and infinities
  if (aValue >= 1.0 && aValue <= 10000.0)
    return PRInt32(NS_round(aValue));
  return aDefault;
}
Esempio n. 4
0
static gfxFloat ComputeMaxDescent(const gfxFont::Metrics& aMetrics,
                                  gfxFontGroup* aFontGroup)
{
    gfxFloat offset = NS_floor(-aFontGroup->GetUnderlineOffset() + 0.5);
    gfxFloat size = NS_round(aMetrics.underlineSize);
    gfxFloat minDescent = NS_floor(offset + size + 0.5);
    return PR_MAX(minDescent, aMetrics.maxDescent);
}
bool
LayerTransactionParent::RecvGetTransform(PLayerParent* aParent,
                                         gfx3DMatrix* aTransform)
{
  if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
    return false;
  }

  // The following code recovers the untranslated transform
  // from the shadow transform by undoing the translations in
  // AsyncCompositionManager::SampleValue.
  Layer* layer = cast(aParent)->AsLayer();
  if (!layer) {
    return false;
  }
  gfx::To3DMatrix(layer->AsLayerComposite()->GetShadowTransform(), *aTransform);
  if (ContainerLayer* c = layer->AsContainerLayer()) {
    aTransform->ScalePost(1.0f/c->GetInheritedXScale(),
                          1.0f/c->GetInheritedYScale(),
                          1.0f);
  }
  float scale = 1;
  gfxPoint3D scaledOrigin;
  gfxPoint3D transformOrigin;
  for (uint32_t i=0; i < layer->GetAnimations().Length(); i++) {
    if (layer->GetAnimations()[i].data().type() == AnimationData::TTransformData) {
      const TransformData& data = layer->GetAnimations()[i].data().get_TransformData();
      scale = data.appUnitsPerDevPixel();
      scaledOrigin =
        gfxPoint3D(NS_round(NSAppUnitsToFloatPixels(data.origin().x, scale)),
                   NS_round(NSAppUnitsToFloatPixels(data.origin().y, scale)),
                   0.0f);
      transformOrigin = data.transformOrigin();
      break;
    }
  }

  aTransform->Translate(-scaledOrigin);
  *aTransform = nsLayoutUtils::ChangeMatrixBasis(-scaledOrigin - transformOrigin, *aTransform);
  return true;
}
Esempio n. 6
0
void
nsSMILTimedElement::AddInstanceTimeFromCurrentTime(nsSMILTime aCurrentTime,
    double aOffsetSeconds, PRBool aIsBegin)
{
  double offset = aOffsetSeconds * PR_MSEC_PER_SEC;
  nsSMILTime timeWithOffset = aCurrentTime + PRInt64(NS_round(offset));

  nsSMILTimeValue timeVal;
  timeVal.SetMillis(timeWithOffset);

  nsSMILInstanceTime instanceTime(timeVal, nsnull, PR_TRUE);
  AddInstanceTime(instanceTime, aIsBegin);
}
Esempio n. 7
0
/* static */
int32_t
WinUtils::LogToPhys(double aValue)
{
  return int32_t(NS_round(aValue * LogToPhysFactor()));
}
bool
LayerTransactionParent::RecvGetAnimationTransform(PLayerParent* aParent,
                                                  MaybeTransform* aTransform)
{
  if (mDestroyed || !layer_manager() || layer_manager()->IsDestroyed()) {
    return false;
  }

  Layer* layer = cast(aParent)->AsLayer();
  if (!layer) {
    return false;
  }

  // This method is specific to transforms applied by animation.
  // This is because this method uses the information stored with an animation
  // such as the origin of the reference frame corresponding to the layer, to
  // recover the untranslated transform from the shadow transform. For
  // transforms that are not set by animation we don't have this information
  // available.
  if (!layer->AsLayerComposite()->GetShadowTransformSetByAnimation()) {
    *aTransform = mozilla::void_t();
    return true;
  }

  // The following code recovers the untranslated transform
  // from the shadow transform by undoing the translations in
  // AsyncCompositionManager::SampleValue.

  Matrix4x4 transform = layer->AsLayerComposite()->GetShadowTransform();
  if (ContainerLayer* c = layer->AsContainerLayer()) {
    // Undo the scale transform applied by AsyncCompositionManager::SampleValue
    transform.ScalePost(1.0f/c->GetInheritedXScale(),
                        1.0f/c->GetInheritedYScale(),
                        1.0f);
  }
  float scale = 1;
  gfxPoint3D scaledOrigin;
  gfxPoint3D transformOrigin;
  for (uint32_t i=0; i < layer->GetAnimations().Length(); i++) {
    if (layer->GetAnimations()[i].data().type() == AnimationData::TTransformData) {
      const TransformData& data = layer->GetAnimations()[i].data().get_TransformData();
      scale = data.appUnitsPerDevPixel();
      scaledOrigin =
        gfxPoint3D(NS_round(NSAppUnitsToFloatPixels(data.origin().x, scale)),
                   NS_round(NSAppUnitsToFloatPixels(data.origin().y, scale)),
                   0.0f);
      double cssPerDev =
        double(nsDeviceContext::AppUnitsPerCSSPixel()) / double(scale);
      transformOrigin = data.transformOrigin() * cssPerDev;
      break;
    }
  }

  // Undo the translation to the origin of the reference frame applied by
  // AsyncCompositionManager::SampleValue
  transform.Translate(-scaledOrigin.x, -scaledOrigin.y, -scaledOrigin.z);

  // Undo the rebasing applied by
  // nsDisplayTransform::GetResultingTransformMatrixInternal
  gfxPoint3D basis = -scaledOrigin - transformOrigin;
  transform.ChangeBasis(basis.x, basis.y, basis.z);

  // Convert to CSS pixels (this undoes the operations performed by
  // nsStyleTransformMatrix::ProcessTranslatePart which is called from
  // nsDisplayTransform::GetResultingTransformMatrix)
  double devPerCss =
    double(scale) / double(nsDeviceContext::AppUnitsPerCSSPixel());
  transform._41 *= devPerCss;
  transform._42 *= devPerCss;
  transform._43 *= devPerCss;

  *aTransform = transform;
  return true;
}
Esempio n. 9
0
void
gfxFT2LockedFace::GetMetrics(gfxFont::Metrics* aMetrics,
                             uint32_t* aSpaceGlyph)
{
    NS_PRECONDITION(aMetrics != nullptr, "aMetrics must not be NULL");
    NS_PRECONDITION(aSpaceGlyph != nullptr, "aSpaceGlyph must not be NULL");

    if (MOZ_UNLIKELY(!mFace)) {
        // No face.  This unfortunate situation might happen if the font
        // file is (re)moved at the wrong time.
        const gfxFloat emHeight = mGfxFont->GetStyle()->size;
        aMetrics->emHeight = emHeight;
        aMetrics->maxAscent = aMetrics->emAscent = 0.8 * emHeight;
        aMetrics->maxDescent = aMetrics->emDescent = 0.2 * emHeight;
        aMetrics->maxHeight = emHeight;
        aMetrics->internalLeading = 0.0;
        aMetrics->externalLeading = 0.2 * emHeight;
        const gfxFloat spaceWidth = 0.5 * emHeight;
        aMetrics->spaceWidth = spaceWidth;
        aMetrics->maxAdvance = spaceWidth;
        aMetrics->aveCharWidth = spaceWidth;
        aMetrics->zeroOrAveCharWidth = spaceWidth;
        const gfxFloat xHeight = 0.5 * emHeight;
        aMetrics->xHeight = xHeight;
        aMetrics->superscriptOffset = xHeight;
        aMetrics->subscriptOffset = xHeight;
        const gfxFloat underlineSize = emHeight / 14.0;
        aMetrics->underlineSize = underlineSize;
        aMetrics->underlineOffset = -underlineSize;
        aMetrics->strikeoutOffset = 0.25 * emHeight;
        aMetrics->strikeoutSize = underlineSize;

        *aSpaceGlyph = 0;
        return;
    }

    const FT_Size_Metrics& ftMetrics = mFace->size->metrics;

    gfxFloat emHeight;
    // Scale for vertical design metric conversion: pixels per design unit.
    // If this remains at 0.0, we can't use metrics from OS/2 etc.
    gfxFloat yScale = 0.0;
    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.
        emHeight = ftMetrics.y_ppem;
        // FT_Face doc says units_per_EM and a bunch of following fields
        // are "only relevant to scalable outlines". If it's an sfnt,
        // we can get units_per_EM from the 'head' table instead; otherwise,
        // we don't have a unitsPerEm value so we can't compute/use yScale.
        const TT_Header* head =
            static_cast<TT_Header*>(FT_Get_Sfnt_Table(mFace, ft_sfnt_head));
        if (head) {
            gfxFloat emUnit = head->Units_Per_EM;
            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 && yScale > 0.0) {
        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).
        // We use NS_round here to parallel the pixel-rounded values that
        // freetype gives us for ftMetrics.ascender/descender.
        aMetrics->maxAscent =
            std::max(aMetrics->maxAscent, NS_round(aMetrics->emAscent));
        aMetrics->maxDescent =
            std::max(aMetrics->maxDescent, NS_round(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 && yScale > 0.0) {
            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 =
            std::max(aMetrics->aveCharWidth, avgCharWidth);
    }
    aMetrics->aveCharWidth =
        std::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 =
        std::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 && yScale > 0.0) {
        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 && yScale > 0.0) {
        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 = std::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 = std::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 = floor(emHeight + 0.5);

    // maxHeight will normally be an integer, but round anyway in case
    // FreeType is configured differently.
    aMetrics->internalLeading =
        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 = floor(std::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;
}
Esempio n. 10
0
static bool
WithinEpsilonOfInteger(gfxFloat aX, gfxFloat aEpsilon)
{
    return fabs(NS_round(aX) - aX) <= fabs(aEpsilon);
}