Beispiel #1
0
static bool SK_WARN_UNUSED_RESULT flatten(const SkImage& image, Json::Value* target, 
                                          bool sendBinaries) {
    if (sendBinaries) {
        SkData* encoded = image.encode(SkImageEncoder::kPNG_Type, 100);
        if (encoded == nullptr) {
            // PNG encode doesn't necessarily support all color formats, convert to a different
            // format
            size_t rowBytes = 4 * image.width();
            void* buffer = sk_malloc_throw(rowBytes * image.height());
            SkImageInfo dstInfo = SkImageInfo::Make(image.width(), image.height(), 
                                                    kN32_SkColorType, kPremul_SkAlphaType);
            if (!image.readPixels(dstInfo, buffer, rowBytes, 0, 0)) {
                SkDebugf("readPixels failed\n");
                return false;
            }
            SkImage* converted = SkImage::NewRasterCopy(dstInfo, buffer, rowBytes);
            encoded = converted->encode(SkImageEncoder::kPNG_Type, 100);
            if (encoded == nullptr) {
                SkDebugf("image encode failed\n");
                return false;
            }
            free(converted);
            free(buffer);
        }
        Json::Value bytes;
        encode_data(encoded->data(), encoded->size(), &bytes);
        (*target)[SKJSONCANVAS_ATTRIBUTE_BYTES] = bytes;
        encoded->unref();
    }
    else {
        SkString description = SkStringPrintf("%dx%d pixel image", image.width(), image.height());
        (*target)[SKJSONCANVAS_ATTRIBUTE_DESCRIPTION] = Json::Value(description.c_str());
    }
    return true;
}
Beispiel #2
0
void TestDataRef(skiatest::Reporter* reporter) {
    const char* str = "We the people, in order to form a more perfect union.";
    const int N = 10;

    SkData* r0 = SkData::NewEmpty();
    SkData* r1 = SkData::NewWithCopy(str, strlen(str));
    SkData* r2 = SkData::NewWithProc(new int[N], N*sizeof(int),
                                           delete_int_proc, gGlobal);
    SkData* r3 = SkData::NewSubset(r1, 7, 6);

    SkAutoUnref aur0(r0);
    SkAutoUnref aur1(r1);
    SkAutoUnref aur2(r2);
    SkAutoUnref aur3(r3);
    
    assert_len(reporter, r0, 0);
    assert_len(reporter, r1, strlen(str));
    assert_len(reporter, r2, N * sizeof(int));
    assert_len(reporter, r3, 6);
    
    assert_data(reporter, r1, str, strlen(str));
    assert_data(reporter, r3, "people", 6);

    SkData* tmp = SkData::NewSubset(r1, strlen(str), 10);
    assert_len(reporter, tmp, 0);
    tmp->unref();
    tmp = SkData::NewSubset(r1, 0, 0);
    assert_len(reporter, tmp, 0);
    tmp->unref();
}
Beispiel #3
0
DEF_TEST(Data, reporter) {
    const char* str = "We the people, in order to form a more perfect union.";
    const int N = 10;

    SkAutoTUnref<SkData> r0(SkData::NewEmpty());
    SkAutoTUnref<SkData> r1(SkData::NewWithCopy(str, strlen(str)));
    SkAutoTUnref<SkData> r2(SkData::NewWithProc(new int[N], N*sizeof(int),
                                           delete_int_proc, gGlobal));
    SkAutoTUnref<SkData> r3(SkData::NewSubset(r1, 7, 6));

    assert_len(reporter, r0, 0);
    assert_len(reporter, r1, strlen(str));
    assert_len(reporter, r2, N * sizeof(int));
    assert_len(reporter, r3, 6);

    assert_data(reporter, r1, str, strlen(str));
    assert_data(reporter, r3, "people", 6);

    SkData* tmp = SkData::NewSubset(r1, strlen(str), 10);
    assert_len(reporter, tmp, 0);
    tmp->unref();
    tmp = SkData::NewSubset(r1, 0, 0);
    assert_len(reporter, tmp, 0);
    tmp->unref();

    test_cstring(reporter);
    test_files(reporter);
}
Beispiel #4
0
int tool_main(int argc, char** argv) {
    SkAutoGraphics ag;
    SkLua L;

    for (int i = 1; i < argc; ++i) {
        SkData* data = nullptr;
        const void* ptr;
        size_t len;

        if (!strcmp(argv[i], "--lua") && i < argc-1) {
            ptr = argv[i + 1];
            len = strlen(argv[i + 1]);
            i += 1;
        } else {
            data = read_into_data(argv[i]);
            ptr = data->data();
            len = data->size();
        }
        if (!L.runCode(ptr, len)) {
            SkDebugf("failed to load %s\n", argv[i]);
            exit(-1);
        }
        SkSafeUnref(data);
    }
    return 0;
}
Beispiel #5
0
static void TestWStream(skiatest::Reporter* reporter) {
    SkDynamicMemoryWStream  ds;
    const char s[] = "abcdefghijklmnopqrstuvwxyz";
    int i;
    for (i = 0; i < 100; i++) {
        REPORTER_ASSERT(reporter, ds.write(s, 26));
    }
    REPORTER_ASSERT(reporter, ds.getOffset() == 100 * 26);
    char* dst = new char[100 * 26 + 1];
    dst[100*26] = '*';
    ds.copyTo(dst);
    REPORTER_ASSERT(reporter, dst[100*26] == '*');
//     char* p = dst;
    for (i = 0; i < 100; i++) {
        REPORTER_ASSERT(reporter, memcmp(&dst[i * 26], s, 26) == 0);
    }

    {
        SkData* data = ds.copyToData();
        REPORTER_ASSERT(reporter, 100 * 26 == data->size());
        REPORTER_ASSERT(reporter, memcmp(dst, data->data(), data->size()) == 0);
        data->unref();
    }
    delete[] dst;
}
static SkData* make_3Dlut(int* cubeDimension, bool invR, bool invG, bool invB) {
    int size = 4 << R(5);
    SkData* data = SkData::NewUninitialized(sizeof(SkColor) * size * size * size);
    SkColor* pixels = (SkColor*)(data->writable_data());
    SkAutoTMalloc<uint8_t> lutMemory(size);
    SkAutoTMalloc<uint8_t> invLutMemory(size);
    uint8_t* lut = lutMemory.get();
    uint8_t* invLut = invLutMemory.get();
    const int maxIndex = size - 1;
    for (int i = 0; i < size; i++) {
        lut[i] = (i * 255) / maxIndex;
        invLut[i] = ((maxIndex - i) * 255) / maxIndex;
    }
    for (int r = 0; r < size; ++r) {
        for (int g = 0; g < size; ++g) {
            for (int b = 0; b < size; ++b) {
                pixels[(size * ((size * b) + g)) + r] = SkColorSetARGB(0xFF,
                        invR ? invLut[r] : lut[r],
                        invG ? invLut[g] : lut[g],
                        invB ? invLut[b] : lut[b]);
            }
        }
    }
    if (cubeDimension) {
        *cubeDimension = size;
    }
    return data;
}
static void decodeThreadWithRefEncodedMain(ImageFrameGenerator* generator)
{
    // Image must be complete - refEncodedData otherwise returns null.
    char buffer[100 * 100 * 4];
    SkData* data = generator->refEncodedData();
    generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4);
    data->unref();
}
Beispiel #8
0
// asserts that inner is a subset of outer
static void test_dataset_subset(skiatest::Reporter* reporter,
                                const SkDataSet& outer, const SkDataSet& inner) {
    SkDataSet::Iter iter(inner);
    for (; !iter.done(); iter.next()) {
        SkData* outerData = outer.find(iter.key());
        REPORTER_ASSERT(reporter, outerData);
        REPORTER_ASSERT(reporter, outerData->equals(iter.value()));
    }
}
static void TypefaceStyle_test(skiatest::Reporter* reporter,
                               uint16_t weight, uint16_t width, SkData* data)
{
    sk_sp<SkData> dataCopy;
    SkData* dataToUse = data;
    if (!dataToUse->unique()) {
        dataCopy = SkData::MakeWithCopy(data->data(), data->size());
        dataToUse = dataCopy.get();
    }
    SkSFNTHeader* sfntHeader = static_cast<SkSFNTHeader*>(dataToUse->writable_data());

    SkSFNTHeader::TableDirectoryEntry* tableEntry =
        SkTAfter<SkSFNTHeader::TableDirectoryEntry>(sfntHeader);
    SkSFNTHeader::TableDirectoryEntry* os2TableEntry = nullptr;
    int numTables = SkEndian_SwapBE16(sfntHeader->numTables);
    for (int tableEntryIndex = 0; tableEntryIndex < numTables; ++tableEntryIndex) {
        if (SkOTTableOS2::TAG == tableEntry[tableEntryIndex].tag) {
            os2TableEntry = tableEntry + tableEntryIndex;
            break;
        }
    }
    SkASSERT_RELEASE(os2TableEntry);

    size_t os2TableOffset = SkEndian_SwapBE32(os2TableEntry->offset);
    SkOTTableOS2_V0* os2Table = SkTAddOffset<SkOTTableOS2_V0>(sfntHeader, os2TableOffset);
    os2Table->usWeightClass.value = SkEndian_SwapBE16(weight);
    using WidthType = SkOTTableOS2_V0::WidthClass::Value;
    os2Table->usWidthClass.value = static_cast<WidthType>(SkEndian_SwapBE16(width));

    sk_sp<SkTypeface> newTypeface(SkTypeface::MakeFromStream(new SkMemoryStream(dataToUse)));
    SkASSERT_RELEASE(newTypeface);

    SkFontStyle newStyle = newTypeface->fontStyle();

    //printf("%d, %f\n", weight, (newStyle.weight() - (float)0x7FFF) / (float)0x7FFF);
    //printf("%d, %f\n", width , (newStyle.width()  - (float)0x7F)   / (float)0x7F);
    //printf("%d, %d\n", weight, newStyle.weight());
    //printf("%d, %d\n", width , newStyle.width());

    // Some back-ends (CG, GDI, DW) support OS/2 version A which uses 0 - 10 (but all differently).
    REPORTER_ASSERT(reporter,
                    newStyle.weight() == weight ||
                    (weight <=   10 && newStyle.weight() == 100 * weight) ||
                    (weight ==    4 && newStyle.weight() == 350) ||  // GDI weirdness
                    (weight ==    5 && newStyle.weight() == 400) ||  // GDI weirdness
                    (weight ==    0 && newStyle.weight() ==   1) ||  // DW weirdness
                    (weight == 1000 && newStyle.weight() == 999)     // DW weirdness
    );

    // Some back-ends (GDI) don't support width, ensure these always report 'medium'.
    REPORTER_ASSERT(reporter,
                    newStyle.width() == width ||
                    newStyle.width() == 5);
}
Beispiel #10
0
SkData* SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) {
    if (0 == length) {
        return SkData::NewEmpty();
    }
    char* storage = (char*)sk_malloc_throw(sizeof(SkData) + length);
    SkData* data = new (storage) SkData(length);
    if (srcOrNull) {
        memcpy(data->writable_data(), srcOrNull, length);
    }
    return data;
}
Beispiel #11
0
DEF_TEST(ImageDataRef, reporter) {
    SkImageInfo info = SkImageInfo::MakeN32Premul(1, 1);
    size_t rowBytes = info.minRowBytes();
    size_t size = info.getSafeSize(rowBytes);
    SkData* data = SkData::NewUninitialized(size);
    REPORTER_ASSERT(reporter, data->unique());
    SkImage* image = SkImage::NewRasterData(info, data, rowBytes);
    REPORTER_ASSERT(reporter, !data->unique());
    image->unref();
    REPORTER_ASSERT(reporter, data->unique());
    data->unref();
}
Beispiel #12
0
SkData* SkRecorder::newDrawableSnapshot(SkBBHFactory* factory, uint32_t recordFlags) {
    const int count = fDrawableList.count();
    if (0 == count) {
        return NULL;
    }
    SkData* data = new_uninitialized_refcnt_ptrs(count);
    SkPicture** pics = reinterpret_cast<SkPicture**>(data->writable_data());
    for (int i = 0; i < count; ++i) {
        pics[i] = fDrawableList[i]->newPictureSnapshot(factory, recordFlags);
    }
    return data;
}
Beispiel #13
0
static void send_picture(int socket, const PictureHeader& header, const SkData& skp) {
    // Vectored IO lets us send header and skp contiguously without first
    // copying them to a contiguous buffer.
    struct nn_iovec iov[] = {
        create_iov(&header, sizeof(header)),
        create_iov(skp.data(), skp.size()),
    };

    struct nn_msghdr msg;
    sk_bzero(&msg, sizeof(msg));
    msg.msg_iov    = iov;
    msg.msg_iovlen = SK_ARRAY_COUNT(iov);

    nn_sendmsg(socket, &msg, 0/*flags*/);
}
SkData* CompressBitmapToFormat(const SkPixmap& pixmap, Format format) {
    int compressedDataSize = GetCompressedDataSize(format, pixmap.width(), pixmap.height());
    if (compressedDataSize < 0) {
        return NULL;
    }

    const uint8_t* src = reinterpret_cast<const uint8_t*>(pixmap.addr());
    SkData* dst = SkData::NewUninitialized(compressedDataSize);

    if (!CompressBufferToFormat((uint8_t*)dst->writable_data(), src, pixmap.colorType(),
                                pixmap.width(), pixmap.height(), pixmap.rowBytes(), format)) {
        dst->unref();
        dst = NULL;
    }
    return dst;
}
Beispiel #15
0
    lua_State* ensureLua() {
        if (NULL == fLua) {
            fLua = SkNEW(SkLua);

            SkString str = GetResourcePath(LUA_FILENAME);
            SkData* data = SkData::NewFromFileName(str.c_str());
            if (data) {
                fLua->runCode(data->data(), data->size());
                data->unref();
                this->setImageFilename(fLua->get());
            } else {
                fLua->runCode(gMissingCode);
            }
        }
        return fLua->get();
    }
