Exemplo n.º 1
0
static bool d_not_equal_ulps(float a, float b, int epsilon) {
    if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
        return false;
    }
    int aBits = SkFloatAs2sCompliment(a);
    int bBits = SkFloatAs2sCompliment(b);
    // Find the difference in ULPs.
    return aBits >= bBits + epsilon || bBits >= aBits + epsilon;
}
Exemplo n.º 2
0
sk_sp<SkImageFilter> SkOffsetImageFilter::Make(SkScalar dx, SkScalar dy,
                                               sk_sp<SkImageFilter> input,
                                               const CropRect* cropRect) {
    if (!SkScalarIsFinite(dx) || !SkScalarIsFinite(dy)) {
        return nullptr;
    }

    return sk_sp<SkImageFilter>(new SkOffsetImageFilter(dx, dy, std::move(input), cropRect));
}
Exemplo n.º 3
0
SkBlurImageFilter::SkBlurImageFilter(SkReadBuffer& buffer)
  : INHERITED(1, buffer) {
    fSigma.fWidth = buffer.readScalar();
    fSigma.fHeight = buffer.readScalar();
    buffer.validate(SkScalarIsFinite(fSigma.fWidth) &&
                    SkScalarIsFinite(fSigma.fHeight) &&
                    (fSigma.fWidth >= 0) &&
                    (fSigma.fHeight >= 0));
}
Exemplo n.º 4
0
// From Barten SPIE 1989
static float contrast_sensitivity(float cyclesPerDegree, float luminance) {
  float a = 440.0f * powf(1.0f + 0.7f / luminance, -0.2f);
  float b = 0.3f * powf(1.0f + 100.0f / luminance, 0.15f);
  float exp = expf(-b * cyclesPerDegree);
  float root = sqrtf(1.0f + 0.06f * expf(b * cyclesPerDegree));
  if (!SkScalarIsFinite(exp) || !SkScalarIsFinite(root)) {
    return 0;
  }
  return a * cyclesPerDegree * exp * root;
}
Exemplo n.º 5
0
sk_sp<SkPathEffect> SkDiscretePathEffect::Make(SkScalar segLength, SkScalar deviation,
                                               uint32_t seedAssist) {
    if (!SkScalarIsFinite(segLength) || !SkScalarIsFinite(deviation)) {
        return nullptr;
    }
    if (segLength <= SK_ScalarNearlyZero) {
        return nullptr;
    }
    return sk_sp<SkPathEffect>(new SkDiscretePathEffect(segLength, deviation, seedAssist));
}
Exemplo n.º 6
0
SkBicubicImageFilter::SkBicubicImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
    SkDEBUGCODE(bool success =) buffer.readScalarArray(fCoefficients, 16);
    SkASSERT(success);
    fScale.fWidth = buffer.readScalar();
    fScale.fHeight = buffer.readScalar();
    buffer.validate(SkScalarIsFinite(fScale.fWidth) &&
                    SkScalarIsFinite(fScale.fHeight) &&
                    (fScale.fWidth >= 0) &&
                    (fScale.fHeight >= 0));
}
Exemplo n.º 7
0
static bool less_or_equal_ulps(float a, float b, int epsilon) {
    if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
        return false;
    }
    if (arguments_denormalized(a, b, epsilon)) {
        return a < b + FLT_EPSILON * epsilon;
    }
    int aBits = SkFloatAs2sCompliment(a);
    int bBits = SkFloatAs2sCompliment(b);
    // Find the difference in ULPs.
    return aBits < bBits + epsilon;
}
Exemplo n.º 8
0
SkDropShadowImageFilter::SkDropShadowImageFilter(SkReadBuffer& buffer)
 : INHERITED(1, buffer) {
    fDx = buffer.readScalar();
    fDy = buffer.readScalar();
    fSigmaX = buffer.readScalar();
    fSigmaY = buffer.readScalar();
    fColor = buffer.readColor();
    buffer.validate(SkScalarIsFinite(fDx) &&
                    SkScalarIsFinite(fDy) &&
                    SkScalarIsFinite(fSigmaX) &&
                    SkScalarIsFinite(fSigmaY));
}
Exemplo n.º 9
0
// from http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/
// FIXME: move to SkFloatBits.h
static bool equal_ulps(float a, float b, int epsilon, int depsilon) {
    if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
        return false;
    }
    if (arguments_denormalized(a, b, depsilon)) {
        return true;
    }
    int aBits = SkFloatAs2sCompliment(a);
    int bBits = SkFloatAs2sCompliment(b);
    // Find the difference in ULPs.
    return aBits < bBits + epsilon && bBits < aBits + epsilon;
}
Exemplo n.º 10
0
sk_sp<SkFont> SkFont::Make(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX,
                           MaskType mt, uint32_t flags) {
    if (size <= 0 || !SkScalarIsFinite(size)) {
        return nullptr;
    }
    if (scaleX <= 0 || !SkScalarIsFinite(scaleX)) {
        return nullptr;
    }
    if (!SkScalarIsFinite(skewX)) {
        return nullptr;
    }
    flags &= kAllFlags;
    return sk_sp<SkFont>(new SkFont(std::move(face), size, scaleX, skewX, mt, flags));
}
Exemplo n.º 11
0
SkDashPathEffect::SkDashPathEffect(const SkScalar intervals[], int count,
                                   SkScalar phase, bool scaleToFit)
        : fScaleToFit(scaleToFit) {
    SkASSERT(intervals);
    SkASSERT(count > 1 && SkAlign2(count) == count);

    fIntervals = (SkScalar*)sk_malloc_throw(sizeof(SkScalar) * count);
    fCount = count;

    SkScalar len = 0;
    for (int i = 0; i < count; i++) {
        SkASSERT(intervals[i] >= 0);
        fIntervals[i] = intervals[i];
        len += intervals[i];
    }
    fIntervalLength = len;

    // watch out for values that might make us go out of bounds
    if ((len > 0) && SkScalarIsFinite(phase) && SkScalarIsFinite(len)) {

        // Adjust phase to be between 0 and len, "flipping" phase if negative.
        // e.g., if len is 100, then phase of -20 (or -120) is equivalent to 80
        if (phase < 0) {
            phase = -phase;
            if (phase > len) {
                phase = SkScalarMod(phase, len);
            }
            phase = len - phase;

            // Due to finite precision, it's possible that phase == len,
            // even after the subtract (if len >>> phase), so fix that here.
            // This fixes http://crbug.com/124652 .
            SkASSERT(phase <= len);
            if (phase == len) {
                phase = 0;
            }
        } else if (phase >= len) {
            phase = SkScalarMod(phase, len);
        }
        SkASSERT(phase >= 0 && phase < len);

        fInitialDashLength = FindFirstInterval(intervals, phase,
                                               &fInitialDashIndex, count);

        SkASSERT(fInitialDashLength >= 0);
        SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount);
    } else {
        fInitialDashLength = -1;    // signal bad dash intervals
    }
}
Exemplo n.º 12
0
bool SkDashPath::ValidDashPath(SkScalar phase, const SkScalar intervals[], int32_t count) {
    if (count < 2 || !SkIsAlign2(count)) {
        return false;
    }
    SkScalar length = 0;
    for (int i = 0; i < count; i++) {
        if (intervals[i] < 0) {
            return false;
        }
        length += intervals[i];
    }
    // watch out for values that might make us go out of bounds
    return length > 0 && SkScalarIsFinite(phase) && SkScalarIsFinite(length);
}
Exemplo n.º 13
0
int UlpsDistance(float a, float b) {
    if (!SkScalarIsFinite(a) || !SkScalarIsFinite(b)) {
        return SK_MaxS32;
    }
    SkFloatIntUnion floatIntA, floatIntB;
    floatIntA.fFloat = a;
    floatIntB.fFloat = b;
    // Different signs means they do not match.
    if ((floatIntA.fSignBitInt < 0) != (floatIntB.fSignBitInt < 0)) {
        // Check for equality to make sure +0 == -0
        return a == b ? 0 : SK_MaxS32;
    }
    // Find the difference in ULPs.
    return abs(floatIntA.fSignBitInt - floatIntB.fSignBitInt);
}
Exemplo n.º 14
0
uint32_t GrPathUtils::cubicPointCount(const SkPoint points[],
                                           SkScalar tol) {
    if (tol < gMinCurveTol) {
        tol = gMinCurveTol;
    }
    SkASSERT(tol > 0);

    SkScalar d = SkTMax(
        points[1].distanceToLineSegmentBetweenSqd(points[0], points[3]),
        points[2].distanceToLineSegmentBetweenSqd(points[0], points[3]));
    d = SkScalarSqrt(d);
    if (!SkScalarIsFinite(d)) {
        return MAX_POINTS_PER_CURVE;
    } else if (d <= tol) {
        return 1;
    } else {
        SkScalar divSqrt = SkScalarSqrt(d / tol);
        if (((SkScalar)SK_MaxS32) <= divSqrt) {
            return MAX_POINTS_PER_CURVE;
        } else {
            int temp = SkScalarCeilToInt(SkScalarSqrt(d / tol));
            int pow2 = GrNextPow2(temp);
            // Because of NaNs & INFs we can wind up with a degenerate temp
            // such that pow2 comes out negative. Also, our point generator
            // will always output at least one pt.
            if (pow2 < 1) {
                pow2 = 1;
            }
            return SkTMin(pow2, MAX_POINTS_PER_CURVE);
        }
    }
}
Exemplo n.º 15
0
uint32_t GrPathUtils::quadraticPointCount(const SkPoint points[],
                                          SkScalar tol) {
    if (tol < gMinCurveTol) {
        tol = gMinCurveTol;
    }
    SkASSERT(tol > 0);

    SkScalar d = points[1].distanceToLineSegmentBetween(points[0], points[2]);
    if (!SkScalarIsFinite(d)) {
        return MAX_POINTS_PER_CURVE;
    } else if (d <= tol) {
        return 1;
    } else {
        // Each time we subdivide, d should be cut in 4. So we need to
        // subdivide x = log4(d/tol) times. x subdivisions creates 2^(x)
        // points.
        // 2^(log4(x)) = sqrt(x);
        SkScalar divSqrt = SkScalarSqrt(d / tol);
        if (((SkScalar)SK_MaxS32) <= divSqrt) {
            return MAX_POINTS_PER_CURVE;
        } else {
            int temp = SkScalarCeilToInt(divSqrt);
            int pow2 = GrNextPow2(temp);
            // Because of NaNs & INFs we can wind up with a degenerate temp
            // such that pow2 comes out negative. Also, our point generator
            // will always output at least one pt.
            if (pow2 < 1) {
                pow2 = 1;
            }
            return SkTMin(pow2, MAX_POINTS_PER_CURVE);
        }
    }
}
Exemplo n.º 16
0
/* This works -- more needs to be done to see if it is performant on all platforms.
   To use this to measure parts of quads requires recomputing everything -- perhaps
   a chop-like interface can start from a larger measurement and get two new measurements
   with one call here.
 */
