Beispiel #1
0
    static void doDraw(SkCanvas* canvas, SkPaint* paint, const int isrc[],
                       const int idst[], int count) {
        SkMatrix matrix;
        SkPoint src[4], dst[4];

        for (int i = 0; i < count; i++) {
            src[i].set(SkIntToScalar(isrc[2*i+0]), SkIntToScalar(isrc[2*i+1]));
            dst[i].set(SkIntToScalar(idst[2*i+0]), SkIntToScalar(idst[2*i+1]));
        }

        canvas->save();
        matrix.setPolyToPoly(src, dst, count);
        canvas->concat(matrix);

        paint->setColor(SK_ColorGRAY);
        paint->setStyle(SkPaint::kStroke_Style);
        const SkScalar D = SkIntToScalar(64);
        canvas->drawRectCoords(0, 0, D, D, *paint);
        canvas->drawLine(0, 0, D, D, *paint);
        canvas->drawLine(0, D, D, 0, *paint);

        SkPaint::FontMetrics fm;
        paint->getFontMetrics(&fm);
        paint->setColor(SK_ColorRED);
        paint->setStyle(SkPaint::kFill_Style);
        SkScalar x = D/2;
        float y = D/2 - (fm.fAscent + fm.fDescent)/2;
        SkString str;
        str.appendS32(count);
        canvas->drawText(str.c_str(), str.size(),
                         x, SkFloatToScalar(y),
                         *paint);

        canvas->restore();
    }
