MorphologyBench(SkScalar rad, MorphologyType style)
      {
     fRadius = rad;
     fStyle = style;
     const char* name = rad > 0 ? gStyleName[style] : "none";
     if (SkScalarFraction(rad) != 0) {
         fName.printf("morph_%.2f_%s", SkScalarToFloat(rad), name);
     } else {
         fName.printf("morph_%d_%s", SkScalarRoundToInt(rad), name);
     }
 }
Beispiel #2
0
float SkTouchGesture::limitTotalZoom(float scale) const {
    // this query works 'cause we know that we're square-scale w/ no skew/rotation
    const float curr = SkScalarToFloat(fGlobalM[0]);

    if (scale > 1 && curr * scale > MAX_ZOOM_SCALE) {
        scale = MAX_ZOOM_SCALE / curr;
    } else if (scale < 1 && curr * scale < MIN_ZOOM_SCALE) {
        scale = MIN_ZOOM_SCALE / curr;
    }
    return scale;
}
Beispiel #3
0
    BlurRectDirectBench(SkScalar rad) : INHERITED(rad) {
        SkString name;

        if (SkScalarFraction(rad) != 0) {
            name.printf("blurrect_direct_%.2f", SkScalarToFloat(rad));
        } else {
            name.printf("blurrect_direct_%d", SkScalarRoundToInt(rad));
        }

        this->setName(name);
    }
Beispiel #4
0
float Path::length() const
{
    SkScalar length = 0;
    SkPathMeasure measure(m_path, false);

    do {
        length += measure.getLength();
    } while (measure.nextContour());

    return SkScalarToFloat(length);
}
Beispiel #5
0
void SkTableMaskFilter::MakeGammaTable(uint8_t table[256], SkScalar gamma) {
    const float dx = 1 / 255.0f;
    const float g = SkScalarToFloat(gamma);

    float x = 0;
    for (int i = 0; i < 256; i++) {
     // float ee = powf(x, g) * 255;
        table[i] = SkPin32(sk_float_round2int(powf(x, g) * 255), 0, 255);
        x += dx;
    }
}
static void android_view_MotionEvent_nativeTransform(JNIEnv* env, jclass clazz,
        jint nativePtr, jobject matrixObj) {
    SkMatrix* matrix = android_graphics_Matrix_getSkMatrix(env, matrixObj);
    MotionEvent* event = reinterpret_cast<MotionEvent*>(nativePtr);

    float m[9];
    m[0] = SkScalarToFloat(matrix->get(SkMatrix::kMScaleX));
    m[1] = SkScalarToFloat(matrix->get(SkMatrix::kMSkewX));
    m[2] = SkScalarToFloat(matrix->get(SkMatrix::kMTransX));
    m[3] = SkScalarToFloat(matrix->get(SkMatrix::kMSkewY));
    m[4] = SkScalarToFloat(matrix->get(SkMatrix::kMScaleY));
    m[5] = SkScalarToFloat(matrix->get(SkMatrix::kMTransY));
    m[6] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp0));
    m[7] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp1));
    m[8] = SkScalarToFloat(matrix->get(SkMatrix::kMPersp2));
    event->transform(m);
}
Beispiel #7
0
 static jfloat measureText_String(JNIEnv* env, jobject jpaint, jstring text) {
     NPE_CHECK_RETURN_ZERO(env, jpaint);
     NPE_CHECK_RETURN_ZERO(env, text);
     
     SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);        
     const jchar* textArray = env->GetStringChars(text, NULL);
     size_t textLength = env->GetStringLength(text);
     
     jfloat width = SkScalarToFloat(paint->measureText(textArray, textLength << 1));
     env->ReleaseStringChars(text, textArray);
     return width;
 }
