void SkARGB32_Blitter::blitH(int x, int y, int width) {
    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width());

    if (fSrcA == 0) {
        return;
    }

    uint32_t* device = fDevice.getAddr32(x, y);

    if (fSrcA == 255) {
        sk_memset32(device, fPMColor, width);
    } else {
        uint32_t color = fPMColor;
        unsigned dst_scale = SkAlpha255To256(255 - fSrcA);
        uint32_t prevDst = ~device[0];  // so we always fail the test the first time
        uint32_t result SK_INIT_TO_AVOID_WARNING;

        for (int i = 0; i < width; i++) {
            uint32_t currDst = device[i];
            if (currDst != prevDst) {
                result = color + SkAlphaMulQ(currDst, dst_scale);
                prevDst = currDst;
            }
            device[i] = result;
        }
    }
}
示例#2
0
void SkARGB32_Black_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
                                       const int16_t runs[]) {
    uint32_t*   device = fDevice.getAddr32(x, y);
    SkPMColor   black = (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT);

    for (;;) {
        int count = runs[0];
        SkASSERT(count >= 0);
        if (count <= 0) {
            return;
        }
        unsigned aa = antialias[0];
        if (aa) {
            if (aa == 255) {
                sk_memset32(device, black, count);
            } else {
                SkPMColor src = aa << SK_A32_SHIFT;
                unsigned dst_scale = 256 - aa;
                int n = count;
                do {
                    --n;
                    device[n] = src + SkAlphaMulQ(device[n], dst_scale);
                } while (n > 0);
            }
        }
        runs += count;
        antialias += count;
        device += count;
    }
}
示例#3
0
void SkARGB32_Blitter::blitRect(int x, int y, int width, int height) {
    SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width() && y + height <= fDevice.height());

    if (fSrcA == 0) {
        return;
    }

    uint32_t*   device = fDevice.getAddr32(x, y);
    uint32_t    color = fPMColor;

    if (fSrcA == 255) {
        while (--height >= 0) {
            sk_memset32(device, color, width);
            device = (uint32_t*)((char*)device + fDevice.rowBytes());
        }
    } else {
        unsigned dst_scale = SkAlpha255To256(255 - fSrcA);

        while (--height >= 0) {
            uint32_t prevDst = ~device[0];
            uint32_t result SK_INIT_TO_AVOID_WARNING;

            for (int i = 0; i < width; i++) {
                uint32_t dst = device[i];
                if (dst != prevDst) {
                    result = color + SkAlphaMulQ(dst, dst_scale);
                    prevDst = dst;
                }
                device[i] = result;
            }
            device = (uint32_t*)((char*)device + fDevice.rowBytes());
        }
    }
}
void SkRasterPipelineBlitter::blitH(int x, int y, int w) {
    fDstPtr = fDst.writable_addr(0,y);
    fCurrentY = y;

    if (fCanMemsetInBlitH) {
        switch (fDst.shiftPerPixel()) {
            case 0:    memset  ((uint8_t *)fDstPtr + x, fMemsetColor, w); return;
            case 1: sk_memset16((uint16_t*)fDstPtr + x, fMemsetColor, w); return;
            case 2: sk_memset32((uint32_t*)fDstPtr + x, fMemsetColor, w); return;
            case 3: sk_memset64((uint64_t*)fDstPtr + x, fMemsetColor, w); return;
            default: break;
        }
    }

    auto& p = fBlitH;
    if (p.empty()) {
        p.extend(fShader);
        if (fBlend != SkBlendMode::kSrc) {
            this->append_load_d(&p);
            this->append_blend(&p);
            this->maybe_clamp(&p);
        }
        this->append_store(&p);
    }
    p.run(x,w);
}
void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
                                 const int16_t runs[]) {
    if (fSrcA == 0) {
        return;
    }

    uint32_t    color = fPMColor;
    uint32_t*   device = fDevice.getAddr32(x, y);
    unsigned    opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case

    for (;;) {
        int count = runs[0];
        SkASSERT(count >= 0);
        if (count <= 0) {
            return;
        }
        unsigned aa = antialias[0];
        if (aa) {
            if ((opaqueMask & aa) == 255) {
                sk_memset32(device, color, count);
            } else {
                uint32_t sc = SkAlphaMulQ(color, aa);
                unsigned dst_scale = 255 - SkGetPackedA32(sc);
                int n = count;
                do {
                    --n;
                    device[n] = sc + SkAlphaMulQ(device[n], dst_scale);
                } while (n > 0);
            }
        }
        runs += count;
        antialias += count;
        device += count;
    }
}
示例#6
0
void SkARGB32_Blitter::blitAntiH(int x, int y, const SkAlpha antialias[],
                                 const int16_t runs[]) {
    if (fSrcA == 0) {
        return;
    }

    uint32_t    color = fPMColor;
    uint32_t*   device = fDevice.getAddr32(x, y);
    unsigned    opaqueMask = fSrcA; // if fSrcA is 0xFF, then we will catch the fast opaque case

    for (;;) {
        int count = runs[0];
        SkASSERT(count >= 0);
        if (count <= 0) {
            return;
        }
        unsigned aa = antialias[0];
        if (aa) {
            if ((opaqueMask & aa) == 255) {
                sk_memset32(device, color, count);
            } else {
                uint32_t sc = SkAlphaMulQ(color, SkAlpha255To256(aa));
                fColor32Proc(device, device, count, sc);
            }
        }
        runs += count;
        antialias += count;
        device += count;
    }
}
示例#7
0
void SkBaseDevice::drawAtlas(const SkImage* atlas, const SkRSXform xform[],
                             const SkRect tex[], const SkColor colors[], int quadCount,
                             SkBlendMode mode, const SkPaint& paint) {
    const int triCount = quadCount << 1;
    const int vertexCount = triCount * 3;
    uint32_t flags = SkVertices::kHasTexCoords_BuilderFlag;
    if (colors) {
        flags |= SkVertices::kHasColors_BuilderFlag;
    }
    SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, vertexCount, 0, flags);

    SkPoint* vPos = builder.positions();
    SkPoint* vTex = builder.texCoords();
    SkColor* vCol = builder.colors();
    for (int i = 0; i < quadCount; ++i) {
        SkPoint tmp[4];
        xform[i].toQuad(tex[i].width(), tex[i].height(), tmp);
        vPos = quad_to_tris(vPos, tmp);

        tex[i].toQuad(tmp);
        vTex = quad_to_tris(vTex, tmp);

        if (colors) {
            sk_memset32(vCol, colors[i], 6);
            vCol += 6;
        }
    }
    SkPaint p(paint);
    p.setShader(atlas->makeShader());
    this->drawVertices(builder.detach().get(), mode, p);
}
示例#8
0
static void test_read_pixels(skiatest::Reporter* reporter, SkImage* image) {
    const SkPMColor expected = SkPreMultiplyColor(SK_ColorWHITE);
    const SkPMColor notExpected = ~expected;

    const int w = 2, h = 2;
    const size_t rowBytes = w * sizeof(SkPMColor);
    SkPMColor pixels[w*h];

    SkImageInfo info;

    info = SkImageInfo::MakeUnknown(w, h);
    REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, 0));

    // out-of-bounds should fail
    info = SkImageInfo::MakeN32Premul(w, h);
    REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, -w, 0));
    REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, -h));
    REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, image->width(), 0));
    REPORTER_ASSERT(reporter, !image->readPixels(info, pixels, rowBytes, 0, image->height()));

    // top-left should succeed
    sk_memset32(pixels, notExpected, w*h);
    REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, 0, 0));
    REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));

    // bottom-right should succeed
    sk_memset32(pixels, notExpected, w*h);
    REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
                                                image->width() - w, image->height() - h));
    REPORTER_ASSERT(reporter, has_pixels(pixels, w*h, expected));

    // partial top-left should succeed
    sk_memset32(pixels, notExpected, w*h);
    REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes, -1, -1));
    REPORTER_ASSERT(reporter, pixels[3] == expected);
    REPORTER_ASSERT(reporter, has_pixels(pixels, w*h - 1, notExpected));

    // partial bottom-right should succeed
    sk_memset32(pixels, notExpected, w*h);
    REPORTER_ASSERT(reporter, image->readPixels(info, pixels, rowBytes,
                                                image->width() - 1, image->height() - 1));
    REPORTER_ASSERT(reporter, pixels[0] == expected);
    REPORTER_ASSERT(reporter, has_pixels(&pixels[1], w*h - 1, notExpected));
}
    void drawBG(SkCanvas* canvas)
    {
        canvas->drawColor(0xFFDDDDDD);
        return;

#if 0
        SkColorTable    ct;
        SkPMColor       colors[] = { SK_ColorRED, SK_ColorBLUE };
        ct.setColors(colors, 2);
        ct.setFlags(ct.getFlags() | SkColorTable::kColorsAreOpaque_Flag);

        SkBitmap        bm;
        bm.setConfig(SkBitmap::kIndex8_Config, 20, 20, 21);
        bm.setColorTable(&ct);
        bm.allocPixels();
        sk_memset16((uint16_t*)bm.getAddr8(0, 0), 0x0001, bm.rowBytes() * bm.height() / 2);
#endif
#if 0
        SkBitmap        bm;
        bm.setConfig(SkBitmap::kRGB_565_Config, 20, 20, 42);
        bm.allocPixels();
        sk_memset32((uint32_t*)bm.getAddr16(0, 0), 0x0000FFFF, bm.rowBytes() * bm.height() / 4);
#endif
#if 1
        SkBitmap        bm;
        bm.setConfig(SkBitmap::kARGB_8888_Config, 20, 20);
        bm.allocPixels();
        sk_memset32((uint32_t*)bm.getAddr32(0, 0), 0xFFDDDDDD, bm.rowBytes() * bm.height() / 4);
#endif

        SkPaint paint;

//        SkShader* shader = SkShader::CreateBitmapShader(bm, false, SkPaint::kBilinear_FilterType, SkShader::kRepeat_TileMode);
        SkPoint pts[] = { 0, 0, SkIntToScalar(100), SkIntToScalar(0) };
        SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
        SkShader* shader = SkGradientShader::CreateLinear(pts, colors, NULL, 2, SkShader::kMirror_TileMode);
        paint.setShader(shader)->unref();

        canvas->drawPaint(paint);
    }