Beispiel #2
0
void FontPlatformData::setupPaint(SkPaint* paint) const
{
    if (hashTableDeletedFontValue() == mTypeface)
        paint->setTypeface(0);
    else
        paint->setTypeface(mTypeface);

    paint->setAntiAlias(true);
    paint->setSubpixelText(true);
    paint->setHinting(SkPaint::kSlight_Hinting);
    paint->setTextSize(SkFloatToScalar(mTextSize));
    if (!mForceFakeBold & 0x02)
        paint->setFakeBoldText(mFakeBold);
    else
        paint->setFakeBoldText(mForceFakeBold & 0x01);
    if (!mForceFakeItalic & 0x02)
        paint->setTextSkewX(mFakeItalic ? -SK_Scalar1/4 : 0);
    else
        paint->setTextSkewX((mForceFakeItalic & 0x01) ? -SK_Scalar1/4 : 0);
    /*guoxiaolei 20120827 end>*/

#ifndef SUPPORT_COMPLEX_SCRIPTS
    paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
#endif
}
Beispiel #3
0
static void setupPaintForFont(SkPaint* paint, GraphicsContext* context,
                              SkTypeface* face, float size, uint32_t textFlags)
{
    paint->setTextSize(SkFloatToScalar(size));
    paint->setTypeface(face);

    if (!context->couldUseLCDRenderedText()) {
        textFlags &= ~SkPaint::kLCDRenderText_Flag;
        // If we *just* clear our request for LCD, then GDI seems to
        // sometimes give us AA text, and sometimes give us BW text. Since the
        // original intent was LCD, we want to force AA (rather than BW), so we
        // add a special bit to tell Skia to do its best to avoid the BW: by
        // drawing LCD offscreen and downsampling that to AA.
        textFlags |= SkPaint::kGenA8FromLCD_Flag;
    }

    static const uint32_t textFlagsMask = SkPaint::kAntiAlias_Flag |
                                          SkPaint::kLCDRenderText_Flag |
                                          SkPaint::kGenA8FromLCD_Flag;

    // now copy in just the text flags
    SkASSERT(!(textFlags & ~textFlagsMask));
    uint32_t flags = paint->getFlags();
    flags &= ~textFlagsMask;
    flags |= textFlags;
    paint->setFlags(flags);
}
Beispiel #4
0
PassRefPtr<SkImageFilter> FEOffset::createImageFilter(SkiaImageFilterBuilder* builder)
{
    RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));
    Filter* filter = this->filter();
    SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
    return adoptRef(SkOffsetImageFilter::Create(SkFloatToScalar(filter->applyHorizontalScale(m_dx)), SkFloatToScalar(filter->applyVerticalScale(m_dy)), input.get(), &cropRect));
}
Beispiel #5
0
cairo_t *
_cairo_skia_context_create (void *target)
{
    cairo_skia_surface_t *surface = (cairo_skia_surface_t *) target;
    cairo_skia_context_t *cr;

    cr = (cairo_skia_context_t *) _freed_pool_get (&context_pool);
    if (unlikely (cr == NULL)) {
	    cr = new cairo_skia_context_t;
	    if (unlikely (cr == NULL))
		return _cairo_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));

	    cr->path = new SkPath;
	    cr->paint = new SkPaint;
    }

    _cairo_init (&cr->base, &_cairo_skia_context_backend);

    cr->source = NULL;
    cr->source_image = NULL;

    cr->paint->setStrokeWidth (SkFloatToScalar (2.0));

    cr->target = (cairo_skia_surface_t *) cairo_surface_reference ((cairo_surface_t *) target);
    cr->original = (cairo_skia_surface_t *) cairo_surface_reference ((cairo_surface_t *) target);
    cr->canvas = new SkCanvas (*surface->bitmap);
    cr->canvas->save ();

    cairo_matrix_init_identity (&cr->matrix);

    return &cr->base;
}
void FontPlatformData::setupPaint(SkPaint* paint) const
{
    const float ts = m_textSize >= 0 ? m_textSize : 12;

    paint->setAntiAlias(m_style.useAntiAlias == FontRenderStyle::NoPreference ? isSkiaAntiAlias : m_style.useAntiAlias);
    switch (m_style.useHinting) {
    case FontRenderStyle::NoPreference:
        paint->setHinting(skiaHinting);
        break;
    case 0:
        paint->setHinting(SkPaint::kNo_Hinting);
        break;
    default:
        paint->setHinting(static_cast<SkPaint::Hinting>(m_style.hintStyle));
        break;
    }

    paint->setEmbeddedBitmapText(m_style.useBitmaps);
    paint->setTextSize(SkFloatToScalar(ts));
    paint->setTypeface(m_typeface);
    paint->setFakeBoldText(m_fakeBold);
    paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1 / 4 : 0);
    paint->setAutohinted(m_style.useAutoHint);
    paint->setSubpixelText(m_style.useSubpixelPositioning == FontRenderStyle::NoPreference ? useSkiaSubpixelPositioning : m_style.useSubpixelPositioning);

    if (m_style.useAntiAlias == 1 || (m_style.useAntiAlias == FontRenderStyle::NoPreference && isSkiaAntiAlias))
        paint->setLCDRenderText(m_style.useSubpixelRendering == FontRenderStyle::NoPreference ? useSkiaSubpixelRendering : m_style.useSubpixelRendering);
}
void FontPlatformData::setupPaint(SkPaint* paint,
                                  GraphicsContext* context) const {
  paint->setAntiAlias(m_style.useAntiAlias);
  paint->setHinting(static_cast<SkPaint::Hinting>(m_style.hintStyle));
  paint->setEmbeddedBitmapText(m_style.useBitmaps);
  paint->setAutohinted(m_style.useAutoHint);
  if (m_style.useAntiAlias)
    paint->setLCDRenderText(m_style.useSubpixelRendering);

  // Do not enable subpixel text on low-dpi if full hinting is requested.
  bool useSubpixelText = paint->getHinting() != SkPaint::kFull_Hinting ||
                         (context && context->deviceScaleFactor() > 1.0f);

  // TestRunner specifically toggles the subpixel positioning flag.
  if (useSubpixelText)
    paint->setSubpixelText(true);
  else
    paint->setSubpixelText(m_style.useSubpixelPositioning);

  const float ts = m_textSize >= 0 ? m_textSize : 12;
  paint->setTextSize(SkFloatToScalar(ts));
  paint->setTypeface(m_typeface);
  paint->setFakeBoldText(m_syntheticBold);
  paint->setTextSkewX(m_syntheticItalic ? -SK_Scalar1 / 4 : 0);
}
Beispiel #8
0
static void get_adjusted_radii(SkScalar passRadius, int *loRadius, int *hiRadius)
{
    *loRadius = *hiRadius = SkScalarCeil(passRadius);
    if (SkIntToScalar(*hiRadius) - passRadius > SkFloatToScalar(0.5f)) {
        *loRadius = *hiRadius - 1;
    }
}
    static SkMaskFilter* createEmboss(JNIEnv* env, jobject, jfloatArray dirArray, float ambient, float specular, float radius) {
        SkScalar direction[3];

        AutoJavaFloatArray autoDir(env, dirArray, 3);
        float* values = autoDir.ptr();
        for (int i = 0; i < 3; i++) {
            direction[i] = SkFloatToScalar(values[i]);
        }

        SkMaskFilter* filter =  SkBlurMaskFilter::CreateEmboss(direction,
                                                      SkFloatToScalar(ambient),
                                                      SkFloatToScalar(specular),
                                                      SkFloatToScalar(radius));
        ThrowIAE_IfNull(env, filter);
        return filter;
    }