Beispiel #8
0
static void drawGrad(SkCanvas* canvas, const SkScalar d0[], const SkScalar d1[]) {
    const SkRect bounds = SkRect::MakeXYWH(SkIntToScalar(-50),
                                           SkIntToScalar(-50),
                                           SkIntToScalar(200),
                                           SkIntToScalar(100));

    SkPoint c0 = { d0[0], d0[1] };
    SkScalar r0 = d0[2];
    SkPoint c1 = { d1[0], d1[1] };
    SkScalar r1 = d1[2];

    SkColor colors[] = { SK_ColorGREEN, SK_ColorRED };
    SkPaint paint;
    paint.setAntiAlias(true);

    SkString str;
    str.printf("%g,%g,%g  %g,%g,%g",
               SkScalarToFloat(c0.fX), SkScalarToFloat(c0.fY), SkScalarToFloat(r0),
               SkScalarToFloat(c1.fX), SkScalarToFloat(c1.fY), SkScalarToFloat(r1));
    canvas->drawText(str.c_str(), str.size(),
                     bounds.fLeft, bounds.fTop - paint.getTextSize()/2, paint);

    paint.setShader(SkGradientShader::CreateTwoPointConical(c0, r0, c1, r1,
                                                            colors, NULL, 2,
                                                            SkShader::kClamp_TileMode))->unref();
    canvas->drawRect(bounds, paint);

    paint.setShader(NULL);
    paint.setColor(0x66000000);
    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawCircle(c0.fX, c0.fY, r0, paint);
    canvas->drawCircle(c1.fX, c1.fY, r1, paint);
    canvas->drawRect(bounds, paint);
}
// Static function to create a 2D convolution
GrFragmentProcessor*
GrMatrixConvolutionEffect::CreateGaussian(GrTexture* texture,
                                          const SkIRect& bounds,
                                          const SkISize& kernelSize,
                                          SkScalar gain,
                                          SkScalar bias,
                                          const SkIPoint& kernelOffset,
                                          GrTextureDomain::Mode tileMode,
                                          bool convolveAlpha,
                                          SkScalar sigmaX,
                                          SkScalar sigmaY) {
    float kernel[MAX_KERNEL_SIZE];
    int width = kernelSize.width();
    int height = kernelSize.height();
    SkASSERT(width * height <= MAX_KERNEL_SIZE);
    float sum = 0.0f;
    float sigmaXDenom = 1.0f / (2.0f * SkScalarToFloat(SkScalarSquare(sigmaX)));
    float sigmaYDenom = 1.0f / (2.0f * SkScalarToFloat(SkScalarSquare(sigmaY)));
    int xRadius = width / 2;
    int yRadius = height / 2;
    for (int x = 0; x < width; x++) {
      float xTerm = static_cast<float>(x - xRadius);
      xTerm = xTerm * xTerm * sigmaXDenom;
      for (int y = 0; y < height; y++) {
        float yTerm = static_cast<float>(y - yRadius);
        float xyTerm = sk_float_exp(-(xTerm + yTerm * yTerm * sigmaYDenom));
        // Note that the constant term (1/(sqrt(2*pi*sigma^2)) of the Gaussian
       // is dropped here, since we renormalize the kernel below.
        kernel[y * width + x] = xyTerm;
        sum += xyTerm;
      }
    }
    // Normalize the kernel
    float scale = 1.0f / sum;
    for (int i = 0; i < width * height; ++i) {
        kernel[i] *= scale;
    }
    return new GrMatrixConvolutionEffect(texture, bounds, kernelSize, kernel, gain, bias,
                                         kernelOffset, tileMode, convolveAlpha);
}
GrMatrixConvolutionEffect::GrMatrixConvolutionEffect(GrTexture* texture,
                                                     const SkIRect& bounds,
                                                     const SkISize& kernelSize,
                                                     const SkScalar* kernel,
                                                     SkScalar gain,
                                                     SkScalar bias,
                                                     const SkIPoint& kernelOffset,
                                                     GrTextureDomain::Mode tileMode,
                                                     bool convolveAlpha)
  : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture)),
    fKernelSize(kernelSize),
    fGain(SkScalarToFloat(gain)),
    fBias(SkScalarToFloat(bias) / 255.0f),
    fConvolveAlpha(convolveAlpha),
    fDomain(GrTextureDomain::MakeTexelDomainForMode(texture, bounds, tileMode), tileMode) {
    this->initClassID<GrMatrixConvolutionEffect>();
    for (int i = 0; i < kernelSize.width() * kernelSize.height(); i++) {
        fKernel[i] = SkScalarToFloat(kernel[i]);
    }
    fKernelOffset[0] = static_cast<float>(kernelOffset.x());
    fKernelOffset[1] = static_cast<float>(kernelOffset.y());
}
 virtual const char* onGetName() {
     fName.printf("text_%g", SkScalarToFloat(fPaint.getTextSize()));
     if (fDoPos) {
         fName.append("_pos");
     }
     fName.appendf("_%s", fontQualityName(fPaint));
     if (SK_ColorBLACK != fPaint.getColor()) {
         fName.appendf("_%02X", fPaint.getAlpha());
     } else {
         fName.append("_BK");
     }
     return fName.c_str();
 }
