static inline void test_premul(skiatest::Reporter* reporter) { for (int a = 0; a <= 255; a++) { for (int x = 0; x <= 255; x++) { SkColor c0 = SkColorSetARGB(a, x, x, x); SkPMColor p0 = SkPreMultiplyColor(c0); SkColor c1 = SkUnPreMultiply::PMColorToColor(p0); SkPMColor p1 = SkPreMultiplyColor(c1); // we can't promise that c0 == c1, since c0 -> p0 is a many to one // function, however, we can promise that p0 -> c1 -> p1 : p0 == p1 REPORTER_ASSERT(reporter, p0 == p1); { int ax = SkMulDiv255Ceiling(x, a); REPORTER_ASSERT(reporter, ax <= a); } } } }
void putImageData(ByteArray*& source, const IntSize& sourceSize, const IntRect& sourceRect, const IntPoint& destPoint, SkDevice* dstDevice, const IntSize& size) { ASSERT(sourceRect.width() > 0); ASSERT(sourceRect.height() > 0); int originX = sourceRect.x(); int destX = destPoint.x() + sourceRect.x(); ASSERT(destX >= 0); ASSERT(destX < size.width()); ASSERT(originX >= 0); ASSERT(originX < sourceRect.maxX()); int endX = destPoint.x() + sourceRect.maxX(); ASSERT(endX <= size.width()); int numColumns = endX - destX; int originY = sourceRect.y(); int destY = destPoint.y() + sourceRect.y(); ASSERT(destY >= 0); ASSERT(destY < size.height()); ASSERT(originY >= 0); ASSERT(originY < sourceRect.maxY()); int endY = destPoint.y() + sourceRect.maxY(); ASSERT(endY <= size.height()); int numRows = endY - destY; unsigned srcBytesPerRow = 4 * sourceSize.width(); SkBitmap deviceBitmap = dstDevice->accessBitmap(true); SkAutoLockPixels deviceAutoLock(deviceBitmap); // If the device's bitmap doesn't have pixels we will make a temp and call writePixels on the device. bool temporaryBitmap = !deviceBitmap.getPixels(); SkBitmap destBitmap; if (temporaryBitmap) { destBitmap.setConfig(SkBitmap::kARGB_8888_Config, numColumns, numRows, srcBytesPerRow); if (!destBitmap.allocPixels()) CRASH(); } else deviceBitmap.extractSubset(&destBitmap, SkIRect::MakeXYWH(destX, destY, numColumns, numRows)); // Whether we made a temporary or not destBitmap is always configured to be written at 0,0 SkAutoLockPixels destAutoLock(destBitmap); const unsigned char* srcRow = source->data() + originY * srcBytesPerRow + originX * 4; for (int y = 0; y < numRows; ++y) { SkPMColor* destRow = destBitmap.getAddr32(0, y); for (int x = 0; x < numColumns; ++x) { const unsigned char* srcPixel = &srcRow[x * 4]; if (multiplied == Unmultiplied) { unsigned char alpha = srcPixel[3]; unsigned char r = SkMulDiv255Ceiling(srcPixel[0], alpha); unsigned char g = SkMulDiv255Ceiling(srcPixel[1], alpha); unsigned char b = SkMulDiv255Ceiling(srcPixel[2], alpha); destRow[x] = SkPackARGB32(alpha, r, g, b); } else destRow[x] = SkPackARGB32(srcPixel[3], srcPixel[0], srcPixel[1], srcPixel[2]); } srcRow += srcBytesPerRow; } // If we used a temporary then write it to the device if (temporaryBitmap) dstDevice->writePixels(destBitmap, destX, destY); }