示例#10
0
template <DstType D> void src_1(const SkXfermode*, uint32_t dst[],
                                const SkPM4f* src, int count, const SkAlpha aa[]) {
    const Sk4f s4 = src->to4f_pmorder();

    if (aa) {
        if (D == kLinear_Dst) {
            // operate in bias-255 space for src and dst
            const Sk4f& s4_255 = s4 * Sk4f(255);
            while (count >= 4) {
                Sk4f aa4 = SkNx_cast<float>(Sk4b::Load(aa)) * Sk4f(1/255.f);
                Sk4f r0 = lerp(s4_255, to_4f(dst[0]), Sk4f(aa4[0])) + Sk4f(0.5f);
                Sk4f r1 = lerp(s4_255, to_4f(dst[1]), Sk4f(aa4[1])) + Sk4f(0.5f);
                Sk4f r2 = lerp(s4_255, to_4f(dst[2]), Sk4f(aa4[2])) + Sk4f(0.5f);
                Sk4f r3 = lerp(s4_255, to_4f(dst[3]), Sk4f(aa4[3])) + Sk4f(0.5f);
                Sk4f_ToBytes((uint8_t*)dst, r0, r1, r2, r3);

                dst += 4;
                aa += 4;
                count -= 4;
            }
        } else {    // kSRGB
            while (count >= 4) {
                Sk4f aa4 = SkNx_cast<float>(Sk4b::Load(aa)) * Sk4f(1/255.0f);

                /*  If we ever natively support convert 255_linear -> 255_srgb, then perhaps
                 *  it would be faster (and possibly allow more code sharing with kLinear) to
                 *  stay in that space.
                 */
                Sk4f r0 = lerp(s4, load_dst<D>(dst[0]), Sk4f(aa4[0]));
                Sk4f r1 = lerp(s4, load_dst<D>(dst[1]), Sk4f(aa4[1]));
                Sk4f r2 = lerp(s4, load_dst<D>(dst[2]), Sk4f(aa4[2]));
                Sk4f r3 = lerp(s4, load_dst<D>(dst[3]), Sk4f(aa4[3]));
                Sk4f_ToBytes((uint8_t*)dst,
                             linear_unit_to_srgb_255f(r0),
                             linear_unit_to_srgb_255f(r1),
                             linear_unit_to_srgb_255f(r2),
                             linear_unit_to_srgb_255f(r3));

                dst += 4;
                aa += 4;
                count -= 4;
            }
        }
        for (int i = 0; i < count; ++i) {
            unsigned a = aa[i];
            Sk4f d4 = load_dst<D>(dst[i]);
            dst[i] = store_dst<D>(lerp(s4, d4, a));
        }
    } else {
        sk_memset32(dst, store_dst<D>(s4), count);
    }
}
示例#11
0
文件: SkSampler.cpp 项目: google/skia
void SkSampler::Fill(const SkImageInfo& info, void* dst, size_t rowBytes,
                     SkCodec::ZeroInitialized zeroInit) {
    SkASSERT(dst != nullptr);

    if (SkCodec::kYes_ZeroInitialized == zeroInit) {
        return;
    }

    const int width = info.width();
    const int numRows = info.height();

    // Use the proper memset routine to fill the remaining bytes
    switch (info.colorType()) {
        case kRGBA_8888_SkColorType:
        case kBGRA_8888_SkColorType: {
            uint32_t* dstRow = (uint32_t*) dst;
            for (int row = 0; row < numRows; row++) {
                sk_memset32(dstRow, 0, width);
                dstRow = SkTAddOffset<uint32_t>(dstRow, rowBytes);
            }
            break;
        }
        case kRGB_565_SkColorType: {
            uint16_t* dstRow = (uint16_t*) dst;
            for (int row = 0; row < numRows; row++) {
                sk_memset16(dstRow, 0, width);
                dstRow = SkTAddOffset<uint16_t>(dstRow, rowBytes);
            }
            break;
        }
        case kGray_8_SkColorType: {
            uint8_t* dstRow = (uint8_t*) dst;
            for (int row = 0; row < numRows; row++) {
                memset(dstRow, 0, width);
                dstRow = SkTAddOffset<uint8_t>(dstRow, rowBytes);
            }
            break;
        }
        case kRGBA_F16_SkColorType: {
            uint64_t* dstRow = (uint64_t*) dst;
            for (int row = 0; row < numRows; row++) {
                sk_memset64(dstRow, 0, width);
                dstRow = SkTAddOffset<uint64_t>(dstRow, rowBytes);
            }
            break;
        }
        default:
            SkCodecPrintf("Error: Unsupported dst color type for fill().  Doing nothing.\n");
            SkASSERT(false);
            break;
    }
}
示例#12
0
static void clear_srgb(const SkXfermode*, uint32_t dst[], const SkPM4f[],
                       int count, const SkAlpha aa[]) {
    if (aa) {
        for (int i = 0; i < count; ++i) {
            if (aa[i]) {
                Sk4f d = Sk4f_fromS32(dst[i]) * Sk4f((255 - aa[i]) * (1/255.0f));
                dst[i] = Sk4f_toS32(d);
            }
        }
    } else {
        sk_memset32(dst, 0, count);
    }
}
示例#13
0
static void test_32(skiatest::Reporter* reporter) {
    uint32_t buffer[TOTAL];
    
    for (int count = 0; count < MAX_COUNT; ++count) {
        for (int alignment = 0; alignment < MAX_ALIGNMENT; ++alignment) {
            set_zero(buffer, sizeof(buffer));
            
            uint32_t* base = &buffer[PAD + alignment];
            sk_memset32(base, VALUE32, count);
            
            compare32(buffer,       0,       PAD + alignment);
            compare32(base,         VALUE32, count);
            compare32(base + count, 0,       TOTAL - count - PAD - alignment);
        }
    }
}
示例#14
0
static void clear_linear(const SkXfermode*, uint32_t dst[], const SkPM4f[],
                           int count, const SkAlpha aa[]) {
    if (aa) {
        for (int i = 0; i < count; ++i) {
            unsigned a = aa[i];
            if (a) {
                SkPMColor dstC = dst[i];
                SkPMColor C = 0;
                if (0xFF != a) {
                    C = SkFourByteInterp(C, dstC, a);
                }
                dst[i] = C;
            }
        }
    } else {
        sk_memset32(dst, 0, count);
    }
}
 bool onGetPixels(const SkImageInfo& info, void* pixels, size_t rowBytes,
                  SkPMColor ctable[], int* ctableCount) override {
     REPORTER_ASSERT(fReporter, pixels != NULL);
     REPORTER_ASSERT(fReporter, rowBytes >= info.minRowBytes());
     if (fType != kSucceedGetPixels_TestType) {
         return false;
     }
     if (info.colorType() != kN32_SkColorType) {
         return false;
     }
     char* bytePtr = static_cast<char*>(pixels);
     for (int y = 0; y < info.height(); ++y) {
         sk_memset32(reinterpret_cast<SkColor*>(bytePtr),
                     TestImageGenerator::Color(), info.width());
         bytePtr += rowBytes;
     }
     return true;
 }