void SkSet::dump(SkAnimateMaker* maker) {
    INHERITED::dump(maker);
    if (dur != 1) {
#ifdef SK_CAN_USE_FLOAT
        SkDebugf("dur=\"%g\" ", SkScalarToFloat(SkScalarDiv(dur,1000)));
#else
        SkDebugf("dur=\"%x\" ", SkScalarDiv(dur,1000));
#endif
    }
    //don't want double />\n's
    SkDebugf("/>\n");

}
Beispiel #13
0
void STDMETHODCALLTYPE SkDWriteGeometrySink::AddBeziers(const D2D1_BEZIER_SEGMENT *beziers, UINT beziersCount) {
    SkPoint lastPt;
    fPath->getLastPt(&lastPt);
    D2D1_POINT_2F prevPt = { SkScalarToFloat(lastPt.fX), SkScalarToFloat(lastPt.fY) };

    for (const D2D1_BEZIER_SEGMENT *end = &beziers[beziersCount]; beziers < end; ++beziers) {
        Cubic cubic = { { prevPt.x, prevPt.y },
                        { beziers->point1.x, beziers->point1.y },
                        { beziers->point2.x, beziers->point2.y },
                        { beziers->point3.x, beziers->point3.y }, };
        Quadratic quadratic;
        if (check_quadratic(cubic, quadratic)) {
            fPath->quadTo(quadratic[1].x, quadratic[1].y,
                          quadratic[2].x, quadratic[2].y);
        } else {
            fPath->cubicTo(beziers->point1.x, beziers->point1.y,
                           beziers->point2.x, beziers->point2.y,
                           beziers->point3.x, beziers->point3.y);
        }
        prevPt = beziers->point3;
    }
}
Beispiel #14
0
void SkDumpCanvas::didConcat(const SkMatrix& matrix) {
    SkString str;

    switch (matrix.getType()) {
        case SkMatrix::kTranslate_Mask:
            this->dump(kMatrix_Verb, nullptr, "translate(%g %g)",
                       SkScalarToFloat(matrix.getTranslateX()),
                       SkScalarToFloat(matrix.getTranslateY()));
            break;
        case SkMatrix::kScale_Mask:
            this->dump(kMatrix_Verb, nullptr, "scale(%g %g)",
                       SkScalarToFloat(matrix.getScaleX()),
                       SkScalarToFloat(matrix.getScaleY()));
            break;
        default:
            matrix.toString(&str);
            this->dump(kMatrix_Verb, nullptr, "concat(%s)", str.c_str());
            break;
    }

    this->INHERITED::didConcat(matrix);
}
void GrGpuGLShaders::flushTextureDomain(int s) {
    const GrGLint& uni = fProgramData->fUniLocations.fStages[s].fTexDomUni;
    if (GrGLProgram::kUnusedUniform != uni) {
        const GrRect &texDom =
            fCurrDrawState.fSamplerStates[s].getTextureDomain();

        if (((1 << s) & fDirtyFlags.fTextureChangedMask) ||
            fProgramData->fTextureDomain[s] != texDom) {

            fProgramData->fTextureDomain[s] = texDom;

            float values[4] = {
                GrScalarToFloat(texDom.left()),
                GrScalarToFloat(texDom.top()),
                GrScalarToFloat(texDom.right()),
                GrScalarToFloat(texDom.bottom())
            };

            GrGLTexture* texture = (GrGLTexture*) fCurrDrawState.fTextures[s];
            GrGLTexture::Orientation orientation = texture->orientation();

            // vertical flip if necessary
            if (GrGLTexture::kBottomUp_Orientation == orientation) {
                values[1] = 1.0f - values[1];
                values[3] = 1.0f - values[3];
                // The top and bottom were just flipped, so correct the ordering
                // of elements so that values = (l, t, r, b).
                SkTSwap(values[1], values[3]);
            }

            values[0] *= SkScalarToFloat(texture->contentScaleX());
            values[2] *= SkScalarToFloat(texture->contentScaleX());
            values[1] *= SkScalarToFloat(texture->contentScaleY());
            values[3] *= SkScalarToFloat(texture->contentScaleY());

            GL_CALL(Uniform4fv(uni, 1, values));
        }
    }
}
Beispiel #16
0
 BlurBench(SkScalar rad, SkBlurStyle bs, uint32_t flags = 0) {
     fRadius = rad;
     fStyle = bs;
     fFlags = flags;
     const char* name = rad > 0 ? gStyleName[bs] : "none";
     const char* quality = flags & SkBlurMaskFilter::kHighQuality_BlurFlag ? "high_quality"
                                                                           : "low_quality";
     if (SkScalarFraction(rad) != 0) {
         fName.printf("blur_%.2f_%s_%s", SkScalarToFloat(rad), name, quality);
     } else {
         fName.printf("blur_%d_%s_%s", SkScalarRoundToInt(rad), name, quality);
     }
 }
