static void check(skiatest::Reporter* r, const char path[], SkISize size, bool supportsScanlineDecoding, bool supportsSubsetDecoding, bool supportsIncomplete = true) { SkAutoTDelete<SkStream> stream(resource(path)); if (!stream) { SkDebugf("Missing resource '%s'\n", path); return; } SkAutoTDelete<SkCodec> codec(nullptr); bool isIncomplete = supportsIncomplete; if (isIncomplete) { size_t size = stream->getLength(); SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))); codec.reset(SkCodec::NewFromData(data)); } else { codec.reset(SkCodec::NewFromStream(stream.detach())); } if (!codec) { ERRORF(r, "Unable to decode '%s'", path); return; } // Test full image decodes with SkCodec SkMD5::Digest codecDigest; SkImageInfo info = codec->getInfo().makeColorType(kN32_SkColorType); SkBitmap bm; SkCodec::Result expectedResult = isIncomplete ? SkCodec::kIncompleteInput : SkCodec::kSuccess; test_codec(r, codec.get(), bm, info, size, expectedResult, &codecDigest, nullptr); // Scanline decoding follows. // Need to call startScanlineDecode() first. REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0); REPORTER_ASSERT(r, codec->skipScanlines(1) == 0); const SkCodec::Result startResult = codec->startScanlineDecode(info); if (supportsScanlineDecoding) { bm.eraseColor(SK_ColorYELLOW); REPORTER_ASSERT(r, startResult == SkCodec::kSuccess); for (int y = 0; y < info.height(); y++) { const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); if (!isIncomplete) { REPORTER_ASSERT(r, 1 == lines); } } // verify that scanline decoding gives the same result. if (SkCodec::kTopDown_SkScanlineOrder == codec->getScanlineOrder()) { compare_to_good_digest(r, codecDigest, bm); } // Cannot continue to decode scanlines beyond the end REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0); // Interrupting a scanline decode with a full decode starts from // scratch REPORTER_ASSERT(r, codec->startScanlineDecode(info) == SkCodec::kSuccess); const int lines = codec->getScanlines(bm.getAddr(0, 0), 1, 0); if (!isIncomplete) { REPORTER_ASSERT(r, lines == 1); } REPORTER_ASSERT(r, codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes()) == expectedResult); REPORTER_ASSERT(r, codec->getScanlines(bm.getAddr(0, 0), 1, 0) == 0); REPORTER_ASSERT(r, codec->skipScanlines(1) == 0); // Test partial scanline decodes if (supports_scaled_codec(path) && info.width() >= 3) { SkCodec::Options options; int width = info.width(); int height = info.height(); SkIRect subset = SkIRect::MakeXYWH(2 * (width / 3), 0, width / 3, height); options.fSubset = ⊂ const SkCodec::Result partialStartResult = codec->startScanlineDecode(info, &options, nullptr, nullptr); REPORTER_ASSERT(r, partialStartResult == SkCodec::kSuccess); for (int y = 0; y < height; y++) { const int lines = codec->getScanlines(bm.getAddr(0, y), 1, 0); if (!isIncomplete) { REPORTER_ASSERT(r, 1 == lines); } } } } else { REPORTER_ASSERT(r, startResult == SkCodec::kUnimplemented); } // The rest of this function tests decoding subsets, and will decode an arbitrary number of // random subsets. // Do not attempt to decode subsets of an image of only once pixel, since there is no // meaningful subset. if (size.width() * size.height() == 1) { return; } SkRandom rand; SkIRect subset; SkCodec::Options opts; opts.fSubset = ⊂ for (int i = 0; i < 5; i++) { subset = generate_random_subset(&rand, size.width(), size.height()); SkASSERT(!subset.isEmpty()); const bool supported = codec->getValidSubset(&subset); REPORTER_ASSERT(r, supported == supportsSubsetDecoding); SkImageInfo subsetInfo = info.makeWH(subset.width(), subset.height()); SkBitmap bm; bm.allocPixels(subsetInfo); const SkCodec::Result result = codec->getPixels(bm.info(), bm.getPixels(), bm.rowBytes(), &opts, nullptr, nullptr); if (supportsSubsetDecoding) { REPORTER_ASSERT(r, result == expectedResult); // Webp is the only codec that supports subsets, and it will have modified the subset // to have even left/top. REPORTER_ASSERT(r, SkIsAlign2(subset.fLeft) && SkIsAlign2(subset.fTop)); } else { // No subsets will work. REPORTER_ASSERT(r, result == SkCodec::kUnimplemented); } } // SkScaledCodec tests if ((supportsScanlineDecoding || supportsSubsetDecoding) && supports_scaled_codec(path)) { SkAutoTDelete<SkStream> stream(resource(path)); if (!stream) { SkDebugf("Missing resource '%s'\n", path); return; } SkAutoTDelete<SkAndroidCodec> androidCodec(nullptr); if (isIncomplete) { size_t size = stream->getLength(); SkAutoTUnref<SkData> data((SkData::NewFromStream(stream, 2 * size / 3))); androidCodec.reset(SkAndroidCodec::NewFromData(data)); } else { androidCodec.reset(SkAndroidCodec::NewFromStream(stream.detach())); } if (!androidCodec) { ERRORF(r, "Unable to decode '%s'", path); return; } SkBitmap bm; SkMD5::Digest scaledCodecDigest; test_codec(r, androidCodec.get(), bm, info, size, expectedResult, &scaledCodecDigest, &codecDigest); } // Test SkCodecImageGenerator if (!isIncomplete) { SkAutoTDelete<SkStream> stream(resource(path)); SkAutoTUnref<SkData> fullData(SkData::NewFromStream(stream, stream->getLength())); SkAutoTDelete<SkImageGenerator> gen(SkCodecImageGenerator::NewFromEncodedCodec(fullData)); SkBitmap bm; bm.allocPixels(info); SkAutoLockPixels autoLockPixels(bm); REPORTER_ASSERT(r, gen->getPixels(info, bm.getPixels(), bm.rowBytes())); compare_to_good_digest(r, codecDigest, bm); } // If we've just tested incomplete decodes, let's run the same test again on full decodes. if (isIncomplete) { check(r, path, size, supportsScanlineDecoding, supportsSubsetDecoding, false); } }
void QOscServer::readyRead() { //qDebug() << "QOscServer::readyRead()"; while ( socket()->hasPendingDatagrams() ) { QByteArray fullData( BUFFERSIZE, char( 0 ) ); int size = socket()->readDatagram( fullData.data(), BUFFERSIZE ); //qDebug() << " read" << size << "(" << fullData.size() << ") bytes:" << fullData; //printf("%s\n", qPrintable(QString(fullData.toHex()))); QList<QByteArray> list; if(fullData.left(7) == "#bundle") { int k = 16; while (k < size) { int chunkSize = toInt32(fullData.mid(k, 4)); QByteArray dataChunk = fullData.mid( k+4 , chunkSize); //qDebug() << " readchunk" << chunkSize << "(" << dataChunk.size() << ") bytes:" << dataChunk; list.append(dataChunk); if (chunkSize == 0) break; k += (chunkSize + 4); } } else { list.append(fullData); } QString path; QString args; QVariant arguments; for (int index = 0; index < list.size(); ++index) { QByteArray data = list.at(index); int i = 0; if ( data[ i ] == '/' ) { for ( ; i<size && data[ i ] != char( 0 ); ++i ) path += data[ i ]; while ( data[ i ] != ',' ) ++i; ++i; while ( data[ i ] != char( 0 ) ) args += data[ i++ ]; i++; //move one byte more! if ( ! args.isEmpty() ) { QList<QVariant> list1; foreach( QChar type, args ) { while ( i%4 != 0 ) ++i; //qDebug() << i << "\ttrying to convert to" << type; QByteArray tmp = data.right( data.size()-i ); QVariant value; if ( type == 's' ) { QString s = toString( tmp ); value = s; // string size plus one for the null terminator i += s.size() + 1; } if ( type == 'i' ) { value = toInt32( tmp ); i+=4; } if ( type == 'f' ) { value = toFloat( tmp ); i+=4; } //qDebug() << " got" << value; if ( args.size() > 1 ) list1.append( value ); else arguments = value; } if ( args.size() > 1 ) arguments = list1; } } qDebug() << "path seems to be" << path << "args are" << args << ":" << arguments; QMap<QString,QString> replacements; replacements[ "!" ] = "^"; replacements[ "{" ] = "("; replacements[ "}" ] = ")"; replacements[ "," ] = "|"; replacements[ "*" ] = ".*"; replacements[ "?" ] = "."; foreach( QString rep, replacements.keys() ) path.replace( rep, replacements[ rep ] ); //qDebug() << " after transformation to OSC-RegExp path is" << path; QRegExp exp( path ); foreach( PathObject* obj, paths ) { if ( exp.exactMatch( obj->_path ) ) obj->signalData( arguments ); } } }