String ImageBuffer::toDataURL(const String&, const double*) const
{
    // Encode the image into a vector.
    SkDynamicMemoryWStream pngStream;
    const SkBitmap& dst = imageBufferCanvas(this)->getDevice()->accessBitmap(true);
    SkImageEncoder::EncodeStream(&pngStream, dst, SkImageEncoder::kPNG_Type, 100);

    // Convert it into base64.
    Vector<char> pngEncodedData;
    SkData* streamData = pngStream.copyToData();
    pngEncodedData.append((char*)streamData->data(), streamData->size());
    streamData->unref();
    Vector<char> base64EncodedData;
    base64Encode(pngEncodedData, base64EncodedData);
    // Append with a \0 so that it's a valid string.
    base64EncodedData.append('\0');

    // And the resulting string.
    return String::format("data:image/png;base64,%s", base64EncodedData.data());
}
Beispiel #17
0
/*
If you execute skp_parser with one argument, it spits out a json representation
of the skp, but that's incomplete since it's missing many binary blobs (these
could represent images or typefaces or just anything that doesn't currently
have a json representation).  Each unique blob is labeled with a string in the
form "data/%d".  So for example:

    tools/git-sync-deps
    bin/gn gen out/debug
    ninja -C out/debug dm skp_parser
    out/debug/dm -m grayscale -w /tmp/dm --config skp
    out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp | less
    out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp | grep data
    out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp data/0 | file -
    out/debug/skp_parser /tmp/dm/skp/gm/grayscalejpg.skp data/0 > /tmp/data0.png

"data/0" is an image that the SKP serializer has encoded as PNG.
*/
int main(int argc, char** argv) {
    if (argc < 2) {
        SkDebugf("Usage:\n  %s SKP_FILE [DATA_URL]\n", argv[0]);
        return 1;
    }
    SkFILEStream input(argv[1]);
    if (!input.isValid()) {
        SkDebugf("Bad file: '%s'\n", argv[1]);
        return 2;
    }
    sk_sp<SkPicture> pic = SkPicture::MakeFromStream(&input);
    if (!pic) {
        SkDebugf("Bad skp: '%s'\n", argv[1]);
        return 3;
    }
    SkISize size = pic->cullRect().roundOut().size();
    SkDebugCanvas debugCanvas(size.width(), size.height());
    pic->playback(&debugCanvas);
    std::unique_ptr<SkCanvas> nullCanvas = SkMakeNullCanvas();
    UrlDataManager dataManager(SkString("data"));
    Json::Value json = debugCanvas.toJSON(
            dataManager, debugCanvas.getSize(), nullCanvas.get());
    if (argc > 2) {
        if (UrlDataManager::UrlData* data =
            dataManager.getDataFromUrl(SkString(argv[2]))) {
            SkData* skdata = data->fData.get();
            SkASSERT(skdata);
            #ifdef SK_BUILD_FOR_WIN
            fflush(stdout);
            (void)_setmode(_fileno(stdout), _O_BINARY);
            #endif
            fwrite(skdata->data(), skdata->size(), 1, stdout);
        } else {
            SkDebugf("Bad data url.\n");
            return 4;
        }
    } else {
        Json::StyledStreamWriter("  ").write(std::cout, json);
    }
    return 0;
}
TEST_F(ImageFrameGeneratorTest, incompleteDecodeBecomesCompleteMultiThreaded)
{
    setFrameStatus(ImageFrame::FramePartial);

    char buffer[100 * 100 * 4];
    m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4);
    EXPECT_EQ(1, m_decodeRequestCount);
    EXPECT_EQ(0, m_decodersDestroyed);
    SkData* data = m_generator->refEncodedData();
    EXPECT_EQ(nullptr, data);

    // LocalFrame can now be decoded completely.
    setFrameStatus(ImageFrame::FrameComplete);
    addNewData();
    // addNewData is calling m_generator->setData with allDataReceived == false, which means that
    // refEncodedData should return null.
    data = m_generator->refEncodedData();
    EXPECT_EQ(nullptr, data);
    OwnPtr<WebThread> thread = adoptPtr(Platform::current()->createThread("DecodeThread"));
    thread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSafeBind(&decodeThreadMain, AllowCrossThreadAccess(m_generator.get()))));
    thread.clear();
    EXPECT_EQ(2, m_decodeRequestCount);
    EXPECT_EQ(1, m_decodersDestroyed);

    // Decoder created again.
    m_generator->decodeAndScale(0, imageInfo(), buffer, 100 * 4);
    EXPECT_EQ(3, m_decodeRequestCount);

    addNewData(true);
    data = m_generator->refEncodedData();
    ASSERT_TRUE(data);
    // To prevent data writting, SkData::unique() should be false.
    ASSERT_TRUE(!data->unique());

    // Thread will also ref and unref the data.
    thread = adoptPtr(Platform::current()->createThread("RefEncodedDataThread"));
    thread->taskRunner()->postTask(BLINK_FROM_HERE, new Task(threadSafeBind(&decodeThreadWithRefEncodedMain, AllowCrossThreadAccess(m_generator.get()))));
    thread.clear();
    EXPECT_EQ(4, m_decodeRequestCount);

    data->unref();
    // m_generator is holding the only reference to SkData now.
    ASSERT_TRUE(data->unique());

    data = m_generator->refEncodedData();
    ASSERT_TRUE(data && !data->unique());

    // Delete generator, and SkData should have the only reference.
    m_generator = nullptr;
    ASSERT_TRUE(data->unique());
    data->unref();
}
Beispiel #19
0
 void makeCubeData() {
     fCubeDimension = 32;
     fCubeData = SkData::NewUninitialized(sizeof(SkColor) *
                                          fCubeDimension * fCubeDimension * fCubeDimension);
     SkColor* pixels = (SkColor*)(fCubeData->writable_data());
     SkAutoTMalloc<uint8_t> lutMemory(fCubeDimension);
     uint8_t* lut = lutMemory.get();
     const int maxIndex = fCubeDimension - 1;
     for (int i = 0; i < fCubeDimension; ++i) {
         // Make an invert lut, but the content of
         // the lut shouldn't affect performance.
         lut[i] = ((maxIndex - i) * 255) / maxIndex;
     }
     for (int r = 0; r < fCubeDimension; ++r) {
         for (int g = 0; g < fCubeDimension; ++g) {
             for (int b = 0; b < fCubeDimension; ++b) {
                 pixels[(fCubeDimension * ((fCubeDimension * b) + g)) + r] =
                     SkColorSetARGB(0xFF, lut[r], lut[g], lut[b]);
             }
         }
     }
 }