Beispiel #17
0
ECode CCamera::DotWithNormal(
    /* [in] */ Float dx,
    /* [in] */ Float dy,
    /* [in] */ Float dz,
    /* [out] */ Float* result)
{
    VALIDATE_NOT_NULL(result);

    Sk3DView* v = reinterpret_cast<Sk3DView*>(mNativeInstance);
    SkScalar dot = v->dotWithNormal(dx, dy, dz);
    *result = SkScalarToFloat(dot);
    return NOERROR;
}
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
    SkASSERT(sizeof(glyph) == 2);   // compile-time assert

    SkPaint paint;

    m_font.setupPaint(&paint);

    paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
    SkScalar width = paint.measureText(&glyph, 2);
    
    return SkScalarToFloat(width);
}
Beispiel #19
0
void SkTMaskGamma_build_correcting_lut(uint8_t table[256], U8CPU srcI, SkScalar contrast,
                                       const SkColorSpaceLuminance& srcConvert, SkScalar srcGamma,
                                       const SkColorSpaceLuminance& dstConvert, SkScalar dstGamma) {
    const float src = (float)srcI / 255.0f;
    const float linSrc = srcConvert.toLuma(srcGamma, src);
    //Guess at the dst. The perceptual inverse provides smaller visual
    //discontinuities when slight changes to desaturated colors cause a channel
    //to map to a different correcting lut with neighboring srcI.
    //See https://code.google.com/p/chromium/issues/detail?id=141425#c59 .
    const float dst = 1.0f - src;
    const float linDst = dstConvert.toLuma(dstGamma, dst);

    //Contrast value tapers off to 0 as the src luminance becomes white
    const float adjustedContrast = SkScalarToFloat(contrast) * linDst;

    //Remove discontinuity and instability when src is close to dst.
    //The value 1/256 is arbitrary and appears to contain the instability.
    if (fabs(src - dst) < (1.0f / 256.0f)) {
        float ii = 0.0f;
        for (int i = 0; i < 256; ++i, ii += 1.0f) {
            float rawSrca = ii / 255.0f;
            float srca = apply_contrast(rawSrca, adjustedContrast);
            table[i] = SkToU8(sk_float_round2int(255.0f * srca));
        }
    } else {
        // Avoid slow int to float conversion.
        float ii = 0.0f;
        for (int i = 0; i < 256; ++i, ii += 1.0f) {
            // 'rawSrca += 1.0f / 255.0f' and even
            // 'rawSrca = i * (1.0f / 255.0f)' can add up to more than 1.0f.
            // When this happens the table[255] == 0x0 instead of 0xff.
            // See http://code.google.com/p/chromium/issues/detail?id=146466
            float rawSrca = ii / 255.0f;
            float srca = apply_contrast(rawSrca, adjustedContrast);
            SkASSERT(srca <= 1.0f);
            float dsta = 1.0f - srca;

            //Calculate the output we want.
            float linOut = (linSrc * srca + dsta * linDst);
            SkASSERT(linOut <= 1.0f);
            float out = dstConvert.fromLuma(dstGamma, linOut);

            //Undo what the blit blend will do.
            float result = (out - dst) / (src - dst);
            SkASSERT(sk_float_round2int(255.0f * result) <= 255);

            table[i] = SkToU8(sk_float_round2int(255.0f * result));
        }
    }
}
Beispiel #20
0
bool Path::pointAndNormalAtLength(float length, FloatPoint& point, float& normal) const
{
    SkPathMeasure measure(m_path, false);

    do {
        SkScalar contourLength = measure.getLength();
        if (length <= contourLength) {
            SkVector tangent;
            SkPoint position;

            if (measure.getPosTan(length, &position, &tangent)) {
                normal = rad2deg(SkScalarToFloat(SkScalarATan2(tangent.fY, tangent.fX)));
                point = FloatPoint(SkScalarToFloat(position.fX), SkScalarToFloat(position.fY));
                return true;
            }
        }
        length -= contourLength;
    } while (measure.nextContour());

    normal = 0;
    point = FloatPoint(0, 0);
    return false;
}
void SkPowerMode::init(SkScalar e) {
    fExp = e;
    float ee = SkScalarToFloat(e);

    printf("------ %g\n", ee);
    for (int i = 0; i < 256; i++) {
        float x = i / 255.f;
     //   printf(" %d %g", i, x);
        x = powf(x, ee);
     //   printf(" %g", x);
        int xx = SkScalarRound(SkFloatToScalar(x * 255));
     //   printf(" %d\n", xx);
        fTable[i] = SkToU8(xx);
    }
}
Beispiel #22
0
void Path::PositionCalculator::pointAndNormalAtLength(float length,
                                                      FloatPoint& point,
                                                      float& normalAngle) {
  SkScalar skLength = WebCoreFloatToSkScalar(length);
  if (skLength >= 0) {
    if (skLength < m_accumulatedLength) {
      // Reset path measurer to rewind (and restart from 0).
      m_pathMeasure.setPath(&m_path, false);
      m_accumulatedLength = 0;
    } else {
      skLength -= m_accumulatedLength;
    }

    if (calculatePointAndNormalOnPath(m_pathMeasure, skLength, point,
                                      normalAngle, &m_accumulatedLength))
      return;
  }

  SkPoint position = m_path.getPoint(0);
  point =
      FloatPoint(SkScalarToFloat(position.fX), SkScalarToFloat(position.fY));
  normalAngle = 0;
  return;
}
Beispiel #23
0
static void toString(const SkRRect& rrect, SkString* str) {
    SkRect r = rrect.getBounds();
    str->appendf("[%g,%g %g:%g]",
                 SkScalarToFloat(r.fLeft), SkScalarToFloat(r.fTop),
                 SkScalarToFloat(r.width()), SkScalarToFloat(r.height()));
    if (rrect.isOval()) {
        str->append("()");
    } else if (rrect.isSimple()) {
        const SkVector& rad = rrect.getSimpleRadii();
        str->appendf("(%g,%g)", rad.x(), rad.y());
    } else if (rrect.isComplex()) {
        SkVector radii[4] = {
            rrect.radii(SkRRect::kUpperLeft_Corner),
            rrect.radii(SkRRect::kUpperRight_Corner),
            rrect.radii(SkRRect::kLowerRight_Corner),
            rrect.radii(SkRRect::kLowerLeft_Corner),
        };
        str->appendf("(%g,%g %g,%g %g,%g %g,%g)",
                     radii[0].x(), radii[0].y(),
                     radii[1].x(), radii[1].y(),
                     radii[2].x(), radii[2].y(),
                     radii[3].x(), radii[3].y());
    }
}
HRESULT SkScalerContext_DW::getBoundingBox(SkGlyph* glyph,
        DWRITE_RENDERING_MODE renderingMode,
        DWRITE_TEXTURE_TYPE textureType,
        RECT* bbox)
{
    //Measure raster size.
    fXform.dx = SkFixedToFloat(glyph->getSubXFixed());
    fXform.dy = SkFixedToFloat(glyph->getSubYFixed());

    FLOAT advance = 0;

    UINT16 glyphId = glyph->getGlyphID();

    DWRITE_GLYPH_OFFSET offset;
    offset.advanceOffset = 0.0f;
    offset.ascenderOffset = 0.0f;

    DWRITE_GLYPH_RUN run;
    run.glyphCount = 1;
    run.glyphAdvances = &advance;
    run.fontFace = fTypeface->fDWriteFontFace.get();
    run.fontEmSize = SkScalarToFloat(fTextSizeRender);
    run.bidiLevel = 0;
    run.glyphIndices = &glyphId;
    run.isSideways = FALSE;
    run.glyphOffsets = &offset;

    SkTScopedComPtr<IDWriteGlyphRunAnalysis> glyphRunAnalysis;
    {
        SkAutoExclusive l(DWriteFactoryMutex);
        HRM(fTypeface->fFactory->CreateGlyphRunAnalysis(
                &run,
                1.0f, // pixelsPerDip,
                &fXform,
                renderingMode,
                fMeasuringMode,
                0.0f, // baselineOriginX,
                0.0f, // baselineOriginY,
                &glyphRunAnalysis),
            "Could not create glyph run analysis.");
    }
    {
        Shared l(DWriteFactoryMutex);
        HRM(glyphRunAnalysis->GetAlphaTextureBounds(textureType, bbox),
            "Could not get texture bounds.");
    }
    return S_OK;
}
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const {
  if (!m_platformData.size())
    return 0;

  SkASSERT(sizeof(glyph) == 2);  // compile-time assert

  SkPaint paint;

  m_platformData.setupPaint(&paint);

  paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
  SkScalar width = paint.measureText(&glyph, 2);
  if (!paint.isSubpixelText())
    width = SkScalarRoundToInt(width);
  return SkScalarToFloat(width);
}
Beispiel #26
0
    static int breakText(JNIEnv* env, const SkPaint& paint, const jchar text[],
                         int count, float maxWidth, jfloatArray jmeasured,
                         SkPaint::TextBufferDirection tbd) {
        SkASSERT(paint.getTextEncoding() == SkPaint::kUTF16_TextEncoding);

        SkScalar     measured;
        size_t       bytes = paint.breakText(text, count << 1,
                                   SkFloatToScalar(maxWidth), &measured, tbd);
        SkASSERT((bytes & 1) == 0);

        if (jmeasured && env->GetArrayLength(jmeasured) > 0) {
            AutoJavaFloatArray autoMeasured(env, jmeasured, 1);
            jfloat* array = autoMeasured.ptr();
            array[0] = SkScalarToFloat(measured);
        }
        return bytes >> 1;
    }