static SkScalar compute_quad_len(const SkPoint pts[3]) {
    SkPoint a,b;
    a.fX = pts[0].fX - 2 * pts[1].fX + pts[2].fX;
    a.fY = pts[0].fY - 2 * pts[1].fY + pts[2].fY;
    SkScalar A = 4 * (a.fX * a.fX + a.fY * a.fY);
    if (0 == A) {
        a = pts[2] - pts[0];
        return a.length();
    }
    b.fX = 2 * (pts[1].fX - pts[0].fX);
    b.fY = 2 * (pts[1].fY - pts[0].fY);
    SkScalar B = 4 * (a.fX * b.fX + a.fY * b.fY);
    SkScalar C =      b.fX * b.fX + b.fY * b.fY;
    SkScalar Sabc = 2 * SkScalarSqrt(A + B + C);
    SkScalar A_2  = SkScalarSqrt(A);
    SkScalar A_32 = 2 * A * A_2;
    SkScalar C_2  = 2 * SkScalarSqrt(C);
    SkScalar BA   = B / A_2;
    if (0 == BA + C_2) {
        return quad_folded_len(pts);
    }
    SkScalar J = A_32 * Sabc + A_2 * B * (Sabc - C_2);
    SkScalar K = 4 * C * A - B * B;
    SkScalar L = (2 * A_2 + BA + Sabc) / (BA + C_2);
    if (L <= 0) {
        return quad_folded_len(pts);
    }
    SkScalar M = SkScalarLog(L);
    SkScalar result = (J + K * M) / (4 * A_32);
    SkASSERT(SkScalarIsFinite(result));
    return result;
}
Exemplo n.º 17
0
/*
 *  We have to worry about 2 tricky conditions:
 *  1. underflow of mag2 (compared against nearlyzero^2)
 *  2. overflow of mag2 (compared w/ isfinite)
 *
 *  If we underflow, we return false. If we overflow, we compute again using
 *  doubles, which is much slower (3x in a desktop test) but will not overflow.
 */