示例#16
0
void xfer_pm4_proc_1(const SkXfermode::PM4fState& state, uint32_t dst[], const SkPM4f& src,
                     int count, const SkAlpha aa[]) {
    uint32_t pm;
    pm4f_to_linear_32(&pm, &src, 1);

    const int N = 128;
    SkPMColor tmp[N];
    sk_memset32(tmp, pm, SkMin32(count, N));
    while (count > 0) {
        const int n = SkMin32(count, N);
        state.fXfer->xfer32(dst, tmp, n, aa);

        dst += n;
        if (aa) {
            aa += n;
        }
        count -= n;
    }
}
static void fillRect(SkBitmap* bm, GifWord left, GifWord top, GifWord width, GifWord height,
                     uint32_t col)
{
    int bmWidth = bm->width();
    int bmHeight = bm->height();
    uint32_t* dst = bm->getAddr32(left, top);
    GifWord copyWidth = width;
    if (left + copyWidth > bmWidth) {
        copyWidth = bmWidth - left;
    }

    GifWord copyHeight = height;
    if (top + copyHeight > bmHeight) {
        copyHeight = bmHeight - top;
    }

    for (; copyHeight > 0; copyHeight--) {
        sk_memset32(dst, col, copyWidth);
        dst += bmWidth;
    }
}
示例#18
0
template <DstType D> void src_1(const SkXfermode::PM4fState& state, uint32_t dst[],
                                const SkPM4f& src, int count, const SkAlpha aa[]) {
    const Sk4f r4 = Sk4f::Load(src.fVec);   // src always overrides dst
    const uint32_t r32 = store_dst<D>(r4);

    if (aa) {
        for (int i = 0; i < count; ++i) {
            unsigned a = aa[i];
            if (0 == a) {
                continue;
            }
            if (a != 0xFF) {
                Sk4f d4 = load_dst<D>(dst[i]);
                dst[i] = store_dst<D>(lerp(r4, d4, a));
            } else {
                dst[i] = r32;
            }
        }
    } else {
        sk_memset32(dst, r32, count);
    }
}
示例#19
0
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ApplyGamma, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    static const int kW = 256;
    static const int kH = 256;
    static const size_t kRowBytes = sizeof(uint32_t) * kW;

    GrSurfaceDesc baseDesc;
    baseDesc.fConfig = kRGBA_8888_GrPixelConfig;
    baseDesc.fWidth = kW;
    baseDesc.fHeight = kH;

    const SkImageInfo ii = SkImageInfo::MakeN32Premul(kW, kH);

    SkAutoTMalloc<uint32_t> srcPixels(kW * kH);
    for (int y = 0; y < kH; ++y) {
        for (int x = 0; x < kW; ++x) {
            srcPixels.get()[y*kW+x] = SkPreMultiplyARGB(x, y, x, 0xFF);
        }
    }

    SkBitmap bm;
    bm.installPixels(ii, srcPixels.get(), kRowBytes);

    SkAutoTMalloc<uint32_t> read(kW * kH);

    // We allow more error on GPUs with lower precision shader variables.
    float error = context->caps()->shaderCaps()->floatPrecisionVaries() ? 1.2f : 0.5f;

    for (auto toSRGB : { false, true }) {
        sk_sp<SkSurface> dst(SkSurface::MakeRenderTarget(context, SkBudgeted::kNo, ii));

        if (!dst) {
            ERRORF(reporter, "Could not create surfaces for copy surface test.");
            continue;
        }

        SkCanvas* dstCanvas = dst->getCanvas();

        dstCanvas->clear(SK_ColorRED);
        dstCanvas->flush();

        SkPaint gammaPaint;
        gammaPaint.setBlendMode(SkBlendMode::kSrc);
        gammaPaint.setColorFilter(toSRGB ? SkColorFilter::MakeLinearToSRGBGamma()
                                         : SkColorFilter::MakeSRGBToLinearGamma());

        dstCanvas->drawBitmap(bm, 0, 0, &gammaPaint);
        dstCanvas->flush();

        sk_memset32(read.get(), 0, kW * kH);
        if (!dstCanvas->readPixels(ii, read.get(), kRowBytes, 0, 0)) {
            ERRORF(reporter, "Error calling readPixels");
            continue;
        }

        bool abort = false;
        // Validate that pixels were copied/transformed correctly.
        for (int y = 0; y < kH && !abort; ++y) {
            for (int x = 0; x < kW && !abort; ++x) {
                uint32_t r = read.get()[y * kW + x];
                uint32_t s = srcPixels.get()[y * kW + x];
                uint32_t expected;
                if (!check_gamma(s, r, toSRGB, error, &expected)) {
                    ERRORF(reporter, "Expected dst %d,%d to contain 0x%08x "
                           "from src 0x%08x and mode %s. Got %08x", x, y, expected, s,
                           toSRGB ? "ToSRGB" : "ToLinear", r);
                    abort = true;
                    break;
                }
            }
        }
    }
}
示例#20
0
 void filterSpan(const SkPMColor shader[], int count, SkPMColor result[]) const override {
     sk_memset32(result, this->getPMColor(), count);
 }