Beispiel #10
0
sk_sp<SkImageFilter> FEDropShadow::createImageFilter() {
  sk_sp<SkImageFilter> input(
      SkiaImageFilterBuilder::build(inputEffect(0), operatingColorSpace()));
  float dx = getFilter()->applyHorizontalScale(m_dx);
  float dy = getFilter()->applyVerticalScale(m_dy);
  float stdX = getFilter()->applyHorizontalScale(m_stdX);
  float stdY = getFilter()->applyVerticalScale(m_stdY);
  Color color = adaptColorToOperatingColorSpace(
      m_shadowColor.combineWithAlpha(m_shadowOpacity));
  SkImageFilter::CropRect cropRect = getCropRect();
  return SkDropShadowImageFilter::Make(
      SkFloatToScalar(dx), SkFloatToScalar(dy), SkFloatToScalar(stdX),
      SkFloatToScalar(stdY), color.rgb(),
      SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode,
      std::move(input), &cropRect);
}
Beispiel #11
0
void 
DrawTargetSkia::StrokeLine(const Point &aStart,
                           const Point &aEnd,
                           const Pattern &aPattern,
                           const StrokeOptions &aStrokeOptions,
                           const DrawOptions &aOptions)
{
  MarkChanged();
  AutoPaintSetup paint(mCanvas.get(), aOptions, aPattern);
  if (!StrokeOptionsToPaint(paint.mPaint, aStrokeOptions)) {
    return;
  }

  mCanvas->drawLine(SkFloatToScalar(aStart.x), SkFloatToScalar(aStart.y), 
                    SkFloatToScalar(aEnd.x), SkFloatToScalar(aEnd.y), 
                    paint.mPaint);
}
Beispiel #12
0
void TextLayout::drawTextOnPath(SkPaint* paint, const Char16* text, Int32 count,
                                Int32 bidiFlags, Float hOffset, Float vOffset,
                                SkPath* path, SkCanvas* canvas)
{

    SkScalar h_ = SkFloatToScalar(hOffset);
    SkScalar v_ = SkFloatToScalar(vOffset);

    sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
            text, 0, count, count, bidiFlags);
    if (value == NULL) {
        return;
    }

    // Beware: this needs Glyph encoding (already done on the Paint constructor)
    canvas->drawTextOnPathHV(value->getGlyphs(), value->getGlyphsCount() * 2, *path, h_, v_, *paint);
}
Beispiel #13
0
bool SkPathContainsPoint(const SkPath& originalPath, const FloatPoint& point, SkPath::FillType ft)
{
    SkRect bounds = originalPath.getBounds();

    // We can immediately return false if the point is outside the bounding
    // rect.  We don't use bounds.contains() here, since it would exclude
    // points on the right and bottom edges of the bounding rect, and we want
    // to include them.
    SkScalar fX = SkFloatToScalar(point.x());
    SkScalar fY = SkFloatToScalar(point.y());
    if (fX < bounds.fLeft || fX > bounds.fRight || fY < bounds.fTop || fY > bounds.fBottom)
        return false;

    // Scale the path to a large size before hit testing for two reasons:
    // 1) Skia has trouble with coordinates close to the max signed 16-bit values, so we scale larger paths down.
    //    TODO: when Skia is patched to work properly with large values, this will not be necessary.
    // 2) Skia does not support analytic hit testing, so we scale paths up to do raster hit testing with subpixel accuracy.
    // 3) Scale the x/y axis separately so an extreme large/small scale factor on one axis won't
    //    ruin the resolution of the other axis.
    SkScalar biggestCoordX = std::max(bounds.fRight, -bounds.fLeft);
    SkScalar biggestCoordY = std::max(bounds.fBottom, -bounds.fTop);
    if (SkScalarNearlyZero(biggestCoordX) || SkScalarNearlyZero(biggestCoordY))
        return false;

    biggestCoordX = std::max(biggestCoordX, std::fabs(fX) + 1);
    biggestCoordY = std::max(biggestCoordY, std::fabs(fY) + 1);

    const SkScalar kMaxCoordinate = SkIntToScalar(1 << 15);
    SkScalar scaleX = kMaxCoordinate / biggestCoordX;
    SkScalar scaleY = kMaxCoordinate / biggestCoordY;

    SkRegion rgn;
    SkRegion clip;
    SkMatrix m;
    SkPath scaledPath(originalPath);

    scaledPath.setFillType(ft);
    m.setScale(scaleX, scaleY);
    scaledPath.transform(m, 0);

    int x = static_cast<int>(floorf(0.5f + point.x() * scaleX));
    int y = static_cast<int>(floorf(0.5f + point.y() * scaleY));
    clip.setRect(x - 1, y - 1, x + 1, y + 1);

    return rgn.setPath(scaledPath, clip);
}
void PlatformGraphicsContext::setLineDash(const DashArray& dashes, float dashOffset)
{
    size_t dashLength = dashes.size();
    if (!dashLength)
        return;

    size_t count = !(dashLength % 2) ? dashLength : dashLength * 2;
    SkScalar* intervals = new SkScalar[count];

    for (unsigned int i = 0; i < count; i++)
        intervals[i] = SkFloatToScalar(dashes[i % dashLength]);
    SkPathEffect **effectPtr = &m_state->pathEffect;
    SkSafeUnref(*effectPtr);
    *effectPtr = new SkDashPathEffect(intervals, count, SkFloatToScalar(dashOffset));

    delete[] intervals;
}
Beispiel #15
0
PassRefPtr<SkImageFilter> FEConvolveMatrix::createImageFilter(SkiaImageFilterBuilder* builder)
{
    RefPtr<SkImageFilter> input(builder->build(inputEffect(0), operatingColorSpace()));

    SkISize kernelSize(SkISize::Make(m_kernelSize.width(), m_kernelSize.height()));
    int numElements = kernelSize.width() * kernelSize.height();
    SkScalar gain = SkFloatToScalar(1.0f / m_divisor);
    SkScalar bias = SkFloatToScalar(m_bias * 255);
    SkIPoint target = SkIPoint::Make(m_targetOffset.x(), m_targetOffset.y());
    SkMatrixConvolutionImageFilter::TileMode tileMode = toSkiaTileMode(m_edgeMode);
    bool convolveAlpha = !m_preserveAlpha;
    OwnPtr<SkScalar[]> kernel = adoptArrayPtr(new SkScalar[numElements]);
    for (int i = 0; i < numElements; ++i)
        kernel[i] = SkFloatToScalar(m_kernelMatrix[numElements - 1 - i]);
    SkImageFilter::CropRect cropRect = getCropRect(builder->cropOffset());
    return adoptRef(SkMatrixConvolutionImageFilter::Create(kernelSize, kernel.get(), gain, bias, target, tileMode, convolveAlpha, input.get(), &cropRect));
}
Beispiel #16
0
static inline float transformAngle(const SkMatrix* matrix, float angleRadians) {
    // Construct and transform a vector oriented at the specified clockwise angle from vertical.
    // Coordinate system: down is increasing Y, right is increasing X.
    SkPoint vector;
    vector.fX = SkFloatToScalar(sinf(angleRadians));
    vector.fY = SkFloatToScalar(-cosf(angleRadians));
    matrix->mapVectors(& vector, 1);

    // Derive the transformed vector's clockwise angle from vertical.
    float result = atan2f(SkScalarToFloat(vector.fX), SkScalarToFloat(-vector.fY));
    if (result < - M_PI_2) {
        result += M_PI;
    } else if (result > M_PI_2) {
        result -= M_PI;
    }
    return result;
}
Beispiel #17
0
SkScalar SampleCode::GetAnimScalar(SkScalar speed, SkScalar period) {
    SkScalar seconds = SkFloatToScalar(gAnimTime / 1000.0f);
    SkScalar value = SkScalarMul(speed, seconds);
    if (period) {
        value = SkScalarMod(value, period);
    }
    return value;
}
Beispiel #18
0
const SkMatrix& TestMatrix(SkMWCRandom* random) {
    static SkMatrix gMatrices[5];
    static bool gOnce;
    if (!gOnce) {
        gMatrices[0].reset();
        gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
        gMatrices[2].setRotate(SkIntToScalar(17));
        gMatrices[3].setRotate(SkIntToScalar(185));
        gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
        gMatrices[3].postScale(SkIntToScalar(2), SK_ScalarHalf);
        gMatrices[4].setRotate(SkIntToScalar(215));
        gMatrices[4].set(SkMatrix::kMPersp0, SkFloatToScalar(0.00013f));
        gMatrices[4].set(SkMatrix::kMPersp1, SkFloatToScalar(-0.000039f));
        gOnce = true;
    }
    return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
}
static cairo_status_t
_cairo_skia_context_set_miter_limit (void *abstract_cr, double limit)
{
    cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;

    cr->paint->setStrokeMiter (SkFloatToScalar (limit));
    return CAIRO_STATUS_SUCCESS;
}
void Font::drawComplexText(GraphicsContext* gc, TextRun const& run,
                           FloatPoint const& point, int, int) const
{
    SkCanvas*   canvas = gc->platformContext()->mCanvas;
    SkPaint     paint;

    if (!setupForText(&paint, gc, primaryFont())) {
        return;
    }

    // go to chars, instead of glyphs, which was set by setupForText()
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);

    canvas->drawText(run.characters(), run.length() << 1,
                     SkFloatToScalar(point.x()), SkFloatToScalar(point.y()),
                     paint);
}
Beispiel #21
0
SkImageFilter* FEDisplacementMap::createImageFilter(SkiaImageFilterBuilder* builder)
{
    SkImageFilter* color = builder->build(inputEffect(0), operatingColorSpace());
    SkImageFilter* displ = builder->build(inputEffect(1), operatingColorSpace());
    SkDisplacementMapEffect::ChannelSelectorType typeX = toSkiaMode(m_xChannelSelector);
    SkDisplacementMapEffect::ChannelSelectorType typeY = toSkiaMode(m_yChannelSelector);
    return new SkDisplacementMapEffect(typeX, typeY, SkFloatToScalar(m_scale), displ, color);
}
Beispiel #22
0
    virtual void onDraw(SkCanvas* canvas) {
        this->drawBG(canvas);

        SkColor colors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorGREEN, SK_ColorRED };
        SkScalar pos[] = { 0, SkFloatToScalar(0.01f), SkFloatToScalar(0.99f), SK_Scalar1 };
        SkPoint c0;
        c0.iset(-80, 25);
        SkScalar r0 = SkIntToScalar(70);
        SkPoint c1;
        c1.iset(0, 25);
        SkScalar r1 = SkIntToScalar(150);
        SkShader* s = SkGradientShader::CreateTwoPointRadial(c0, r0, c1, r1, colors,
                                                             pos, SK_ARRAY_COUNT(pos),
                                                             SkShader::kClamp_TileMode);
        SkPaint paint;
        paint.setShader(s)->unref();
        canvas->drawPaint(paint);
    }
