예제 #1
0
static unsigned color_dist16(uint16_t a, uint16_t b) {
    unsigned dr = SkAbs32(SkPacked16ToR32(a) - SkPacked16ToR32(b));
    unsigned dg = SkAbs32(SkPacked16ToG32(a) - SkPacked16ToG32(b));
    unsigned db = SkAbs32(SkPacked16ToB32(a) - SkPacked16ToB32(b));
    
    return SkMax32(dr, SkMax32(dg, db));
}
예제 #2
0
static inline SkFDot6 cheap_distance(SkFDot6 dx, SkFDot6 dy)
{
    dx = SkAbs32(dx);
    dy = SkAbs32(dy);
    // return max + min/2
    if (dx > dy)
        dx += dy >> 1;
    else
예제 #3
0
 /*  return non-zero if the path is too big, and should be shrunk to avoid
     overflows during intermediate calculations. Note that we compute the
     bounds for this. If we had a custom callback/walker for paths, we could
     perhaps go faster by using that, and just perform the abs | in that
     routine
 */
 static int needs_to_shrink(const SkPath& path) {
     const SkRect& r = path.getBounds();
     SkFixed mask = SkAbs32(r.fLeft);
     mask |= SkAbs32(r.fTop);
     mask |= SkAbs32(r.fRight);
     mask |= SkAbs32(r.fBottom);
     // we need the top 3 bits clear (after abs) to avoid overflow
     return mask >> 29;
 }
예제 #4
0
// returns 0..255
static unsigned color_dist32(SkPMColor c, U8CPU r, U8CPU g, U8CPU b) {
    SkASSERT(r <= 0xFF);
    SkASSERT(g <= 0xFF);
    SkASSERT(b <= 0xFF);

    unsigned dr = SkAbs32(SkGetPackedR32(c) - r);
    unsigned dg = SkAbs32(SkGetPackedG32(c) - g);
    unsigned db = SkAbs32(SkGetPackedB32(c) - b);

    return SkMax32(dr, SkMax32(dg, db));
}
예제 #5
0
// returns 0..31
static unsigned color_dist16(uint16_t c, unsigned r, unsigned g, unsigned b) {
    SkASSERT(r <= SK_R16_MASK);
    SkASSERT(g <= SK_G16_MASK);
    SkASSERT(b <= SK_B16_MASK);

    unsigned dr = SkAbs32(SkGetPackedR16(c) - r);
    unsigned dg = SkAbs32(SkGetPackedG16(c) - g) >> (SK_G16_BITS - SK_R16_BITS);
    unsigned db = SkAbs32(SkGetPackedB16(c) - b);

    return SkMax32(dr, SkMax32(dg, db));
}
// returns 0..15
static unsigned color_dist4444(uint16_t c, unsigned r, unsigned g, unsigned b)
{
    SkASSERT(r <= 0xF);
    SkASSERT(g <= 0xF);
    SkASSERT(b <= 0xF);

    unsigned dr = SkAbs32(SkGetPackedR4444(c) - r);
    unsigned dg = SkAbs32(SkGetPackedG4444(c) - g);
    unsigned db = SkAbs32(SkGetPackedB4444(c) - b);

    return SkMax32(dr, SkMax32(dg, db));
}
예제 #7
0
static inline SkFixed quickSkFDot6Div(SkFDot6 a, SkFDot6 b) {
    if (SkAbs32(b) < kInverseTableSize) {
        SkASSERT((int64_t)a * QuickFDot6Inverse::Lookup(b) <= SK_MaxS32);
        SkFixed ourAnswer = (a * QuickFDot6Inverse::Lookup(b)) >> 6;
        #ifdef SK_DEBUG
        SkFixed directAnswer = SkFDot6Div(a, b);
        SkASSERT(
            (directAnswer == 0 && ourAnswer == 0) ||
            SkFixedDiv(SkAbs32(directAnswer - ourAnswer), SkAbs32(directAnswer)) <= 1 << 10
        );
        #endif
        return ourAnswer;
    } else {
예제 #8
0
static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
                              jint offset, jint stride, jint width, jint height,
                              jint configHandle, jboolean isMutable) {
    SkColorType colorType = GraphicsJNI::legacyBitmapConfigToColorType(configHandle);
    if (NULL != jColors) {
        size_t n = env->GetArrayLength(jColors);
        if (n < SkAbs32(stride) * (size_t)height) {
            doThrowAIOOBE(env);
            return NULL;
        }
    }

    // ARGB_4444 is a deprecated format, convert automatically to 8888
    if (colorType == kARGB_4444_SkColorType) {
        colorType = kN32_SkColorType;
    }

    SkBitmap bitmap;
    bitmap.setInfo(SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType));

    jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
    if (NULL == buff) {
        return NULL;
    }

    if (jColors != NULL) {
        GraphicsJNI::SetPixels(env, jColors, offset, stride,
                0, 0, width, height, bitmap);
    }

    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,
            getPremulBitmapCreateFlags(isMutable), NULL, NULL);
}
예제 #9
0
static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
                              jint offset, jint stride, jint width, jint height,
                              jint configHandle, jboolean isMutable) {
    SkBitmap::Config config = static_cast<SkBitmap::Config>(configHandle);
    if (NULL != jColors) {
        size_t n = env->GetArrayLength(jColors);
        if (n < SkAbs32(stride) * (size_t)height) {
            doThrowAIOOBE(env);
            return NULL;
        }
    }

    // ARGB_4444 is a deprecated format, convert automatically to 8888
    if (config == SkBitmap::kARGB_4444_Config) {
        config = SkBitmap::kARGB_8888_Config;
    }

    SkBitmap bitmap;
    bitmap.setConfig(config, width, height);

    jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
    if (NULL == buff) {
        return NULL;
    }

    if (jColors != NULL) {
        GraphicsJNI::SetPixels(env, jColors, offset, stride,
                0, 0, width, height, bitmap, true);
    }

    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff,
            getPremulBitmapCreateFlags(isMutable), NULL, NULL);
}
예제 #10
0
static jobject Bitmap_creator(JNIEnv* env, jobject, jintArray jColors,
                              int offset, int stride, int width, int height,
                              SkBitmap::Config config, jboolean isMutable) {
    if (NULL != jColors) {
        size_t n = env->GetArrayLength(jColors);
        if (n < SkAbs32(stride) * (size_t)height) {
            doThrowAIOOBE(env);
            return NULL;
        }
    }

    SkBitmap bitmap;

    bitmap.setConfig(config, width, height);

    jbyteArray buff = GraphicsJNI::allocateJavaPixelRef(env, &bitmap, NULL);
    if (NULL == buff) {
        return NULL;
    }

    if (jColors != NULL) {
        GraphicsJNI::SetPixels(env, jColors, offset, stride,
                               0, 0, width, height, bitmap);
    }

    return GraphicsJNI::createBitmap(env, new SkBitmap(bitmap), buff, isMutable, NULL);
}
static int similarBits(const SkBitmap& gr, const SkBitmap& sk) {
    const int kRowCount = 3;
    const int kThreshold = 3;
    int width = SkTMin(gr.width(), sk.width());
    if (width < kRowCount) {
        return true;
    }
    int height = SkTMin(gr.height(), sk.height());
    if (height < kRowCount) {
        return true;
    }
    int errorTotal = 0;
    SkTArray<int, true> errorRows;
    errorRows.push_back_n(width * kRowCount);
    SkAutoLockPixels autoGr(gr);
    SkAutoLockPixels autoSk(sk);
    for (int y = 0; y < height; ++y) {
        SkPMColor* grRow = gr.getAddr32(0, y);
        SkPMColor* skRow = sk.getAddr32(0, y);
        int* base = &errorRows[0];
        int* cOut = &errorRows[y % kRowCount];
        for (int x = 0; x < width; ++x) {
            SkPMColor grColor = grRow[x];
            SkPMColor skColor = skRow[x];
            int dr = SkGetPackedR32(grColor) - SkGetPackedR32(skColor);
            int dg = SkGetPackedG32(grColor) - SkGetPackedG32(skColor);
            int db = SkGetPackedB32(grColor) - SkGetPackedB32(skColor);
            int error = cOut[x] = SkTMax(SkAbs32(dr), SkTMax(SkAbs32(dg), SkAbs32(db)));
            if (error < kThreshold || x < 2) {
                continue;
            }
            if (base[x - 2] < kThreshold
                    || base[width + x - 2] < kThreshold
                    || base[width * 2 + x - 2] < kThreshold
                    || base[x - 1] < kThreshold
                    || base[width + x - 1] < kThreshold
                    || base[width * 2 + x - 1] < kThreshold
                    || base[x] < kThreshold
                    || base[width + x] < kThreshold
                    || base[width * 2 + x] < kThreshold) {
                continue;
            }
            errorTotal += error;
        }
    }
    return errorTotal;
}
예제 #12
0
uint8_t SkBlurMask::ProfileLookup(const uint8_t *profile, int loc, int blurred_width, int sharp_width) {
    int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far are we from the original edge?
    int ox = dx >> 1;
    if (ox < 0) {
        ox = 0;
    }

    return profile[ox];
}
static inline unsigned int profile_lookup( unsigned int *profile, int loc, int blurred_width, int sharp_width ) {
    int dx = SkAbs32(((loc << 1) + 1) - blurred_width) - sharp_width; // how far are we from the original edge?
    int ox = dx >> 1;
    if (ox < 0) {
        ox = 0;
    }

    return profile[ox];
}
예제 #14
0
sk_sp<SkImage> SkReadBuffer::readImage() {
    if (fInflator) {
        SkImage* img = fInflator->getImage(this->read32());
        return img ? sk_ref_sp(img) : nullptr;
    }

    int width = this->read32();
    int height = this->read32();
    if (width <= 0 || height <= 0) {    // SkImage never has a zero dimension
        this->validate(false);
        return nullptr;
    }

    int32_t size = this->read32();
    if (size == SK_NaN32) {
        // 0x80000000 is never valid, since it cannot be passed to abs().
        this->validate(false);
        return nullptr;
    }
    if (size == 0) {
        // The image could not be encoded at serialization time - return an empty placeholder.
        return MakeEmptyImage(width, height);
    }

    // we used to negate the size for "custom" encoded images -- ignore that signal (Dec-2017)
    size = SkAbs32(size);
    if (size == 1) {
        // legacy check (we stopped writing this for "raw" images Nov-2017)
        this->validate(false);
        return nullptr;
    }

    sk_sp<SkData> data = SkData::MakeUninitialized(size);
    if (!this->readPad32(data->writable_data(), size)) {
        this->validate(false);
        return nullptr;
    }
    if (this->isVersionLT(kDontNegateImageSize_Version)) {
        (void)this->read32();   // originX
        (void)this->read32();   // originY
    }

    sk_sp<SkImage> image;
    if (fProcs.fImageProc) {
        image = fProcs.fImageProc(data->data(), data->size(), fProcs.fImageCtx);
    }
    if (!image) {
        image = SkImage::MakeFromEncoded(std::move(data));
    }
    // Question: are we correct to return an "empty" image instead of nullptr, if the decoder
    //           failed for some reason?
    return image ? image : MakeEmptyImage(width, height);
}
SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
    int storedCount = buffer.readS32();
    this->initAlloc(SkAbs32(storedCount), storedCount < 0);

    for (int i = 0; i < fCount; ++i) {
        fFilters[i] = (SkImageFilter*)buffer.readFlattenable();
    }

    if (fModes) {
        SkASSERT(storedCount < 0);
        buffer.read(fModes, fCount * sizeof(fModes[0]));
    } else {
        SkASSERT(storedCount >= 0);
    }
}
SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
    int storedCount = buffer.readInt();
    this->initAlloc(SkAbs32(storedCount), storedCount < 0);

    for (int i = 0; i < fCount; ++i) {
        fFilters[i] = buffer.readFlattenableT<SkImageFilter>();
    }

    if (fModes) {
        SkASSERT(storedCount < 0);
        SkASSERT(buffer.getArrayCount() == fCount * sizeof(fModes[0]));
        buffer.readByteArray(fModes);
    } else {
        SkASSERT(storedCount >= 0);
    }
}
예제 #17
0
void SkGraphics::Init() {
    SkGlobals::Init();

#ifdef BUILD_EMBOSS_TABLE
    SkEmbossMask_BuildTable();
#endif
#ifdef BUILD_RADIALGRADIENT_TABLE
    SkRadialGradient_BuildTable();
#endif

#ifdef SK_DEBUGx
    int i;

    static const struct {
        const char* fTypeName;
        size_t      fSizeOf;
    } gTypeSize[] = {
        typesizeline(char),
        typesizeline(short),
        typesizeline(int),
        typesizeline(long),
        typesizeline(size_t),
        typesizeline(void*),

        typesizeline(S8CPU),
        typesizeline(U8CPU),
        typesizeline(S16CPU),
        typesizeline(U16CPU),

        typesizeline(SkPoint),
        typesizeline(SkRect),
        typesizeline(SkMatrix),
        typesizeline(SkPath),
        typesizeline(SkGlyph),
        typesizeline(SkRefCnt),

        typesizeline(SkPaint),
        typesizeline(SkCanvas),
        typesizeline(SkBlitter),
        typesizeline(SkShader),
        typesizeline(SkXfermode),
        typesizeline(SkPathEffect)
    };

#ifdef SK_CPU_BENDIAN
    SkDebugf("SkGraphics: big-endian\n");
#else
    SkDebugf("SkGraphics: little-endian\n");
#endif

    {
        char    test = 0xFF;
        int     itest = test;   // promote to int, see if it sign-extended
        if (itest < 0)
            SkDebugf("SkGraphics: char is signed\n");
        else
            SkDebugf("SkGraphics: char is unsigned\n");
    }
    for (i = 0; i < (int)SK_ARRAY_COUNT(gTypeSize); i++) {
        SkDebugf("SkGraphics: sizeof(%s) = %d\n",
                 gTypeSize[i].fTypeName, gTypeSize[i].fSizeOf);
    }

#endif

    if (false)  // test asm fixmul
    {
        int j;
        SkMSec now = SkTime::GetMSecs();
        for (j = 0; j < BIG_LOOP_COUNT; j++) {
            (void)SkFixedMul_portable(0x8000, 0x150000);
        }
        SkMSec now2 = SkTime::GetMSecs();
        printf("-------- SkFixedMul_portable = %d\n", now2 - now);

        for (j = 0; j < BIG_LOOP_COUNT; j++) {
            (void)SkFixedMul(0x8000, 0x150000);
        }
        printf("-------- SkFixedMul = %d\n", SkTime::GetMSecs() - now2);

        SkRandom rand;
        for (j = 0; j < 10000; j++) {
            SkFixed a = rand.nextS() >> 8;
            SkFixed b = rand.nextS() >> 8;
            SkFixed c1 = SkFixedMul_portable(a, b);
            SkFixed c2 = SkFixedMul(a, b);
            if (SkAbs32(c1 - c2) > 1)
                printf("------ FixMul disagreement: (%x %x) slow=%x fast=%x\n", a, b, c1, c2);
        }
    }
void PlatformGraphicsContextSkia::drawLine(const IntPoint& point1,
                                       const IntPoint& point2)
{
    StrokeStyle style = m_state->strokeStyle;
    if (style == NoStroke)
        return;

    SkPaint paint;
    SkCanvas* canvas = mCanvas;
    const int idx = SkAbs32(point2.x() - point1.x());
    const int idy = SkAbs32(point2.y() - point1.y());

    // Special-case horizontal and vertical lines that are really just dots
    if (setupPaintStroke(&paint, 0, !idy) && (!idx || !idy)) {
        const SkScalar diameter = paint.getStrokeWidth();
        const SkScalar radius = SkScalarHalf(diameter);
        SkScalar x = SkIntToScalar(SkMin32(point1.x(), point2.x()));
        SkScalar y = SkIntToScalar(SkMin32(point1.y(), point2.y()));
        SkScalar dx, dy;
        int count;
        SkRect bounds;

        if (!idy) { // Horizontal
            bounds.set(x, y - radius, x + SkIntToScalar(idx), y + radius);
            x += radius;
            dx = diameter * 2;
            dy = 0;
            count = idx;
        } else { // Vertical
            bounds.set(x - radius, y, x + radius, y + SkIntToScalar(idy));
            y += radius;
            dx = 0;
            dy = diameter * 2;
            count = idy;
        }

        // The actual count is the number of ONs we hit alternating
        // ON(diameter), OFF(diameter), ...
        {
            SkScalar width = SkScalarDiv(SkIntToScalar(count), diameter);
            // Now compute the number of cells (ON and OFF)
            count = SkScalarRound(width);
            // Now compute the number of ONs
            count = (count + 1) >> 1;
        }

        SkAutoMalloc storage(count * sizeof(SkPoint));
        SkPoint* verts = (SkPoint*)storage.get();
        // Now build the array of vertices to past to drawPoints
        for (int i = 0; i < count; i++) {
            verts[i].set(x, y);
            x += dx;
            y += dy;
        }

        paint.setStyle(SkPaint::kFill_Style);
        paint.setPathEffect(0);

        // Clipping to bounds is not required for correctness, but it does
        // allow us to reject the entire array of points if we are completely
        // offscreen. This is common in a webpage for android, where most of
        // the content is clipped out. If drawPoints took an (optional) bounds
        // parameter, that might even be better, as we would *just* use it for
        // culling, and not both wacking the canvas' save/restore stack.
        canvas->save(SkCanvas::kClip_SaveFlag);
        canvas->clipRect(bounds);
        canvas->drawPoints(SkCanvas::kPoints_PointMode, count, verts, paint);
        canvas->restore();
    } else {
/**
 *  Test decoding an image in premultiplied mode and unpremultiplied mode and compare
 *  them.
 */
static void compare_unpremul(skiatest::Reporter* reporter, const SkString& filename) {
    // Decode a resource:
    SkBitmap bm8888;
    SkBitmap bm8888Unpremul;

    SkFILEStream stream(filename.c_str());

    SkImageDecoder::Format format = SkImageDecoder::GetStreamFormat(&stream);
    if (skip_image_format(format)) {
        return;
    }

    SkAutoTDelete<SkImageDecoder> decoder(SkImageDecoder::Factory(&stream));
    if (NULL == decoder.get()) {
        SkDebugf("couldn't decode %s\n", filename.c_str());
        return;
    }

    bool success = decoder->decode(&stream, &bm8888, SkBitmap::kARGB_8888_Config,
                                   SkImageDecoder::kDecodePixels_Mode);
    if (!success) {
        return;
    }

    success = stream.rewind();
    REPORTER_ASSERT(reporter, success);
    if (!success) {
        return;
    }

    decoder->setRequireUnpremultipliedColors(true);
    success = decoder->decode(&stream, &bm8888Unpremul, SkBitmap::kARGB_8888_Config,
                              SkImageDecoder::kDecodePixels_Mode);
    if (!success) {
        return;
    }

    bool dimensionsMatch = bm8888.width() == bm8888Unpremul.width()
                           && bm8888.height() == bm8888Unpremul.height();
    REPORTER_ASSERT(reporter, dimensionsMatch);
    if (!dimensionsMatch) {
        return;
    }

    // Only do the comparison if the two bitmaps are both 8888.
    if (bm8888.config() != SkBitmap::kARGB_8888_Config
        || bm8888Unpremul.config() != SkBitmap::kARGB_8888_Config) {
        return;
    }

    // Now compare the two bitmaps.
    for (int i = 0; i < bm8888.width(); ++i) {
        for (int j = 0; j < bm8888.height(); ++j) {
            // "c0" is the color of the premultiplied bitmap at (i, j).
            const SkPMColor c0 = *bm8888.getAddr32(i, j);
            // "c1" is the result of premultiplying the color of the unpremultiplied
            // bitmap at (i, j).
            const SkPMColor c1 = premultiply_unpmcolor(*bm8888Unpremul.getAddr32(i, j));
            // Compute the difference for each component.
            int da = SkAbs32(SkGetPackedA32(c0) - SkGetPackedA32(c1));
            int dr = SkAbs32(SkGetPackedR32(c0) - SkGetPackedR32(c1));
            int dg = SkAbs32(SkGetPackedG32(c0) - SkGetPackedG32(c1));
            int db = SkAbs32(SkGetPackedB32(c0) - SkGetPackedB32(c1));

            // Alpha component must be exactly the same.
            REPORTER_ASSERT(reporter, 0 == da);

            // Color components may not match exactly due to rounding error.
            REPORTER_ASSERT(reporter, dr <= 1);
            REPORTER_ASSERT(reporter, dg <= 1);
            REPORTER_ASSERT(reporter, db <= 1);
        }
    }
}
// max + 0.5 min has error [0.0, 0.12]
// max + 0.375 min has error [-.03, 0.07]
// 0.96043387 max + 0.397824735 min has error [-.06, +.05]
// For determining the maximum possible number of points to use in
// drawing a quadratic, we want to err on the high side.
static inline int cheap_distance(SkScalar dx, SkScalar dy) {
    int idx = SkAbs32(SkScalarRoundToInt(dx));
    int idy = SkAbs32(SkScalarRoundToInt(dy));
    if (idx > idy) {
        idx += idy >> 1;
    } else {
예제 #21
0
 inline static SkFixed Lookup(SkFDot6 x) {
     SkASSERT(SkAbs32(x) < kInverseTableSize);
     return table[x];
 }