Beispiel #20
0
// static
void SkPDFUtils::EmitPath(const SkPath& path, SkPaint::Style paintStyle,
                          SkWStream* content) {
    // Filling a path with no area results in a drawing in PDF renderers but
    // Chrome expects to be able to draw some such entities with no visible
    // result, so we detect those cases and discard the drawing for them.
    // Specifically: moveTo(X), lineTo(Y) and moveTo(X), lineTo(X), lineTo(Y).
    enum SkipFillState {
        kEmpty_SkipFillState         = 0,
        kSingleLine_SkipFillState    = 1,
        kNonSingleLine_SkipFillState = 2,
    };
    SkipFillState fillState = kEmpty_SkipFillState;
    if (paintStyle != SkPaint::kFill_Style) {
        fillState = kNonSingleLine_SkipFillState;
    }
    SkPoint lastMovePt = SkPoint::Make(0,0);
    SkDynamicMemoryWStream currentSegment;
    SkPoint args[4];
    SkPath::Iter iter(path, false);
    for (SkPath::Verb verb = iter.next(args);
         verb != SkPath::kDone_Verb;
         verb = iter.next(args)) {
        // args gets all the points, even the implicit first point.
        switch (verb) {
            case SkPath::kMove_Verb:
                MoveTo(args[0].fX, args[0].fY, &currentSegment);
                lastMovePt = args[0];
                fillState = kEmpty_SkipFillState;
                break;
            case SkPath::kLine_Verb:
                AppendLine(args[1].fX, args[1].fY, &currentSegment);
                if (fillState == kEmpty_SkipFillState) {
                   if (args[0] != lastMovePt) {
                       fillState = kSingleLine_SkipFillState;
                   }
                } else if (fillState == kSingleLine_SkipFillState) {
                    fillState = kNonSingleLine_SkipFillState;
                }
                break;
            case SkPath::kQuad_Verb: {
                SkPoint cubic[4];
                SkConvertQuadToCubic(args, cubic);
                AppendCubic(cubic[1].fX, cubic[1].fY, cubic[2].fX, cubic[2].fY,
                            cubic[3].fX, cubic[3].fY, &currentSegment);
                fillState = kNonSingleLine_SkipFillState;
                break;
            }
            case SkPath::kCubic_Verb:
                AppendCubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
                            args[3].fX, args[3].fY, &currentSegment);
                fillState = kNonSingleLine_SkipFillState;
                break;
            case SkPath::kClose_Verb:
                if (fillState != kSingleLine_SkipFillState) {
                    ClosePath(&currentSegment);
                    SkData* data = currentSegment.copyToData();
                    content->write(data->data(), data->size());
                    data->unref();
                }
                currentSegment.reset();
                break;
            default:
                SkASSERT(false);
                break;
        }
    }
    if (currentSegment.bytesWritten() > 0) {
        SkData* data = currentSegment.copyToData();
        content->write(data->data(), data->size());
        data->unref();
    }
}
Beispiel #21
0
// assumes context is a SkData
static void sk_dataref_releaseproc(const void*, size_t, void* context) {
    SkData* src = reinterpret_cast<SkData*>(context);
    src->unref();
}
static void test_gatherpixelrefs(skiatest::Reporter* reporter) {
    const int IW = 8;
    const int IH = IW;
    const SkScalar W = SkIntToScalar(IW);
    const SkScalar H = W;

    static const int N = 4;
    SkBitmap bm[N];
    SkPixelRef* refs[N];

    const SkPoint pos[] = {
        { 0, 0 }, { W, 0 }, { 0, H }, { W, H }
    };

    // Our convention is that the color components contain the index of their
    // corresponding bitmap/pixelref
    for (int i = 0; i < N; ++i) {
        make_bm(&bm[i], IW, IH, SkColorSetARGB(0xFF, i, i, i), true);
        refs[i] = bm[i].pixelRef();
    }

    static const DrawBitmapProc procs[] = {
        drawbitmap_proc, drawbitmaprect_proc, drawshader_proc
    };

    SkRandom rand;
    for (size_t k = 0; k < SK_ARRAY_COUNT(procs); ++k) {
        SkAutoTUnref<SkPicture> pic(record_bitmaps(bm, pos, N, procs[k]));

        REPORTER_ASSERT(reporter, pic->willPlayBackBitmaps() || N == 0);
        // quick check for a small piece of each quadrant, which should just
        // contain 1 bitmap.
        for (size_t  i = 0; i < SK_ARRAY_COUNT(pos); ++i) {
            SkRect r;
            r.set(2, 2, W - 2, H - 2);
            r.offset(pos[i].fX, pos[i].fY);
            SkAutoDataUnref data(SkPictureUtils::GatherPixelRefs(pic, r));
            REPORTER_ASSERT(reporter, data);
            if (data) {
                int count = static_cast<int>(data->size() / sizeof(SkPixelRef*));
                REPORTER_ASSERT(reporter, 1 == count);
                REPORTER_ASSERT(reporter, *(SkPixelRef**)data->data() == refs[i]);
            }
        }

        // Test a bunch of random (mostly) rects, and compare the gather results
        // with a deduced list of refs by looking at the colors drawn.
        for (int j = 0; j < 100; ++j) {
            SkRect r;
            rand_rect(&r, rand, 2*W, 2*H);

            SkBitmap result;
            draw(pic, r, &result);
            SkTDArray<SkPixelRef*> array;

            SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
            size_t dataSize = data ? data->size() : 0;
            int gatherCount = static_cast<int>(dataSize / sizeof(SkPixelRef*));
            SkASSERT(gatherCount * sizeof(SkPixelRef*) == dataSize);
            SkPixelRef** gatherRefs = data ? (SkPixelRef**)(data->data()) : NULL;
            SkAutoDataUnref adu(data);

            gather_from_colors(result, refs, N, &array);

            /*
             *  GatherPixelRefs is conservative, so it can return more bitmaps
             *  that we actually can see (usually because of conservative bounds
             *  inflation for antialiasing). Thus our check here is only that
             *  Gather didn't miss any that we actually saw. Even that isn't
             *  a strict requirement on Gather, which is meant to be quick and
             *  only mostly-correct, but at the moment this test should work.
             */
            for (int i = 0; i < array.count(); ++i) {
                bool found = find(gatherRefs, array[i], gatherCount);
                REPORTER_ASSERT(reporter, found);
#if 0
                // enable this block of code to debug failures, as it will rerun
                // the case that failed.
                if (!found) {
                    SkData* data = SkPictureUtils::GatherPixelRefs(pic, r);
                    size_t dataSize = data ? data->size() : 0;
                }
#endif
            }
        }
    }
}
Beispiel #23
0
int SkSocket::readPacket(void (*onRead)(int, const void*, size_t, DataType,
                                        void*), void* context) {
    if (!fConnected || !fReady || NULL == onRead || NULL == context
        || fReadSuspended)
        return -1;

    int totalBytesRead = 0;

    char packet[PACKET_SIZE];
    for (int i = 0; i <= fMaxfd; ++i) {
        if (!FD_ISSET (i, &fMasterSet))
            continue;

        memset(packet, 0, PACKET_SIZE);
        SkDynamicMemoryWStream stream;
        int attempts = 0;
        bool failure = false;
        int bytesReadInTransfer = 0;
        int bytesReadInPacket = 0;
        header h;
        h.done = false;
        h.bytes = 0;
        while (!h.done && fConnected && !failure) {
            int retval = read(i, packet + bytesReadInPacket,
                              PACKET_SIZE - bytesReadInPacket);

            ++attempts;
            if (retval < 0) {
#ifdef NONBLOCKING_SOCKETS
                if (errno == EWOULDBLOCK || errno == EAGAIN) {
                    if (bytesReadInPacket > 0 || bytesReadInTransfer > 0)
                        continue; //incomplete packet or frame, keep tring
                    else
                        break; //nothing to read
                }
#endif
                //SkDebugf("Read() failed with error: %s\n", strerror(errno));
                failure = true;
                break;
            }

            if (retval == 0) {
                //SkDebugf("Peer closed connection or connection failed\n");
                failure = true;
                break;
            }

            SkASSERT(retval > 0);
            bytesReadInPacket += retval;
            if (bytesReadInPacket < PACKET_SIZE) {
                //SkDebugf("Read %d/%d\n", bytesReadInPacket, PACKET_SIZE);
                continue; //incomplete packet, keep trying
            }

            SkASSERT((bytesReadInPacket == PACKET_SIZE) && !failure);
            memcpy(&h.done, packet, sizeof(bool));
            memcpy(&h.bytes, packet + sizeof(bool), sizeof(int));
            memcpy(&h.type, packet + sizeof(bool) + sizeof(int), sizeof(DataType));
            if (h.bytes > CONTENT_SIZE || h.bytes <= 0) {
                //SkDebugf("bad packet\n");
                failure = true;
                break;
            }
            //SkDebugf("read packet(done:%d, bytes:%d) from fd:%d in %d tries\n",
            //         h.done, h.bytes, fSockfd, attempts);
            stream.write(packet + HEADER_SIZE, h.bytes);
            bytesReadInPacket = 0;
            attempts = 0;
            bytesReadInTransfer += h.bytes;
        }

        if (failure) {
            onRead(i, NULL, 0, h.type, context);
            this->onFailedConnection(i);
            continue;
        }

        if (bytesReadInTransfer > 0) {
            SkData* data = stream.copyToData();
            SkASSERT(data->size() == bytesReadInTransfer);
            onRead(i, data->data(), data->size(), h.type, context);
            data->unref();

            totalBytesRead += bytesReadInTransfer;
        }
    }
    return totalBytesRead;
}
Beispiel #24
0
int main(int argc, char** argv)
{

#ifdef MTK_AOSP_ENHANCEMENT
    // work around for SIGPIPE NE caused by abnormal system status
    signal(SIGPIPE, SIG_IGN);
    ALOGD("[Screencap] main");
#endif

    ProcessState::self()->startThreadPool();

    const char* pname = argv[0];
    bool png = false;
    int32_t displayId = DEFAULT_DISPLAY_ID;
    int c;
    while ((c = getopt(argc, argv, "phd:")) != -1) {
        switch (c) {
            case 'p':
                png = true;
                break;
            case 'd':
                displayId = atoi(optarg);
                break;
            case '?':
            case 'h':
                usage(pname);
                return 1;
        }
    }
    argc -= optind;
    argv += optind;

    int fd = -1;
    if (argc == 0) {
        fd = dup(STDOUT_FILENO);
    } else if (argc == 1) {
        const char* fn = argv[0];
        fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664);
        if (fd == -1) {
            fprintf(stderr, "Error opening file: %s (%s)\n", fn, strerror(errno));
            return 1;
        }
        const int len = strlen(fn);
        if (len >= 4 && 0 == strcmp(fn+len-4, ".png")) {
            png = true;
        }
    }
    
    if (fd == -1) {
        usage(pname);
        return 1;
    }

    void const* mapbase = MAP_FAILED;
    ssize_t mapsize = -1;

    void const* base = 0;
    uint32_t w, s, h, f;
    size_t size = 0;

    ScreenshotClient screenshot;
    sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(displayId);
    if (display != NULL && screenshot.update(display, Rect(), false) == NO_ERROR) {
        base = screenshot.getPixels();
        w = screenshot.getWidth();
        h = screenshot.getHeight();
        s = screenshot.getStride();
        f = screenshot.getFormat();
        size = screenshot.getSize();
#ifdef MTK_AOSP_ENHANCEMENT      
        ALOGD("[Screencap] screenshot w:%d h:%d s:%d f:%d", w, h, s, f);
#endif
    } else {
        const char* fbpath = "/dev/graphics/fb0";
        int fb = open(fbpath, O_RDONLY);
        if (fb >= 0) {
            struct fb_var_screeninfo vinfo;
            if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) {
                uint32_t bytespp;
                if (vinfoToPixelFormat(vinfo, &bytespp, &f) == NO_ERROR) {
#ifdef MTK_AOSP_ENHANCEMENT
                    size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres_virtual) * bytespp;
                    w = vinfo.xres;
                    h = vinfo.yres;
                    s = vinfo.xres_virtual;
                    ALOGD("[Screencap] VSCREENINFO w:%d h:%d s:%d f:%d", w, h, s, f);
#else
                    size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp;
                    w = vinfo.xres;
                    h = vinfo.yres;
                    s = vinfo.xres;
#endif
                    size = w*h*bytespp;
                    mapsize = offset + size;
                    mapbase = mmap(0, mapsize, PROT_READ, MAP_PRIVATE, fb, 0);
                    if (mapbase != MAP_FAILED) {
                        base = (void const *)((char const *)mapbase + offset);
                    }
                }
            }
            close(fb);
        }
    }

    if (base) {
        if (png) {
            const SkImageInfo info = SkImageInfo::Make(w, h, flinger2skia(f),
                                                       kPremul_SkAlphaType);
            SkBitmap b;
            b.installPixels(info, const_cast<void*>(base), s*bytesPerPixel(f));
            SkDynamicMemoryWStream stream;
            SkImageEncoder::EncodeStream(&stream, b,
                    SkImageEncoder::kPNG_Type, SkImageEncoder::kDefaultQuality);
            SkData* streamData = stream.copyToData();
            write(fd, streamData->data(), streamData->size());
            streamData->unref();
        } else {
            write(fd, &w, 4);
            write(fd, &h, 4);
            write(fd, &f, 4);
            size_t Bpp = bytesPerPixel(f);
            for (size_t y=0 ; y<h ; y++) {
                write(fd, base, w*Bpp);
                base = (void *)((char *)base + s*Bpp);
            }
        }
    }
    close(fd);
    if (mapbase != MAP_FAILED) {
        munmap((void *)mapbase, mapsize);
    }
    return 0;
}