bool SkPoint::setLength(float x, float y, float length) {
    float mag2;
    if (isLengthNearlyZero(x, y, &mag2)) {
        return false;
    }

    float scale;
    if (SkScalarIsFinite(mag2)) {
        scale = length / sk_float_sqrt(mag2);
    } else {
        // our mag2 step overflowed to infinity, so use doubles instead.
        // much slower, but needed when x or y are very large, other wise we
        // divide by inf. and return (0,0) vector.
        double xx = x;
        double yy = y;
    #ifdef SK_DISCARD_DENORMALIZED_FOR_SPEED
        // The iOS ARM processor discards small denormalized numbers to go faster.
        // Casting this to a float would cause the scale to go to zero. Keeping it
        // as a double for the multiply keeps the scale non-zero.
        double dscale = length / sqrt(xx * xx + yy * yy);
        fX = x * dscale;
        fY = y * dscale;
        return true;
    #else
        scale = (float)(length / sqrt(xx * xx + yy * yy));
    #endif
    }
    fX = x * scale;
    fY = y * scale;
    return true;
}
Exemplo n.º 18
0
SkScalar SkPoint::Normalize(SkPoint* pt) {
    float x = pt->fX;
    float y = pt->fY;
    float mag2;
    if (isLengthNearlyZero(x, y, &mag2)) {
        return 0;
    }

    float mag, scale;
    if (SkScalarIsFinite(mag2)) {
        mag = sk_float_sqrt(mag2);
        scale = 1 / mag;
    } else {
        // our mag2 step overflowed to infinity, so use doubles instead.
        // much slower, but needed when x or y are very large, other wise we
        // divide by inf. and return (0,0) vector.
        double xx = x;
        double yy = y;
        double magmag = sqrt(xx * xx + yy * yy);
        mag = (float)magmag;
        // we perform the divide with the double magmag, to stay exactly the
        // same as setLength. It would be faster to perform the divide with
        // mag, but it is possible that mag has overflowed to inf. but still
        // have a non-zero value for scale (thanks to denormalized numbers).
        scale = (float)(1 / magmag);
    }
    pt->set(x * scale, y * scale);
    return mag;
}
Exemplo n.º 19
0
/** From Numerical Recipes in C.

    Q = -1/2 (B + sign(B) sqrt[B*B - 4*A*C])
    x1 = Q / A
    x2 = C / Q
*/
int SkFindUnitQuadRoots(SkScalar A, SkScalar B, SkScalar C, SkScalar roots[2]) {
    SkASSERT(roots);

    if (A == 0) {
        return valid_unit_divide(-C, B, roots);
    }

    SkScalar* r = roots;

    SkScalar R = B*B - 4*A*C;
    if (R < 0 || !SkScalarIsFinite(R)) {  // complex roots
        // if R is infinite, it's possible that it may still produce
        // useful results if the operation was repeated in doubles
        // the flipside is determining if the more precise answer
        // isn't useful because surrounding machinery (e.g., subtracting
        // the axis offset from C) already discards the extra precision
        // more investigation and unit tests required...
        return 0;
    }
    R = SkScalarSqrt(R);

    SkScalar Q = (B < 0) ? -(B-R)/2 : -(B+R)/2;
    r += valid_unit_divide(Q, A, r);
    r += valid_unit_divide(C, Q, r);
    if (r - roots == 2) {
        if (roots[0] > roots[1])
            SkTSwap<SkScalar>(roots[0], roots[1]);
        else if (roots[0] == roots[1])  // nearly-equal?
            r -= 1; // skip the double root
    }
    return (int)(r - roots);
}
Exemplo n.º 20
0
// Conic weights must be 0 < weight <= finite
static bool validate_conic_weights(const SkScalar weights[], int count) {
    for (int i = 0; i < count; ++i) {
        if (weights[i] <= 0 || !SkScalarIsFinite(weights[i])) {
            return false;
        }
    }
    return true;
}
Exemplo n.º 21
0
void SkDashPath::CalcDashParameters(SkScalar phase, const SkScalar intervals[], int32_t count,
                                    SkScalar* initialDashLength, int32_t* initialDashIndex,
                                    SkScalar* intervalLength, SkScalar* adjustedPhase) {
    SkScalar len = 0;
    for (int i = 0; i < count; i++) {
        len += intervals[i];
    }
    *intervalLength = len;

    // watch out for values that might make us go out of bounds
    if ((len > 0) && SkScalarIsFinite(phase) && SkScalarIsFinite(len)) {

        // Adjust phase to be between 0 and len, "flipping" phase if negative.
        // e.g., if len is 100, then phase of -20 (or -120) is equivalent to 80
        if (adjustedPhase) {
            if (phase < 0) {
                phase = -phase;
                if (phase > len) {
                    phase = SkScalarMod(phase, len);
                }
                phase = len - phase;

                // Due to finite precision, it's possible that phase == len,
                // even after the subtract (if len >>> phase), so fix that here.
                // This fixes http://crbug.com/124652 .
                SkASSERT(phase <= len);
                if (phase == len) {
                    phase = 0;
                }
            } else if (phase >= len) {
                phase = SkScalarMod(phase, len);
            }
            *adjustedPhase = phase;
        }
        SkASSERT(phase >= 0 && phase < len);

        *initialDashLength = find_first_interval(intervals, phase,
                                                initialDashIndex, count);

        SkASSERT(*initialDashLength >= 0);
        SkASSERT(*initialDashIndex >= 0 && *initialDashIndex < count);
    } else {
        *initialDashLength = -1;    // signal bad dash intervals
    }
}
Exemplo n.º 22
0
sk_sp<SkImageFilter> SkDownSampleImageFilter::Make(SkScalar scale, sk_sp<SkImageFilter> input) {
    if (!SkScalarIsFinite(scale)) {
        return nullptr;
    }
    // we don't support scale in this range
    if (scale > SK_Scalar1 || scale <= 0) {
        return nullptr;
    }
    return sk_sp<SkImageFilter>(new SkDownSampleImageFilter(scale, std::move(input)));
}
Exemplo n.º 23
0
bool SkMipMap::extractLevel(const SkSize& scaleSize, Level* levelPtr) const {
    if (nullptr == fLevels) {
        return false;
    }

    SkASSERT(scaleSize.width() >= 0 && scaleSize.height() >= 0);

#ifndef SK_SUPPORT_LEGACY_ANISOTROPIC_MIPMAP_SCALE
    // Use the smallest scale to match the GPU impl.
    const SkScalar scale = SkTMin(scaleSize.width(), scaleSize.height());
#else
    // Ideally we'd pick the smaller scale, to match Ganesh.  But ignoring one of the
    // scales can produce some atrocious results, so for now we use the geometric mean.
    // (https://bugs.chromium.org/p/skia/issues/detail?id=4863)
    const SkScalar scale = SkScalarSqrt(scaleSize.width() * scaleSize.height());
#endif

    if (scale >= SK_Scalar1 || scale <= 0 || !SkScalarIsFinite(scale)) {
        return false;
    }

    SkScalar L = -SkScalarLog2(scale);
    if (!SkScalarIsFinite(L)) {
        return false;
    }
    SkASSERT(L >= 0);
    int level = SkScalarFloorToInt(L);

    SkASSERT(level >= 0);
    if (level <= 0) {
        return false;
    }

    if (level > fCount) {
        level = fCount;
    }
    if (levelPtr) {
        *levelPtr = fLevels[level - 1];
        // need to augment with our colorspace
        levelPtr->fPixmap.setColorSpace(fCS);
    }
    return true;
}
Exemplo n.º 24
0
SkScalar SkPoint::Length(SkScalar dx, SkScalar dy) {
    float mag2 = dx * dx + dy * dy;
    if (SkScalarIsFinite(mag2)) {
        return sk_float_sqrt(mag2);
    } else {
        double xx = dx;
        double yy = dy;
        return (float)sqrt(xx * xx + yy * yy);
    }
}
Exemplo n.º 25
0
SkDisplacementMapEffect::SkDisplacementMapEffect(SkReadBuffer& buffer)
  : INHERITED(2, buffer)
{
    fXChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt();
    fYChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt();
    fScale            = buffer.readScalar();
    buffer.validate(channel_selector_type_is_valid(fXChannelSelector) &&
                    channel_selector_type_is_valid(fYChannelSelector) &&
                    SkScalarIsFinite(fScale));
}
Exemplo n.º 26
0
void SkDashPathEffect::setInternalMembers(SkScalar phase) {
    SkScalar len = 0;
    for (int i = 0; i < fCount; i++) {
        len += fIntervals[i];
    }
    fIntervalLength = len;

    // watch out for values that might make us go out of bounds
    if ((len > 0) && SkScalarIsFinite(phase) && SkScalarIsFinite(len)) {

        // Adjust phase to be between 0 and len, "flipping" phase if negative.
        // e.g., if len is 100, then phase of -20 (or -120) is equivalent to 80
        if (phase < 0) {
            phase = -phase;
            if (phase > len) {
                phase = SkScalarMod(phase, len);
            }
            phase = len - phase;

            // Due to finite precision, it's possible that phase == len,
            // even after the subtract (if len >>> phase), so fix that here.
            // This fixes http://crbug.com/124652 .
            SkASSERT(phase <= len);
            if (phase == len) {
                phase = 0;
            }
        } else if (phase >= len) {
            phase = SkScalarMod(phase, len);
        }
        SkASSERT(phase >= 0 && phase < len);

        fPhase = phase;

        fInitialDashLength = FindFirstInterval(fIntervals, fPhase,
                                               &fInitialDashIndex, fCount);

        SkASSERT(fInitialDashLength >= 0);
        SkASSERT(fInitialDashIndex >= 0 && fInitialDashIndex < fCount);
    } else {
        fInitialDashLength = -1;    // signal bad dash intervals
    }
}
Exemplo n.º 27
0
static SkScalar quad_folded_len(const SkPoint pts[3]) {
    SkScalar t = SkFindQuadMaxCurvature(pts);
    SkPoint pt = SkEvalQuadAt(pts, t);
    SkVector a = pts[2] - pt;
    SkScalar result = a.length();
    if (0 != t) {
        SkVector b = pts[0] - pt;
        result += b.length();
    }
    SkASSERT(SkScalarIsFinite(result));
    return result;
}
sk_sp<SkImageFilter> SkMagnifierImageFilter::Make(const SkRect& srcRect, SkScalar inset,
                                                  sk_sp<SkImageFilter> input) {

    if (!SkScalarIsFinite(inset) || !SkIsValidRect(srcRect)) {
        return nullptr;
    }
    // Negative numbers in src rect are not supported
    if (srcRect.fLeft < 0 || srcRect.fTop < 0) {
        return nullptr;
    }
    return sk_sp<SkImageFilter>(new SkMagnifierImageFilter(srcRect, inset, std::move(input)));
}
SkImageFilter* SkMagnifierImageFilter::Create(const SkRect& srcRect, SkScalar inset,
                                              SkImageFilter* input) {

    if (!SkScalarIsFinite(inset) || !SkIsValidRect(srcRect)) {
        return NULL;
    }
    // Negative numbers in src rect are not supported
    if (srcRect.fLeft < 0 || srcRect.fTop < 0) {
        return NULL;
    }
    return SkNEW_ARGS(SkMagnifierImageFilter, (srcRect, inset, input));
}
Exemplo n.º 30
0
SkFont::SkFont(sk_sp<SkTypeface> face, SkScalar size, SkScalar scaleX, SkScalar skewX, MaskType mt,
               uint32_t flags)
    : fTypeface(face ? std::move(face) : SkTypeface::MakeDefault())
    , fSize(size)
    , fScaleX(scaleX)
    , fSkewX(skewX)
    , fFlags(flags)
    , fMaskType(SkToU8(mt))
{
    SkASSERT(size > 0);
    SkASSERT(scaleX > 0);
    SkASSERT(SkScalarIsFinite(skewX));
    SkASSERT(0 == (flags & ~kAllFlags));
}