Beispiel #23
0
SkMaskFilter* CEmbossMaskFilter::NativeConstructor(
    /* [in] */ const ArrayOf<Float>& dirArray,
    /* [in] */ Float ambient,
    /* [in] */ Float specular,
    /* [in] */ Float blurRadius)
{
    SkScalar direction[3];
    for (Int32 i = 0; i < 3; i++) {
        direction[i] = SkFloatToScalar(dirArray[i]);
    }

    SkMaskFilter* filter =  SkBlurMaskFilter::CreateEmboss(
                                direction,
                                SkFloatToScalar(ambient),
                                SkFloatToScalar(specular),
                                SkFloatToScalar(blurRadius));
    return filter;
}
static void Interpolator_setRepeatMirror(JNIEnv* env, jobject clazz, jlong interpHandle, jfloat repeatCount, jboolean mirror)
{
    SkInterpolator* interp = reinterpret_cast<SkInterpolator*>(interpHandle);
    if (repeatCount > 32000)
        repeatCount = 32000;

    interp->setRepeatCount(SkFloatToScalar(repeatCount));
    interp->setMirror(mirror != 0);
}
static cairo_status_t
_cairo_skia_context_set_line_width (void *abstract_cr,
				    double line_width)
{
    cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;

    cr->paint->setStrokeWidth (SkFloatToScalar (line_width));
    return CAIRO_STATUS_SUCCESS;
}
Beispiel #26
0
bool SkPathContainsPoint(SkPath* originalPath, const FloatPoint& point, SkPath::FillType ft)
{
    SkRect bounds = originalPath->getBounds();

    // We can immediately return false if the point is outside the bounding
    // rect.  We don't use bounds.contains() here, since it would exclude
    // points on the right and bottom edges of the bounding rect, and we want
    // to include them.
    SkScalar fX = SkFloatToScalar(point.x());
    SkScalar fY = SkFloatToScalar(point.y());
    if (fX < bounds.fLeft || fX > bounds.fRight || fY < bounds.fTop || fY > bounds.fBottom)
        return false;

    // Scale the path to a large size before hit testing for two reasons:
    // 1) Skia has trouble with coordinates close to the max signed 16-bit values, so we scale larger paths down.
    //    TODO: when Skia is patched to work properly with large values, this will not be necessary.
    // 2) Skia does not support analytic hit testing, so we scale paths up to do raster hit testing with subpixel accuracy.
    SkScalar biggestCoord = std::max(std::max(std::max(bounds.fRight, bounds.fBottom), -bounds.fLeft), -bounds.fTop);
    if (SkScalarNearlyZero(biggestCoord))
        return false;
    biggestCoord = std::max(std::max(biggestCoord, fX + 1), fY + 1);

    const SkScalar kMaxCoordinate = SkIntToScalar(1 << 15);
    SkScalar scale = SkScalarDiv(kMaxCoordinate, biggestCoord);

    SkRegion rgn;  
    SkRegion clip;
    SkMatrix m;
    SkPath scaledPath;

    SkPath::FillType originalFillType = originalPath->getFillType();
    originalPath->setFillType(ft);

    m.setScale(scale, scale);
    originalPath->transform(m, &scaledPath);

    int x = static_cast<int>(floorf(0.5f + point.x() * scale));
    int y = static_cast<int>(floorf(0.5f + point.y() * scale));
    clip.setRect(x - 1, y - 1, x + 1, y + 1);

    bool contains = rgn.setPath(scaledPath, clip);
    originalPath->setFillType(originalFillType);
    return contains;
}
Beispiel #27
0
void PlatformContextSkia::beginLayerClippedToImage(const FloatRect& rect,
                                                   const ImageBuffer* imageBuffer)
{
    SkRect bounds = { SkFloatToScalar(rect.x()), SkFloatToScalar(rect.y()),
                      SkFloatToScalar(rect.maxX()), SkFloatToScalar(rect.maxY()) };

    if (imageBuffer->internalSize().isEmpty()) {
        m_canvas->clipRect(bounds);
        return;
    }

    // Skia doesn't support clipping to an image, so we create a layer. The next
    // time restore is invoked the layer and |imageBuffer| are combined to
    // create the resulting image.

    m_state->m_clip = bounds;
    // Get the absolute coordinates of the stored clipping rectangle to make it
    // independent of any transform changes.
    canvas()->getTotalMatrix().mapRect(&m_state->m_clip);

    SkCanvas::SaveFlags saveFlags = static_cast<SkCanvas::SaveFlags>(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag);
    saveLayer(&bounds, 0, saveFlags);

    const SkBitmap* bitmap = imageBuffer->context()->platformContext()->bitmap();

    if (m_trackOpaqueRegion) {
        SkRect opaqueRect = bitmap->isOpaque() ? m_state->m_clip : SkRect::MakeEmpty();
        m_opaqueRegion.setImageMask(opaqueRect);
    }

    // Copy off the image as |imageBuffer| may be deleted before restore is invoked.
    if (!bitmap->pixelRef()) {
        // The bitmap owns it's pixels. This happens when we've allocated the
        // pixels in some way and assigned them directly to the bitmap (as
        // happens when we allocate a DIB). In this case the assignment operator
        // does not copy the pixels, rather the copied bitmap ends up
        // referencing the same pixels. As the pixels may not live as long as we
        // need it to, we copy the image.
        bitmap->copyTo(&m_state->m_imageBufferClip, SkBitmap::kARGB_8888_Config);
    } else {
        // If there is a pixel ref, we can safely use the assignment operator.
        m_state->m_imageBufferClip = *bitmap;
    }
}
Beispiel #28
0
static SkPoint* SetCurve(float x0, float y0,
                         float x1, float y1,
                         float x2, float y2,
                         float x3, float y3,
                         SkPoint crv[4]) {
    crv[0].fX = SkFloatToScalar(x0);   crv[0].fY = SkFloatToScalar(y0);
    crv[1].fX = SkFloatToScalar(x1);   crv[1].fY = SkFloatToScalar(y1);
    crv[2].fX = SkFloatToScalar(x2);   crv[2].fY = SkFloatToScalar(y2);
    crv[3].fX = SkFloatToScalar(x3);   crv[3].fY = SkFloatToScalar(y3);
    return crv;
}
Beispiel #29
0
void svg_renderer::update_drawing (const QTransform &transform, const QRectF &rect_to_update, int cache_object_type)
{
  m_cache->lock ();
  DO_ON_EXIT (m_cache->unlock ());

  double cache_zoom_x = m_cache->zoom_x ();
  double cache_zoom_y = m_cache->zoom_y ();
  double cur_zoom_x = transform.m11 ();
  double cur_zoom_y = transform.m22 ();
  QRectF rect_to_draw = rect_to_update;
  QTransform real_transform = transform;

  SkBitmap bitmap;
  bitmap.setConfig (SkBitmap::kARGB_8888_Config, rect_to_draw.width (), rect_to_draw.height ());
  bitmap.allocPixels ();
  SkBitmapDevice device (bitmap);
  SkCanvas canvas (&device);

  if (!are_equal (cache_zoom_x, cur_zoom_x) || !are_equal (cache_zoom_y, cur_zoom_y))
    {
      QTransform scale_transform = QTransform::fromScale (cache_zoom_x / cur_zoom_x, cache_zoom_y / cur_zoom_y);
      real_transform = real_transform * scale_transform;
      canvas.setMatrix (qt2skia::matrix (scale_transform.inverted ()));
      rect_to_draw = scale_transform.mapRect (rect_to_draw);
    }

  canvas.drawColor (SK_ColorTRANSPARENT, SkXfermode::kSrc_Mode);

  pair<render_cache_id, render_cache_id> it_pair = render_cache_id::get_id_for_pixel_rect (real_transform, rect_to_draw, cache_object_type);

  for (int x = it_pair.first.x (); x <= it_pair.second.x (); x++)
    for (int y = it_pair.first.y (); y <= it_pair.second.y (); y++)
      {
        render_cache_id cur_id (x, y, cache_object_type);
        SkBitmap bitmap = m_cache->bitmap (cur_id);
        if (bitmap.empty ())
          continue;

        QRectF pixel_rect = cur_id.pixel_rect (real_transform);
        canvas.drawBitmap (bitmap, SkFloatToScalar (pixel_rect.x ()), SkFloatToScalar (pixel_rect.y ()));
      }

  m_cache->set_current_screen (bitmap, cache_object_type);
}
Beispiel #30
0
void Font::drawGlyphs(GraphicsContext* graphicsContext,
                      const SimpleFontData* font,
                      const GlyphBuffer& glyphBuffer,
                      int from,
                      int numGlyphs,
                      const FloatPoint& point) const
{
    SkColor color = graphicsContext->platformContext()->effectiveFillColor();
    unsigned char alpha = SkColorGetA(color);
    // Skip 100% transparent text; no need to draw anything.
    if (!alpha && graphicsContext->platformContext()->getStrokeStyle() == NoStroke && !graphicsContext->hasShadow())
        return;

    // We draw the glyphs in chunks to avoid having to do a heap allocation for
    // the arrays of characters and advances.
    const int kMaxBufferLength = 256;
    Vector<WORD, kMaxBufferLength> glyphs;
    Vector<int, kMaxBufferLength> advances;
    int glyphIndex = 0;  // The starting glyph of the current chunk.

    // In order to round all offsets to the correct pixel boundary, this code keeps track of the absolute position
    // of each glyph in floating point units and rounds to integer advances at the last possible moment.

    float horizontalOffset = point.x(); // The floating point offset of the left side of the current glyph.
    int lastHorizontalOffsetRounded = lroundf(horizontalOffset); // The rounded offset of the left side of the last glyph rendered.
    while (glyphIndex < numGlyphs) {
        // How many chars will be in this chunk?
        int curLen = std::min(kMaxBufferLength, numGlyphs - glyphIndex);
        glyphs.resize(curLen);
        advances.resize(curLen);

        float currentWidth = 0;
        for (int i = 0; i < curLen; ++i, ++glyphIndex) {
            glyphs[i] = glyphBuffer.glyphAt(from + glyphIndex);
            horizontalOffset += glyphBuffer.advanceAt(from + glyphIndex);
            advances[i] = lroundf(horizontalOffset) - lastHorizontalOffsetRounded;
            lastHorizontalOffsetRounded += advances[i];
            currentWidth += glyphBuffer.advanceAt(from + glyphIndex);
            
            // Bug 26088 - very large positive or negative runs can fail to
            // render so we clamp the size here. In the specs, negative
            // letter-spacing is implementation-defined, so this should be
            // fine, and it matches Safari's implementation. The call actually
            // seems to crash if kMaxNegativeRun is set to somewhere around
            // -32830, so we give ourselves a little breathing room.
            const int maxNegativeRun = -32768;
            const int maxPositiveRun =  32768;
            if ((currentWidth + advances[i] < maxNegativeRun) || (currentWidth + advances[i] > maxPositiveRun)) 
                advances[i] = 0;
        }

        SkPoint origin = point;
        origin.fX += SkFloatToScalar(horizontalOffset - point.x() - currentWidth);
        paintSkiaText(graphicsContext, font->platformData(), curLen, &glyphs[0], &advances[0], 0, &origin);
    }
}