Beispiel #27
0
static float anp_getFontMetrics(ANPPaint* paint, ANPFontMetrics* metrics) {
    SkPaint::FontMetrics fm;
    SkScalar spacing = paint->getFontMetrics(&fm);
    if (metrics) {
        metrics->fTop = SkScalarToFloat(fm.fTop);
        metrics->fAscent = SkScalarToFloat(fm.fAscent);
        metrics->fDescent = SkScalarToFloat(fm.fDescent);
        metrics->fBottom = SkScalarToFloat(fm.fBottom);
        metrics->fLeading = SkScalarToFloat(fm.fLeading);
    }
    return SkScalarToFloat(spacing);
}
static jint Interpolator_timeToValues(JNIEnv* env, jobject clazz, jlong interpHandle, jint msec, jfloatArray valueArray)
{
    SkInterpolator* interp = reinterpret_cast<SkInterpolator*>(interpHandle);
    SkInterpolatorBase::Result result;

    float* values = valueArray ? env->GetFloatArrayElements(valueArray, NULL) : NULL;
    result = interp->timeToValues(msec, (SkScalar*)values);

    if (valueArray) {
        int n = env->GetArrayLength(valueArray);
        for (int i = 0; i < n; i++) {
            values[i] = SkScalarToFloat(*(SkScalar*)&values[i]);
        }
        env->ReleaseFloatArrayElements(valueArray, values, 0);
    }

    return static_cast<jint>(result);
}
Beispiel #29
0
 static jfloat measureText_StringII(JNIEnv* env, jobject jpaint, jstring text, int start, int end) {
     NPE_CHECK_RETURN_ZERO(env, jpaint);
     NPE_CHECK_RETURN_ZERO(env, text);
     
     SkPaint* paint = GraphicsJNI::getNativePaint(env, jpaint);        
     const jchar* textArray = env->GetStringChars(text, NULL);
     size_t textLength = env->GetStringLength(text);
     
     int count = end - start;
     if ((start | count) < 0 || (size_t)count > textLength) {
         doThrow(env, "java/lang/IndexOutOfBoundsException");
         return 0;
     }
     
     jfloat width = SkScalarToFloat(paint->measureText(textArray + start, count << 1));
     env->ReleaseStringChars(text, textArray);
     return width;
 }
void TwoPtRadial::init(const SkPoint& center0, SkScalar rad0,
                       const SkPoint& center1, SkScalar rad1) {
    fCenterX = SkScalarToFloat(center0.fX);
    fCenterY = SkScalarToFloat(center0.fY);
    fDCenterX = SkScalarToFloat(center1.fX) - fCenterX;
    fDCenterY = SkScalarToFloat(center1.fY) - fCenterY;
    fRadius = SkScalarToFloat(rad0);
    fDRadius = SkScalarToFloat(rad1) - fRadius;

    fA = sqr(fDCenterX) + sqr(fDCenterY) - sqr(fDRadius);
    fRadius2 = sqr(fRadius);
    fRDR = fRadius * fDRadius;
}