示例#21
0
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    static const int kW = 10;
    static const int kH = 10;
    static const size_t kRowBytes = sizeof(uint32_t) * kW;

    SkAutoTMalloc<uint32_t> srcPixels(kW * kH);
    for (int i = 0; i < kW * kH; ++i) {
        srcPixels.get()[i] = i;
    }

    SkAutoTMalloc<uint32_t> dstPixels(kW * kH);
    for (int i = 0; i < kW * kH; ++i) {
        dstPixels.get()[i] = ~i;
    }

    static const SkIRect kSrcRects[] {
        { 0,  0, kW  , kH  },
        {-1, -1, kW+1, kH+1},
        { 1,  1, kW-1, kH-1},
        { 5,  5, 6   , 6   },
    };

    static const SkIPoint kDstPoints[] {
        { 0   ,  0   },
        { 1   ,  1   },
        { kW/2,  kH/4},
        { kW-1,  kH-1},
        { kW  ,  kH  },
        { kW+1,  kH+2},
        {-1   , -1   },
    };

    static const SkImageInfo kImageInfos[] {
        SkImageInfo::Make(kW, kH, kRGBA_8888_SkColorType, kPremul_SkAlphaType),
        SkImageInfo::Make(kW, kH, kBGRA_8888_SkColorType, kPremul_SkAlphaType)
    };

    SkAutoTMalloc<uint32_t> read(kW * kH);

    for (auto sOrigin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) {
        for (auto dOrigin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) {
            for (auto sRenderable : {GrRenderable::kYes, GrRenderable::kNo}) {
                for (auto dRenderable : {GrRenderable::kYes, GrRenderable::kNo}) {
                    for (auto srcRect : kSrcRects) {
                        for (auto dstPoint : kDstPoints) {
                            for (auto ii: kImageInfos) {
                                auto src = sk_gpu_test::MakeTextureProxyFromData(
                                        context, sRenderable, kW, kH, ii.colorType(), sOrigin,
                                        srcPixels.get(), kRowBytes);
                                auto dst = sk_gpu_test::MakeTextureProxyFromData(
                                        context, dRenderable, kW, kH, ii.colorType(), dOrigin,
                                        dstPixels.get(), kRowBytes);

                                // Should always work if the color type is RGBA, but may not work
                                // for BGRA
                                if (ii.colorType() == kRGBA_8888_SkColorType) {
                                    if (!src || !dst) {
                                        ERRORF(reporter,
                                               "Could not create surfaces for copy surface test.");
                                        continue;
                                    }
                                } else {
                                    GrPixelConfig config =
                                            SkColorType2GrPixelConfig(kBGRA_8888_SkColorType);
                                    if (!context->priv().caps()->isConfigTexturable(config)) {
                                        continue;
                                    }
                                    if (!src || !dst) {
                                        ERRORF(reporter,
                                               "Could not create surfaces for copy surface test.");
                                        continue;
                                    }
                                }

                                sk_sp<GrSurfaceContext> dstContext =
                                        context->priv().makeWrappedSurfaceContext(std::move(dst));

                                bool result = dstContext->copy(src.get(), srcRect, dstPoint);

                                bool expectedResult = true;
                                SkIPoint dstOffset = { dstPoint.fX - srcRect.fLeft,
                                                       dstPoint.fY - srcRect.fTop };
                                SkIRect copiedDstRect = SkIRect::MakeXYWH(dstPoint.fX,
                                                                          dstPoint.fY,
                                                                          srcRect.width(),
                                                                          srcRect.height());

                                SkIRect copiedSrcRect;
                                if (!copiedSrcRect.intersect(srcRect, SkIRect::MakeWH(kW, kH))) {
                                    expectedResult = false;
                                } else {
                                    // If the src rect was clipped, apply same clipping to each side
                                    // of copied dst rect.
                                    copiedDstRect.fLeft += copiedSrcRect.fLeft - srcRect.fLeft;
                                    copiedDstRect.fTop += copiedSrcRect.fTop - srcRect.fTop;
                                    copiedDstRect.fRight -= copiedSrcRect.fRight - srcRect.fRight;
                                    copiedDstRect.fBottom -= copiedSrcRect.fBottom -
                                                             srcRect.fBottom;
                                }
                                if (copiedDstRect.isEmpty() ||
                                    !copiedDstRect.intersect(SkIRect::MakeWH(kW, kH))) {
                                    expectedResult = false;
                                }
                                // To make the copied src rect correct we would apply any dst
                                // clipping back to the src rect, but we don't use it again so
                                // don't bother.
                                if (expectedResult != result) {
                                    ERRORF(reporter, "Expected return value %d from copySurface, "
                                           "got %d.", expectedResult, result);
                                    continue;
                                }

                                if (!expectedResult || !result) {
                                    continue;
                                }

                                sk_memset32(read.get(), 0, kW * kH);
                                if (!dstContext->readPixels(ii, read.get(), kRowBytes, 0, 0)) {
                                    ERRORF(reporter, "Error calling readPixels");
                                    continue;
                                }

                                bool abort = false;
                                // Validate that pixels inside copiedDstRect received the correct
                                // value from src and that those outside were not modified.
                                for (int y = 0; y < kH && !abort; ++y) {
                                    for (int x = 0; x < kW; ++x) {
                                        uint32_t r = read.get()[y * kW + x];
                                        if (copiedDstRect.contains(x, y)) {
                                            int sx = x - dstOffset.fX;
                                            int sy = y - dstOffset.fY;
                                            uint32_t s = srcPixels.get()[sy * kW + sx];
                                            if (s != r) {
                                                ERRORF(reporter, "Expected dst %d,%d to contain "
                                                       "0x%08x copied from src location %d,%d. Got "
                                                       "0x%08x", x, y, s, sx, sy, r);
                                                abort = true;
                                                break;
                                            }
                                        } else {
                                            uint32_t d = dstPixels.get()[y * kW + x];
                                            if (d != r) {
                                                ERRORF(reporter, "Expected dst %d,%d to be "
                                                       "unmodified (0x%08x). Got 0x%08x",
                                                       x, y, d, r);
                                                abort = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
示例#22
0
Error HWUISink::draw(const Src& src, SkBitmap* dst, SkWStream*, SkString*) const {
    // Do all setup in this function because we don't know the size
    // for the RenderNode and RenderProxy during the constructor.
    // In practice this doesn't seem too expensive.
    const SkISize size = src.size();

    // Based on android::SurfaceTexture_init()
    android::sp<android::IGraphicBufferProducer> producer;
    android::sp<android::IGraphicBufferConsumer> consumer;
    android::BufferQueue::createBufferQueue(&producer, &consumer);

    // Consumer setup

    android::sp<android::CpuConsumer> cpuConsumer =
        new android::CpuConsumer(consumer, 1);
    cpuConsumer->setName(android::String8("SkiaTestClient"));
    cpuConsumer->setDefaultBufferSize(size.width(), size.height());

    // Producer setup

    android::sp<android::Surface> surface = new android::Surface(producer);
    native_window_set_buffers_dimensions(surface.get(), size.width(), size.height());
    native_window_set_buffers_format(surface.get(), android::PIXEL_FORMAT_RGBA_8888);
    native_window_set_usage(surface.get(), GRALLOC_USAGE_SW_READ_OFTEN |
                                           GRALLOC_USAGE_SW_WRITE_NEVER |
                                           GRALLOC_USAGE_HW_RENDER);

    // RenderNode setup based on hwui/tests/main.cpp:TreeContentAnimation
    SkAutoTDelete<android::uirenderer::RenderNode> rootNode
        (new android::uirenderer::RenderNode());
    rootNode->incStrong(nullptr);

    // Values set here won't be applied until the framework has called
    // RenderNode::pushStagingPropertiesChanges() during RenderProxy::syncAndDrawFrame().
    rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, size.width(), size.height());
    rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::X |
                                     android::uirenderer::RenderNode::Y);
    rootNode->mutateStagingProperties().setClipToBounds(false);
    rootNode->setPropertyFieldsDirty(android::uirenderer::RenderNode::GENERIC);

    // RenderProxy setup based on hwui/tests/main.cpp:TreeContentAnimation
    ContextFactory factory;
    SkAutoTDelete<android::uirenderer::renderthread::RenderProxy> proxy
        (new android::uirenderer::renderthread::RenderProxy(false, rootNode, &factory));
    proxy->loadSystemProperties();

    proxy->initialize(surface.get());

    float lightX = size.width() / 2.0f;
    android::uirenderer::Vector3 lightVector { lightX, dp(-200.0f), dp(800.0f) };
    proxy->setup(size.width(), size.height(), lightVector, dp(800.0f), 255 * 0.075f, 255 * 0.15f,
                 kDensity);

    // Do the draw

    SkAutoTDelete<android::uirenderer::DisplayListRenderer> renderer
        (new android::uirenderer::DisplayListRenderer());
    renderer->setViewport(size.width(), size.height());
    renderer->prepare();
    renderer->clipRect(0, 0, size.width(), size.height(), SkRegion::Op::kReplace_Op);

    Error err = src.draw(renderer->asSkCanvas());
    if (!err.isEmpty()) {
        return err;
    }

    renderer->finish();
    rootNode->setStagingDisplayList(renderer->finishRecording());

    proxy->syncAndDrawFrame();
    proxy->fence();

    // Capture pixels

    SkImageInfo destinationConfig =
        SkImageInfo::Make(size.width(), size.height(),
                          kRGBA_8888_SkColorType, kPremul_SkAlphaType);
    dst->allocPixels(destinationConfig);
    sk_memset32((uint32_t*) dst->getPixels(), SK_ColorRED, size.width() * size.height());

    android::CpuConsumer::LockedBuffer nativeBuffer;
    android::status_t retval = cpuConsumer->lockNextBuffer(&nativeBuffer);
    if (retval == android::BAD_VALUE) {
        SkDebugf("HWUISink::draw() got no buffer; returning transparent");
        // No buffer ready to read - commonly triggered by dm sending us
        // a no-op source, or calling code that doesn't do anything on this
        // backend.
        dst->eraseColor(SK_ColorTRANSPARENT);
        return "";
    } else if (retval) {
        return SkStringPrintf("Failed to lock buffer to read pixels: %d.", retval);
    }

    // Move the pixels into the destination SkBitmap

    SK_ALWAYSBREAK(nativeBuffer.format == android::PIXEL_FORMAT_RGBA_8888 &&
                   "Native buffer not RGBA!");
    SkImageInfo nativeConfig =
        SkImageInfo::Make(nativeBuffer.width, nativeBuffer.height,
                          kRGBA_8888_SkColorType, kPremul_SkAlphaType);

    // Android stride is in pixels, Skia stride is in bytes
    SkBitmap nativeWrapper;
    bool success =
        nativeWrapper.installPixels(nativeConfig, nativeBuffer.data, nativeBuffer.stride * 4);
    if (!success) {
        return "Failed to wrap HWUI buffer in a SkBitmap";
    }

    SK_ALWAYSBREAK(dst->colorType() == kRGBA_8888_SkColorType &&
                   "Destination buffer not RGBA!");
    success =
        nativeWrapper.readPixels(destinationConfig, dst->getPixels(), dst->rowBytes(), 0, 0);
    if (!success) {
        return "Failed to extract pixels from HWUI buffer";
    }

    cpuConsumer->unlockBuffer(nativeBuffer);
    return "";
}
 virtual void filterSpan(const SkPMColor shader[], int count,
                         SkPMColor result[]) {
     sk_memset32(result, fPMColor, count);
 }
void SkSampler::Fill(const SkImageInfo& info, void* dst, size_t rowBytes,
        uint64_t colorOrIndex, SkCodec::ZeroInitialized zeroInit) {
    SkASSERT(dst != nullptr);

    // Calculate bytes to fill.
    const size_t bytesToFill = info.computeByteSize(rowBytes);
    const int width = info.width();
    const int numRows = info.height();

    // Use the proper memset routine to fill the remaining bytes
    switch (info.colorType()) {
        case kRGBA_8888_SkColorType:
        case kBGRA_8888_SkColorType: {
            // If memory is zero initialized, we may not need to fill
            uint32_t color = (uint32_t) colorOrIndex;
            if (SkCodec::kYes_ZeroInitialized == zeroInit && 0 == color) {
                return;
            }

            uint32_t* dstRow = (uint32_t*) dst;
            for (int row = 0; row < numRows; row++) {
                sk_memset32((uint32_t*) dstRow, color, width);
                dstRow = SkTAddOffset<uint32_t>(dstRow, rowBytes);
            }
            break;
        }
        case kRGB_565_SkColorType: {
            // If the destination is k565, the caller passes in a 16-bit color.
            // We will not assert that the high bits of colorOrIndex must be zeroed.
            // This allows us to take advantage of the fact that the low 16 bits of an
            // SKPMColor may be a valid a 565 color.  For example, the low 16
            // bits of SK_ColorBLACK are identical to the 565 representation
            // for black.

            // If memory is zero initialized, we may not need to fill
            uint16_t color = (uint16_t) colorOrIndex;
            if (SkCodec::kYes_ZeroInitialized == zeroInit && 0 == color) {
                return;
            }

            uint16_t* dstRow = (uint16_t*) dst;
            for (int row = 0; row < numRows; row++) {
                sk_memset16((uint16_t*) dstRow, color, width);
                dstRow = SkTAddOffset<uint16_t>(dstRow, rowBytes);
            }
            break;
        }
        case kGray_8_SkColorType:
            // If the destination is kGray, the caller passes in an 8-bit color.
            // We will not assert that the high bits of colorOrIndex must be zeroed.
            // This allows us to take advantage of the fact that the low 8 bits of an
            // SKPMColor may be a valid a grayscale color.  For example, the low 8
            // bits of SK_ColorBLACK are identical to the grayscale representation
            // for black.

            // If memory is zero initialized, we may not need to fill
            if (SkCodec::kYes_ZeroInitialized == zeroInit && 0 == (uint8_t) colorOrIndex) {
                return;
            }

            memset(dst, (uint8_t) colorOrIndex, bytesToFill);
            break;
        case kRGBA_F16_SkColorType: {
            uint64_t color = colorOrIndex;
            if (SkCodec::kYes_ZeroInitialized == zeroInit && 0 == color) {
                return;
            }

            uint64_t* dstRow = (uint64_t*) dst;
            for (int row = 0; row < numRows; row++) {
                sk_memset64((uint64_t*) dstRow, color, width);
                dstRow = SkTAddOffset<uint64_t>(dstRow, rowBytes);
            }
            break;
        }
        default:
            SkCodecPrintf("Error: Unsupported dst color type for fill().  Doing nothing.\n");
            SkASSERT(false);
            break;
    }
}
示例#25
0
void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
    sk_memset32(span, fPMColor, count);
}
示例#26
0
bool SkPixmap::erase(SkColor color, const SkIRect& inArea) const {
    if (nullptr == fPixels) {
        return false;
    }
    SkIRect area;
    if (!area.intersect(this->bounds(), inArea)) {
        return false;
    }

    U8CPU a = SkColorGetA(color);
    U8CPU r = SkColorGetR(color);
    U8CPU g = SkColorGetG(color);
    U8CPU b = SkColorGetB(color);

    int height = area.height();
    const int width = area.width();
    const int rowBytes = this->rowBytes();
    
    switch (this->colorType()) {
        case kGray_8_SkColorType: {
            if (255 != a) {
                r = SkMulDiv255Round(r, a);
                g = SkMulDiv255Round(g, a);
                b = SkMulDiv255Round(b, a);
            }
            int gray = SkComputeLuminance(r, g, b);
            uint8_t* p = this->writable_addr8(area.fLeft, area.fTop);
            while (--height >= 0) {
                memset(p, gray, width);
                p += rowBytes;
            }
            break;
        }
        case kAlpha_8_SkColorType: {
            uint8_t* p = this->writable_addr8(area.fLeft, area.fTop);
            while (--height >= 0) {
                memset(p, a, width);
                p += rowBytes;
            }
            break;
        }
        case kARGB_4444_SkColorType:
        case kRGB_565_SkColorType: {
            uint16_t* p = this->writable_addr16(area.fLeft, area.fTop);
            uint16_t v;
            
            // make rgb premultiplied
            if (255 != a) {
                r = SkMulDiv255Round(r, a);
                g = SkMulDiv255Round(g, a);
                b = SkMulDiv255Round(b, a);
            }
            
            if (kARGB_4444_SkColorType == this->colorType()) {
                v = pack_8888_to_4444(a, r, g, b);
            } else {
                v = SkPackRGB16(r >> (8 - SK_R16_BITS),
                                g >> (8 - SK_G16_BITS),
                                b >> (8 - SK_B16_BITS));
            }
            while (--height >= 0) {
                sk_memset16(p, v, width);
                p = (uint16_t*)((char*)p + rowBytes);
            }
            break;
        }
        case kBGRA_8888_SkColorType:
        case kRGBA_8888_SkColorType: {
            uint32_t* p = this->writable_addr32(area.fLeft, area.fTop);
            
            if (255 != a && kPremul_SkAlphaType == this->alphaType()) {
                r = SkMulDiv255Round(r, a);
                g = SkMulDiv255Round(g, a);
                b = SkMulDiv255Round(b, a);
            }
            uint32_t v = kRGBA_8888_SkColorType == this->colorType()
                             ? SkPackARGB_as_RGBA(a, r, g, b)
                             : SkPackARGB_as_BGRA(a, r, g, b);

            while (--height >= 0) {
                sk_memset32(p, v, width);
                p = (uint32_t*)((char*)p + rowBytes);
            }
            break;
        }
        default:
            return false; // no change, so don't call notifyPixelsChanged()
    }
    return true;
}
示例#27
0
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(CopySurface, reporter, ctxInfo) {
    GrContext* context = ctxInfo.grContext();
    static const int kW = 10;
    static const int kH = 10;
    static const size_t kRowBytes = sizeof(uint32_t) * kW;

    GrSurfaceDesc baseDesc;
    baseDesc.fConfig = kRGBA_8888_GrPixelConfig;
    baseDesc.fWidth = kW;
    baseDesc.fHeight = kH;

    SkAutoTMalloc<uint32_t> srcPixels(kW * kH);
    for (int i = 0; i < kW * kH; ++i) {
        srcPixels.get()[i] = i;
    }

    SkAutoTMalloc<uint32_t> dstPixels(kW * kH);
    for (int i = 0; i < kW * kH; ++i) {
        dstPixels.get()[i] = ~i;
    }

    static const SkIRect kSrcRects[] {
        { 0,  0, kW  , kH  },
        {-1, -1, kW+1, kH+1},
        { 1,  1, kW-1, kH-1},
        { 5,  5, 6   , 6   },
    };

    static const SkIPoint kDstPoints[] {
        { 0   ,  0   },
        { 1   ,  1   },
        { kW/2,  kH/4},
        { kW-1,  kH-1},
        { kW  ,  kH  },
        { kW+1,  kH+2},
        {-1   , -1   },
    };

    SkAutoTMalloc<uint32_t> read(kW * kH);

    for (auto sOrigin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) {
        for (auto dOrigin : {kBottomLeft_GrSurfaceOrigin, kTopLeft_GrSurfaceOrigin}) {
            for (auto sFlags: {kRenderTarget_GrSurfaceFlag, kNone_GrSurfaceFlags}) {
                for (auto dFlags: {kRenderTarget_GrSurfaceFlag, kNone_GrSurfaceFlags}) {
                    for (auto srcRect : kSrcRects) {
                        for (auto dstPoint : kDstPoints) {
                            GrSurfaceDesc srcDesc = baseDesc;
                            srcDesc.fOrigin = sOrigin;
                            srcDesc.fFlags = sFlags;
                            GrSurfaceDesc dstDesc = baseDesc;
                            dstDesc.fOrigin = dOrigin;
                            dstDesc.fFlags = dFlags;

                            SkAutoTUnref<GrTexture> src(
                                context->textureProvider()->createTexture(srcDesc, SkBudgeted::kNo,
                                                                          srcPixels.get(),
                                                                          kRowBytes));
                            SkAutoTUnref<GrTexture> dst(
                                context->textureProvider()->createTexture(dstDesc, SkBudgeted::kNo,
                                                                          dstPixels.get(),
                                                                          kRowBytes));
                            if (!src || !dst) {
                                ERRORF(reporter,
                                       "Could not create surfaces for copy surface test.");
                                continue;
                            }

                            bool result = context->copySurface(dst, src, srcRect, dstPoint);

                            bool expectedResult = true;
                            SkIPoint dstOffset = { dstPoint.fX - srcRect.fLeft,
                                                   dstPoint.fY - srcRect.fTop };
                            SkIRect copiedDstRect = SkIRect::MakeXYWH(dstPoint.fX,
                                                                      dstPoint.fY,
                                                                      srcRect.width(),
                                                                      srcRect.height());

                            SkIRect copiedSrcRect;
                            if (!copiedSrcRect.intersect(srcRect, SkIRect::MakeWH(kW, kH))) {
                                expectedResult = false;
                            } else {
                                // If the src rect was clipped, apply same clipping to each side of
                                // copied dst rect.
                                copiedDstRect.fLeft += copiedSrcRect.fLeft - srcRect.fLeft;
                                copiedDstRect.fTop += copiedSrcRect.fTop - srcRect.fTop;
                                copiedDstRect.fRight -= copiedSrcRect.fRight - srcRect.fRight;
                                copiedDstRect.fBottom -= copiedSrcRect.fBottom - srcRect.fBottom;
                            }
                            if (copiedDstRect.isEmpty() ||
                                !copiedDstRect.intersect(SkIRect::MakeWH(kW, kH))) {
                                expectedResult = false;
                            }
                            // To make the copied src rect correct we would apply any dst clipping
                            // back to the src rect, but we don't use it again so don't bother.
                            if (expectedResult != result) {
                                ERRORF(reporter, "Expected return value %d from copySurface, got "
                                       "%d.", expectedResult, result);
                                continue;
                            }

                            if (!expectedResult || !result) {
                                continue;
                            }

                            sk_memset32(read.get(), 0, kW * kH);
                            if (!dst->readPixels(0, 0, kW, kH, baseDesc.fConfig, read.get(),
                                                 kRowBytes)) {
                                ERRORF(reporter, "Error calling readPixels");
                                continue;
                            }

                            bool abort = false;
                            // Validate that pixels inside copiedDstRect received the correct value
                            // from src and that those outside were not modified.
                            for (int y = 0; y < kH && !abort; ++y) {
                                for (int x = 0; x < kW; ++x) {
                                    uint32_t r = read.get()[y * kW + x];
                                    if (copiedDstRect.contains(x, y)) {
                                        int sx = x - dstOffset.fX;
                                        int sy = y - dstOffset.fY;
                                        uint32_t s = srcPixels.get()[sy * kW + sx];
                                        if (s != r) {
                                            ERRORF(reporter, "Expected dst %d,%d to contain "
                                                   "0x%08x copied from src location %d,%d. Got "
                                                   "0x%08x", x, y, s, sx, sy, r);
                                            abort = true;
                                            break;
                                        }
                                    } else {
                                        uint32_t d = dstPixels.get()[y * kW + x];
                                        if (d != r) {
                                            ERRORF(reporter, "Expected dst %d,%d to be unmodified ("
                                                   "0x%08x). Got 0x%08x", x, y, d, r);
                                            abort = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
示例#28
0
// Note: SkColorTable claims to store SkPMColors, which is not necessarily
// the case here.
bool SkPngCodec::createColorTable(SkColorType dstColorType, bool premultiply, int* ctableCount) {

    int numColors;
    png_color* palette;
    if (!png_get_PLTE(fPng_ptr, fInfo_ptr, &palette, &numColors)) {
        return false;
    }

    // Note: These are not necessarily SkPMColors.
    SkPMColor colorPtr[256];

    png_bytep alphas;
    int numColorsWithAlpha = 0;
    if (png_get_tRNS(fPng_ptr, fInfo_ptr, &alphas, &numColorsWithAlpha, nullptr)) {
        // Choose which function to use to create the color table. If the final destination's
        // colortype is unpremultiplied, the color table will store unpremultiplied colors.
        PackColorProc proc = choose_pack_color_proc(premultiply, dstColorType);

        for (int i = 0; i < numColorsWithAlpha; i++) {
            // We don't have a function in SkOpts that combines a set of alphas with a set
            // of RGBs.  We could write one, but it's hardly worth it, given that this
            // is such a small fraction of the total decode time.
            colorPtr[i] = proc(alphas[i], palette->red, palette->green, palette->blue);
            palette++;
        }
    }

    if (numColorsWithAlpha < numColors) {
        // The optimized code depends on a 3-byte png_color struct with the colors
        // in RGB order.  These checks make sure it is safe to use.
        static_assert(3 == sizeof(png_color), "png_color struct has changed.  Opts are broken.");
#ifdef SK_DEBUG
        SkASSERT(&palette->red < &palette->green);
        SkASSERT(&palette->green < &palette->blue);
#endif

        if (is_rgba(dstColorType)) {
            SkOpts::RGB_to_RGB1(colorPtr + numColorsWithAlpha, palette,
                    numColors - numColorsWithAlpha);
        } else {
            SkOpts::RGB_to_BGR1(colorPtr + numColorsWithAlpha, palette,
                    numColors - numColorsWithAlpha);
        }
    }

    // Pad the color table with the last color in the table (or black) in the case that
    // invalid pixel indices exceed the number of colors in the table.
    const int maxColors = 1 << fBitDepth;
    if (numColors < maxColors) {
        SkPMColor lastColor = numColors > 0 ? colorPtr[numColors - 1] : SK_ColorBLACK;
        sk_memset32(colorPtr + numColors, lastColor, maxColors - numColors);
    }

    // Set the new color count.
    if (ctableCount != nullptr) {
        *ctableCount = maxColors;
    }

    fColorTable.reset(new SkColorTable(colorPtr, maxColors));
    return true;
}
示例#29
0
void SkGifCodec::initializeColorTable(const SkImageInfo& dstInfo, SkPMColor* inputColorPtr,
        int* inputColorCount) {
    // Set up our own color table
    const uint32_t maxColors = 256;
    SkPMColor colorPtr[256];
    if (NULL != inputColorCount) {
        // We set the number of colors to maxColors in order to ensure
        // safe memory accesses.  Otherwise, an invalid pixel could
        // access memory outside of our color table array.
        *inputColorCount = maxColors;
    }

    // Get local color table
    ColorMapObject* colorMap = fGif->Image.ColorMap;
    // If there is no local color table, use the global color table
    if (NULL == colorMap) {
        colorMap = fGif->SColorMap;
    }

    uint32_t colorCount = 0;
    if (NULL != colorMap) {
        colorCount = colorMap->ColorCount;
        // giflib guarantees these properties
        SkASSERT(colorCount == (unsigned) (1 << (colorMap->BitsPerPixel)));
        SkASSERT(colorCount <= 256);
        PackColorProc proc = choose_pack_color_proc(false, dstInfo.colorType());
        for (uint32_t i = 0; i < colorCount; i++) {
            colorPtr[i] = proc(0xFF, colorMap->Colors[i].Red,
                    colorMap->Colors[i].Green, colorMap->Colors[i].Blue);
        }
    }

    // Fill in the color table for indices greater than color count.
    // This allows for predictable, safe behavior.
    if (colorCount > 0) {
        // Gifs have the option to specify the color at a single index of the color
        // table as transparent.  If the transparent index is greater than the
        // colorCount, we know that there is no valid transparent color in the color
        // table.  If there is not valid transparent index, we will try to use the
        // backgroundIndex as the fill index.  If the backgroundIndex is also not
        // valid, we will let fFillIndex default to 0 (it is set to zero in the
        // constructor).  This behavior is not specified but matches
        // SkImageDecoder_libgif.
        uint32_t backgroundIndex = fGif->SBackGroundColor;
        if (fTransIndex < colorCount) {
            colorPtr[fTransIndex] = SK_ColorTRANSPARENT;
            fFillIndex = fTransIndex;
        } else if (backgroundIndex < colorCount) {
            fFillIndex = backgroundIndex;
        }

        for (uint32_t i = colorCount; i < maxColors; i++) {
            colorPtr[i] = colorPtr[fFillIndex];
        }
    } else {
        sk_memset32(colorPtr, 0xFF000000, maxColors);
    }

    fColorTable.reset(new SkColorTable(colorPtr, maxColors));
    copy_color_table(dstInfo, this->fColorTable, inputColorPtr, inputColorCount);
}
示例#30
0
/**
 *  Fill with all zeros, which will never match any value from fill_4x4_pixels
 */
static void clear_4x4_pixels(SkPMColor colors[16]) {
    sk_memset32(colors, 0, 16);
}