编译器
0.8.28+commit.7893614a
文件 1 的 8:BitmapImage.sol
pragma solidity ^0.8.28;
library BitmapImage {
uint256 private constant BMP_FILE_HEADER_BYTE_SIZE = 14;
uint256 private constant BMP_V5_HEADER_BYTE_SIZE = 124;
function generateBMP(uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixels)
internal
pure
returns (bytes memory bmpData)
{
bool isRGB = bitsPerPixel <= 24;
uint256 imageSize = _bmpImageSize(bitsPerPixel, width, height);
uint256 headerSize = BMP_FILE_HEADER_BYTE_SIZE + BMP_V5_HEADER_BYTE_SIZE;
bmpData = new bytes(headerSize + imageSize);
_writeBMPFileHeader(bmpData, bmpData.length, headerSize);
_writeCommonDIBHeader(
bmpData,
BMP_V5_HEADER_BYTE_SIZE,
imageSize,
isRGB ? 0 : 3,
0,
width,
height,
bitsPerPixel
);
_writeExtraDIBHeader(bmpData);
_writePixelData(bmpData, pixels, headerSize, width, height, bitsPerPixel >> 3);
return bmpData;
}
function _bmpImageSize(uint256 bitsPerPixel, uint256 width, uint256 height)
private
pure
returns (uint256)
{
unchecked {
uint256 bytesPerPixel = bitsPerPixel >> 3;
uint256 rowSize = width * bytesPerPixel;
return (rowSize + ((4 - (rowSize & 3)) & 3)) * height;
}
}
function _writeBMPFileHeader(bytes memory bmpData, uint256 fileSize, uint256 pixelOffset)
private
pure
{
assembly {
let ptr := add(bmpData, 32)
mstore8(ptr, 0x42)
mstore8(add(ptr, 1), 0x4D)
}
_writeUint32(bmpData, 2, fileSize);
_writeUint32(bmpData, 10, pixelOffset);
}
function _writeCommonDIBHeader(
bytes memory bmpData,
uint256 dibHeaderSize,
uint256 imageSize,
uint256 compressionOption,
uint256 paletteColorCount,
uint256 width,
uint256 height,
uint256 bitsPerPixel
) private pure {
_writeUint32(bmpData, 14, dibHeaderSize);
_writeUint32(bmpData, 18, width);
_writeUint32(bmpData, 22, height);
_writeUint16(bmpData, 26, 1);
_writeUint16(bmpData, 28, bitsPerPixel);
_writeUint32(bmpData, 30, compressionOption);
_writeUint32(bmpData, 34, imageSize);
_writeUint32(bmpData, 46, paletteColorCount);
}
function _writeExtraDIBHeader(bytes memory bmpData) private pure {
_writeUint32(bmpData, 54, 0x00FF0000);
_writeUint32(bmpData, 58, 0x0000FF00);
_writeUint32(bmpData, 62, 0x000000FF);
_writeUint32(bmpData, 66, 0xFF000000);
_writeUint32(bmpData, 70, 0x73524742);
}
function _writePixelData(
bytes memory bmpData,
bytes memory pixelBuffer,
uint256 pixelOffset,
uint256 width,
uint256 height,
uint256 bytesPerPixel
) private pure {
assembly {
let bytesPerRow := mul(width, bytesPerPixel)
let paddedBytesPerRow := add(bytesPerRow, and(sub(4, and(bytesPerRow, 3)), 3))
let bmpDataPtr := add(add(bmpData, 0x20), pixelOffset)
let pixelBufferPtr := add(pixelBuffer, 0x20)
let heightMinus1 := sub(height, 1)
for { let y := 0 } lt(y, height) { y := add(y, 1) } {
mcopy(
add(bmpDataPtr, mul(sub(heightMinus1, y), paddedBytesPerRow)),
add(pixelBufferPtr, mul(y, bytesPerRow)),
bytesPerRow
)
}
}
}
function _writeUint32(bytes memory data, uint256 offset, uint256 value) private pure {
assembly {
let ptr := add(add(data, 32), offset)
mstore8(ptr, value)
mstore8(add(ptr, 1), shr(8, value))
mstore8(add(ptr, 2), shr(16, value))
mstore8(add(ptr, 3), shr(24, value))
}
}
function _writeUint16(bytes memory data, uint256 offset, uint256 value) private pure {
assembly {
let ptr := add(add(data, 32), offset)
mstore8(ptr, value)
mstore8(add(ptr, 1), shr(8, value))
}
}
function _writeBytes(bytes memory data, uint256 offset, bytes memory value) private pure {
assembly {
mcopy(add(add(data, 32), offset), add(value, 32), mload(value))
}
}
}
文件 2 的 8:BitmapLayers.sol
pragma solidity ^0.8.28;
import {PixelLayerResolver} from "../PixelLayerResolver.sol";
contract BitmapLayers is PixelLayerResolver {}
文件 3 的 8:Multicallable.sol
pragma solidity ^0.8.4;
abstract contract Multicallable {
function multicall(bytes[] calldata data) public payable virtual returns (bytes[] memory) {
if (msg.value != 0) revert();
_multicallDirectReturn(_multicall(data));
}
function _multicall(bytes[] calldata data) internal virtual returns (bytes32 results) {
assembly {
results := mload(0x40)
mstore(results, 0x20)
mstore(add(0x20, results), data.length)
let c := add(0x40, results)
let s := c
let end := shl(5, data.length)
calldatacopy(c, data.offset, end)
end := add(c, end)
let m := end
if data.length {
for {} 1 {} {
let o := add(data.offset, mload(c))
calldatacopy(m, add(o, 0x20), calldataload(o))
if iszero(delegatecall(gas(), address(), m, calldataload(o), codesize(), 0x00)) {
returndatacopy(results, 0x00, returndatasize())
revert(results, returndatasize())
}
mstore(c, sub(m, s))
c := add(0x20, c)
mstore(m, returndatasize())
let b := add(m, 0x20)
returndatacopy(b, 0x00, returndatasize())
m := and(add(add(b, returndatasize()), 0x1f), 0xffffffffffffffe0)
mstore(add(b, returndatasize()), 0)
if iszero(lt(c, end)) { break }
}
}
mstore(0x40, m)
results := or(shl(64, m), results)
}
}
function _multicallResultsToBytesArray(bytes32 results)
internal
pure
virtual
returns (bytes[] memory decoded)
{
assembly {
decoded := mload(0x40)
let c := and(0xffffffffffffffff, results)
mstore(decoded, mload(add(c, 0x20)))
let o := add(decoded, 0x20)
let end := add(o, shl(5, mload(decoded)))
mstore(0x40, end)
let s := add(c, 0x40)
let d := sub(s, o)
for {} iszero(eq(o, end)) { o := add(o, 0x20) } { mstore(o, add(mload(add(d, o)), s)) }
}
}
function _multicallDirectReturn(bytes32 results) internal pure virtual {
assembly {
return(and(0xffffffffffffffff, results), shr(64, results))
}
}
}
文件 4 的 8:PaletteRegistry.sol
pragma solidity ^0.8.28;
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Multicallable} from "solady/utils/Multicallable.sol";
contract PaletteRegistry is Multicallable {
using SafeCast for uint256;
event PaletteCreated(
uint256 indexed paletteId,
string name,
uint256 bitsPerColor,
uint256 totalColors,
uint256 colorDataSize,
address creator
);
error InvalidColorBits();
error InvalidColorDataLength();
uint256 public constant BITS_PER_COLOR = 32;
struct Palette {
uint8 bitsPerColor;
uint32 totalColors;
string name;
bytes colors;
}
struct PaletteStorage {
uint32 lastPaletteId;
mapping(uint32 paletteId => Palette palette) palettes;
}
function _getPaletteStorage() internal pure virtual returns (PaletteStorage storage $) {
assembly {
$.slot := 0x3c1adc736457f7fc267f6a24936918f4a353929633e2a763879ceca772633200
}
}
function createPalette(string calldata name, uint8 bitsPerColor, bytes calldata colorData)
public
returns (uint256)
{
PaletteStorage storage $ = _getPaletteStorage();
uint256 paletteId = ++$.lastPaletteId;
Palette storage palette = $.palettes[uint32(paletteId)];
_setPalette(palette, name, bitsPerColor, colorData);
emit PaletteCreated(
paletteId,
name,
bitsPerColor,
(colorData.length / (bitsPerColor >> 3)),
colorData.length,
msg.sender
);
return paletteId;
}
function getPalettes(uint256[] calldata paletteIds)
public
view
returns (Palette[] memory palettes)
{
uint256 length = paletteIds.length;
palettes = new Palette[](length);
mapping(uint32 => Palette) storage _palettes = _getPaletteStorage().palettes;
for (uint256 i = 0; i < length; ++i) {
palettes[i] = _palettes[uint32(paletteIds[i])];
}
}
function getPalette(uint256 paletteId) public view returns (Palette memory) {
return _getPaletteStorage().palettes[uint32(paletteId)];
}
function lastPaletteId() public view returns (uint256) {
return _getPaletteStorage().lastPaletteId;
}
function _setPalette(
Palette storage palette,
string calldata name,
uint8 bitsPerColor,
bytes calldata colorData
) internal {
require(bitsPerColor == BITS_PER_COLOR, InvalidColorBits());
uint256 perColorBytesLen = bitsPerColor >> 3;
uint256 colorDataLength = colorData.length;
require(
colorDataLength > 0 && colorDataLength % perColorBytesLen == 0, InvalidColorDataLength()
);
if (bytes(name).length > 0) palette.name = name;
palette.bitsPerColor = bitsPerColor;
palette.totalColors = (colorDataLength / perColorBytesLen).toUint32();
palette.colors = colorData;
}
function _getPaletteColors(uint256 paletteId)
internal
view
returns (uint8 bitsPerColor, bytes memory paletteColors)
{
Palette storage palette = _getPaletteStorage().palettes[paletteId.toUint32()];
bitsPerColor = palette.bitsPerColor;
paletteColors = palette.colors;
}
}
文件 5 的 8:PixelLayerRegistry.sol
pragma solidity ^0.8.28;
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {Multicallable} from "solady/utils/Multicallable.sol";
contract PixelLayerRegistry is Multicallable {
using SafeCast for uint256;
event PixelLayerCreated(
uint256 indexed layerId,
string name,
uint256 zIndex,
uint256 bitsPerPixel,
uint256 width,
uint256 height,
RectRegion activeRegion,
uint256 regionPixelRefId,
uint256 bgColor,
uint256 paletteId,
address creator
);
event PixelDataCreated(uint256 indexed pixelRefId, uint256 pixelDataLength, bytes32 pixelHash);
error InvalidPaletteId();
error InvalidPixelBits();
error PixelLayerNotExists();
error InvalidPixelSize();
error InvalidLayerInactiveBgColor();
error InvalidLayerActiveRegionConfig();
uint32 public constant EMPTY_PIXEL_LAYER_ID = 0x0;
uint256 public constant MAX_BITS_PER_PIXEL = 32;
struct PixelData {
bytes data;
}
struct Layer {
uint8 zIndex;
uint8 bitsPerPixel;
uint16 width;
uint16 height;
uint16 xTL;
uint16 yTL;
uint16 xBR;
uint16 yBR;
uint32 pixelRefId;
uint32 bgColor;
uint32 paletteId;
string name;
}
struct PixelLayerStorage {
uint32 lastLayerId;
uint32 lastPixelRefId;
mapping(uint32 layerId => Layer layer) layers;
mapping(uint32 pixelRefId => PixelData pixelData) pixelDatas;
}
function _getLayerStorage() internal pure virtual returns (PixelLayerStorage storage $) {
assembly {
$.slot := 0x48829fddcf9497a4a949b434409eed16c5b73dbe348d10b9854adc250b08d400
}
}
struct RectRegion {
uint256 xTL;
uint256 yTL;
uint256 xBR;
uint256 yBR;
}
struct LayerParam {
string name;
uint256 zIndex;
uint256 bitsPerPixel;
uint256 width;
uint256 height;
}
function createLayer(LayerParam calldata layerParam, bytes calldata pixels, uint256 paletteId)
public
returns (uint256)
{
return createLayer(
layerParam, RectRegion(0, 0, layerParam.width, layerParam.height), 0, pixels, paletteId
);
}
function createLayer(
LayerParam calldata layerParam,
RectRegion memory regionParam,
uint256 bgcolorOrIndex,
bytes calldata pixels,
uint256 paletteId
) public returns (uint256) {
_checkLayerRegion(
regionParam,
bgcolorOrIndex,
layerParam.width,
layerParam.height,
layerParam.bitsPerPixel
);
_checkLayerData(
layerParam.bitsPerPixel,
regionParam.xBR - regionParam.xTL,
regionParam.yBR - regionParam.yTL,
pixels.length
);
require(paletteId > 0, InvalidPaletteId());
PixelLayerStorage storage $ = _getLayerStorage();
uint256 pixelRefId = _createPixelData($, pixels);
return _createLayer(layerParam, regionParam, bgcolorOrIndex, pixelRefId, paletteId);
}
function createLayer(LayerParam calldata layerParam, uint256 pixelRefId, uint256 paletteId)
public
returns (uint256)
{
return createLayer(
layerParam,
RectRegion(0, 0, layerParam.width, layerParam.height),
0,
pixelRefId,
paletteId
);
}
function createLayer(
LayerParam calldata layerParam,
RectRegion memory regionParam,
uint256 bgcolorOrIndex,
uint256 pixelRefId,
uint256 paletteId
) public returns (uint256) {
_checkLayerRegion(
regionParam,
bgcolorOrIndex,
layerParam.width,
layerParam.height,
layerParam.bitsPerPixel
);
_checkLayerData(
layerParam.bitsPerPixel,
regionParam.xBR - regionParam.xTL,
regionParam.yBR - regionParam.yTL,
_getPixelDataRef(_getLayerStorage(), pixelRefId.toUint32()).length
);
require(paletteId > 0, InvalidPaletteId());
return _createLayer(layerParam, regionParam, bgcolorOrIndex, pixelRefId, paletteId);
}
function createPixelData(bytes calldata pixels) public returns (uint256 pixelRefId) {
require(pixels.length > 0, InvalidPixelSize());
return _createPixelData(_getLayerStorage(), pixels);
}
function sortLayersByZIndex(uint256[] memory layerIds) public view returns (uint256[] memory) {
_sortLayersByZIndex(layerIds);
return layerIds;
}
function getLayers(uint256[] calldata layerIds) public view returns (Layer[] memory layers) {
uint256 length = layerIds.length;
layers = new Layer[](length);
mapping(uint32 => Layer) storage _layers = _getLayerStorage().layers;
for (uint256 i = 0; i < length; ++i) {
layers[i] = _layers[uint32(layerIds[i])];
}
}
function getLayer(uint256 layerId) public view returns (Layer memory layer) {
return _getLayerStorage().layers[uint32(layerId)];
}
function getPixelData(uint256 pixelRefId) public view returns (bytes memory) {
return _getPixelDataRef(_getLayerStorage(), pixelRefId.toUint32());
}
function lastLayerId() public view returns (uint256) {
return _getLayerStorage().lastLayerId;
}
function _sortLayersByZIndex(uint256[] memory layerIds) internal view {
mapping(uint32 => Layer) storage layers = _getLayerStorage().layers;
unchecked {
uint256 layerCount = _loadMemoryArray(layerIds, 0);
if (layerCount > type(uint32).max) {
revert SafeCast.SafeCastOverflowedUintDowncast(32, layerCount);
}
layerCount = layerIds.length;
for (uint256 i = 1; i < layerCount; ++i) {
uint32 key = _loadMemoryArray(layerIds, i).toUint32();
require(layers[key].bitsPerPixel > 0, PixelLayerNotExists());
uint256 keyZIndex = layers[key].zIndex;
uint256 j = i;
while (
j > 0 && layers[uint32(_loadMemoryArray(layerIds, j - 1))].zIndex > keyZIndex
) {
_storeMemoryArray(layerIds, j, _loadMemoryArray(layerIds, j - 1));
--j;
}
_storeMemoryArray(layerIds, j, key);
}
}
}
function _createLayer(
LayerParam calldata layerParam,
RectRegion memory regionParam,
uint256 bgcolorOrIndex,
uint256 pixelRefId,
uint256 paletteId
) internal returns (uint256 layerId) {
{
PixelLayerStorage storage $ = _getLayerStorage();
layerId = ++$.lastLayerId;
Layer storage layer = $.layers[uint32(layerId)];
if (bytes(layerParam.name).length > 0) {
layer.name = layerParam.name;
}
layer.zIndex = layerParam.zIndex.toUint8();
layer.bitsPerPixel = layerParam.bitsPerPixel.toUint8();
layer.width = layerParam.width.toUint16();
layer.height = layerParam.height.toUint16();
layer.xTL = regionParam.xTL.toUint16();
layer.yTL = regionParam.yTL.toUint16();
layer.xBR = regionParam.xBR.toUint16();
layer.yBR = regionParam.yBR.toUint16();
layer.bgColor = bgcolorOrIndex.toUint32();
layer.paletteId = paletteId.toUint32();
layer.pixelRefId = pixelRefId.toUint32();
}
emit PixelLayerCreated(
layerId,
layerParam.name,
layerParam.zIndex,
layerParam.bitsPerPixel,
layerParam.width,
layerParam.height,
regionParam,
pixelRefId,
bgcolorOrIndex,
paletteId,
msg.sender
);
}
function _createPixelData(PixelLayerStorage storage $, bytes calldata pixels)
internal
returns (uint256 pixelRefId)
{
pixelRefId = ++$.lastPixelRefId;
$.pixelDatas[uint32(pixelRefId)].data = pixels;
emit PixelDataCreated(pixelRefId, pixels.length, keccak256(pixels));
}
function _getPixelDataRef(PixelLayerStorage storage $, uint32 pixelRefId)
internal
view
returns (bytes storage pixelData)
{
return $.pixelDatas[pixelRefId].data;
}
function _checkLayerData(
uint256 bitsPerPixel,
uint256 width,
uint256 height,
uint256 pixelBytes
) internal pure {
require(
0 < bitsPerPixel && bitsPerPixel <= MAX_BITS_PER_PIXEL
&& _isValidBitsPerPixel(bitsPerPixel),
InvalidPixelBits()
);
uint256 totalBits = width * height * bitsPerPixel;
uint256 expectedBytes = (totalBits + 7) >> 3;
require(pixelBytes == expectedBytes, InvalidPixelSize());
}
function _checkLayerRegion(
RectRegion memory param,
uint256 bgColorOrIndex,
uint256 layerWidth,
uint256 layerHeight,
uint256 bitsPerPixel
) internal pure {
require(
param.xTL <= param.xBR && param.xBR <= layerWidth && param.yTL <= param.yBR
&& param.yBR <= layerHeight,
InvalidLayerActiveRegionConfig()
);
require(bgColorOrIndex <= ((1 << bitsPerPixel) - 1), InvalidLayerInactiveBgColor());
}
function _isValidBitsPerPixel(uint256 bitsPerPixel) internal pure returns (bool isValid) {
assembly ("memory-safe") {
let validMask := 0x101010116
isValid := and(shr(bitsPerPixel, validMask), 1)
}
}
struct LayerRegionInfo {
uint256 xTL;
uint256 yTL;
uint256 xBR;
uint256 yBR;
uint256 inactiveBgColor;
uint256 regionWidth;
uint256 layerWidth;
uint256 layerHeight;
}
function _getLayerInner(uint256 layerId)
internal
view
returns (
uint256 bitsPerPixel,
LayerRegionInfo memory region,
uint256 paletteId,
bytes memory pixels
)
{
PixelLayerStorage storage $ = _getLayerStorage();
Layer storage l = $.layers[uint32(layerId)];
bitsPerPixel = l.bitsPerPixel;
region.layerWidth = l.width;
region.layerHeight = l.height;
region.xTL = l.xTL;
region.yTL = l.yTL;
region.xBR = l.xBR;
region.yBR = l.yBR;
region.inactiveBgColor = l.bgColor;
region.regionWidth = region.xBR - region.xTL;
paletteId = l.paletteId;
pixels = _getPixelDataRef($, l.pixelRefId);
}
function _loadMemoryArray(uint256[] memory arr, uint256 index)
internal
pure
returns (uint256 val)
{
assembly {
val := mload(add(add(arr, 0x20), shl(5, index)))
}
}
function _storeMemoryArray(uint256[] memory arr, uint256 index, uint256 val) internal pure {
assembly {
mstore(add(add(arr, 0x20), shl(5, index)), val)
}
}
}
文件 6 的 8:PixelLayerResolver.sol
pragma solidity ^0.8.28;
import {PaletteRegistry} from "./PaletteRegistry.sol";
import {PixelLayerRegistry} from "./PixelLayerRegistry.sol";
import {BitmapImage} from "./library/BitmapImage.sol";
import {SVGImage} from "./library/SVGImage.sol";
contract PixelLayerResolver is PaletteRegistry, PixelLayerRegistry {
error InvalidLayerIdsLength();
error InvalidColorBitDepth();
struct PaletteParam {
string name;
uint8 bitsPerColor;
bytes colorData;
}
struct LayerAndPixelParam {
LayerParam layer;
RectRegion regionParam;
uint256 bgcolorOrIndex;
bytes pixels;
}
struct LayerAndPixelRefParam {
LayerParam layer;
RectRegion regionParam;
uint256 bgcolorOrIndex;
uint256 pixelRefId;
}
function createPaletteAndLayer(
PaletteParam calldata palette,
LayerAndPixelParam[] calldata param1,
LayerAndPixelRefParam[] calldata param2
)
public
returns (uint256 paletteId, uint256[] memory layerIds, uint256[] memory layerWithRefIds)
{
paletteId = createPalette(palette.name, palette.bitsPerColor, palette.colorData);
{
uint256 layerCount = param1.length;
layerIds = new uint256[](layerCount);
for (uint256 i = 0; i < layerCount; ++i) {
LayerAndPixelParam calldata param = param1[i];
layerIds[i] = createLayer(
param.layer, param.regionParam, param.bgcolorOrIndex, param.pixels, paletteId
);
}
}
{
uint256 layerCount = param2.length;
layerWithRefIds = new uint256[](layerCount);
for (uint256 i = 0; i < layerCount; ++i) {
LayerAndPixelRefParam calldata param = param2[i];
layerWithRefIds[i] = createLayer(
param.layer,
param.regionParam,
param.bgcolorOrIndex,
param.pixelRefId,
paletteId
);
}
}
}
function genBMPFromLayers(uint256[] memory layerIds) public view returns (bytes memory bmp) {
(uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixelBuffer) =
compositeLayers(layerIds);
return BitmapImage.generateBMP(bitsPerPixel, width, height, pixelBuffer);
}
function genSVGFromLayers(uint256[] memory layerIds) public view returns (bytes memory svg) {
(uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixelBuffer) =
compositeLayers(layerIds);
return bytes(SVGImage.generateSVG(bitsPerPixel, width, height, pixelBuffer));
}
function compositeLayers(uint256[] memory layerIds)
public
view
returns (uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixelBuffer)
{
uint256 layerCount = layerIds.length;
require(layerCount > 0, InvalidLayerIdsLength());
_sortLayersByZIndex(layerIds);
uint256 paletteId;
uint256 bitsPerLayerPixel;
bytes memory pixelIdx;
bytes memory palette;
LayerRegionInfo memory region;
(bitsPerLayerPixel, region, paletteId, pixelIdx) = _getLayerInner(layerIds[0]);
width = region.layerWidth;
height = region.layerHeight;
(bitsPerPixel, palette) = _getPaletteColors(paletteId);
unchecked {
pixelBuffer = new bytes(width * height * (bitsPerPixel >> 3));
if (region.xTL == 0 && region.yTL == 0 && region.xBR == width && region.yBR == height) {
_compositeLayerWithPalette(
pixelBuffer, palette, pixelIdx, bitsPerPixel, bitsPerLayerPixel
);
} else {
_compositeLayerBG(pixelBuffer, palette, bitsPerPixel, region);
_compositeActiveRegion(
pixelBuffer, palette, pixelIdx, bitsPerPixel, bitsPerLayerPixel, region
);
}
for (uint256 i = 1; i < layerCount; ++i) {
uint256 tmpUint;
(bitsPerLayerPixel, region, tmpUint, pixelIdx) = _getLayerInner(layerIds[i]);
if (tmpUint != paletteId) {
paletteId = tmpUint;
(tmpUint, palette) = _getPaletteColors(paletteId);
require(tmpUint == bitsPerPixel, InvalidColorBitDepth());
}
if (
region.xTL == 0 && region.yTL == 0 && region.xBR == width
&& region.yBR == height
) {
_compositeLayerWithPalette(
pixelBuffer, palette, pixelIdx, bitsPerPixel, bitsPerLayerPixel
);
} else {
_compositeLayerBG(pixelBuffer, palette, bitsPerPixel, region);
_compositeActiveRegion(
pixelBuffer, palette, pixelIdx, bitsPerPixel, bitsPerLayerPixel, region
);
}
}
}
}
function _compositeLayerWithPalette(
bytes memory pixelBuffer,
bytes memory palette,
bytes memory pixelIndex,
uint256 bitsPerColor,
uint256 bitsPerPixel
) internal pure {
unchecked {
uint256 pixelCount;
uint256 colorMask;
uint256 pixelIndexMask;
assembly ("memory-safe") {
pixelCount := div(mload(pixelBuffer), shr(3, bitsPerColor))
pixelIndexMask := sub(shl(bitsPerPixel, 1), 1)
colorMask := sub(shl(bitsPerColor, 1), 1)
}
for (uint256 i = 0; i < pixelCount; ++i) {
uint256 tmpUint;
uint256 fgColor;
assembly {
let elemStartBit := mul(i, bitsPerPixel)
let data := mload(add(add(pixelIndex, 0x20), shr(3, elemStartBit)))
data := shr(sub(256, add(bitsPerPixel, and(elemStartBit, 7))), data)
elemStartBit := mul(and(data, pixelIndexMask), bitsPerColor)
data := mload(add(add(palette, 0x20), shr(3, elemStartBit)))
data := shr(sub(256, add(bitsPerColor, and(elemStartBit, 7))), data)
fgColor := and(data, colorMask)
}
uint256 alpha = fgColor & 0xFF;
if (alpha == 0) continue;
uint256 bgColorOffset;
uint256 bgColorWordShiftCount;
assembly {
tmpUint := mul(i, bitsPerColor)
bgColorWordShiftCount := sub(256, add(bitsPerColor, and(tmpUint, 7)))
bgColorOffset := add(add(pixelBuffer, 0x20), shr(3, tmpUint))
tmpUint := mload(bgColorOffset)
}
if (alpha < 255) {
uint256 bgColor;
assembly {
bgColor := and(shr(bgColorWordShiftCount, tmpUint), colorMask)
}
fgColor = _blendBGRA(fgColor, bgColor, alpha);
}
assembly {
let mask := shl(bgColorWordShiftCount, colorMask)
let shifted := shl(bgColorWordShiftCount, fgColor)
let current := and(tmpUint, not(mask))
mstore(bgColorOffset, or(current, shifted))
}
}
}
}
function _compositeActiveRegion(
bytes memory pixelBuffer,
bytes memory palette,
bytes memory pixelIndex,
uint256 bitsPerColor,
uint256 bitsPerPixel,
LayerRegionInfo memory region
) internal pure {
unchecked {
uint256 colorMask;
uint256 pixelIndexMask;
assembly ("memory-safe") {
pixelIndexMask := sub(shl(bitsPerPixel, 1), 1)
colorMask := sub(shl(bitsPerColor, 1), 1)
mstore(0x00, 0)
}
while (region.yTL < region.yBR) {
uint256 rowStart = region.yTL * region.layerWidth + region.xTL;
uint256 rowEnd = rowStart + region.regionWidth;
while (rowStart < rowEnd) {
uint256 fgColor;
assembly {
let elemStartBit := mul(mload(0x00), bitsPerPixel)
let data := mload(add(add(pixelIndex, 0x20), shr(3, elemStartBit)))
data := shr(sub(256, add(bitsPerPixel, and(elemStartBit, 7))), data)
elemStartBit := mul(and(data, pixelIndexMask), bitsPerColor)
data := mload(add(add(palette, 0x20), shr(3, elemStartBit)))
data := shr(sub(256, add(bitsPerColor, and(elemStartBit, 7))), data)
fgColor := and(data, colorMask)
}
if ((fgColor & 0xFF) == 0) {
assembly {
mstore(0x00, add(mload(0x00), 1))
rowStart := add(rowStart, 1)
}
continue;
}
uint256 bgShift;
uint256 bgOffset;
assembly {
let bufStartBit := mul(rowStart, bitsPerColor)
bgShift := sub(256, add(bitsPerColor, and(bufStartBit, 7)))
bgOffset := add(add(pixelBuffer, 0x20), shr(3, bufStartBit))
}
if ((fgColor & 0xFF) < 255) {
uint256 bgColor;
assembly {
bgColor := and(shr(bgShift, mload(bgOffset)), colorMask)
}
fgColor = _blendBGRA(fgColor, bgColor, fgColor & 0xFF);
}
assembly {
let mask := shl(bgShift, colorMask)
let current := and(mload(bgOffset), not(mask))
mstore(bgOffset, or(current, shl(bgShift, fgColor)))
}
assembly {
mstore(0x00, add(mload(0x00), 1))
rowStart := add(rowStart, 1)
}
}
++region.yTL;
}
}
}
function _compositeLayerBG(
bytes memory pixelBuffer,
bytes memory palette,
uint256 bitsPerColor,
LayerRegionInfo memory region
) internal pure {
uint256 layerBgColor = region.inactiveBgColor;
assembly {
let elemStartBit := mul(layerBgColor, bitsPerColor)
let data := mload(add(add(palette, 0x20), shr(3, elemStartBit)))
data := shr(sub(256, add(bitsPerColor, and(elemStartBit, 7))), data)
layerBgColor := and(data, sub(shl(bitsPerColor, 1), 1))
}
if (region.yTL > 0) {
_compositeLayerRectBG(
pixelBuffer,
layerBgColor,
bitsPerColor,
LayerRegionInfo({
xTL: 0,
yTL: 0,
xBR: region.layerWidth,
yBR: region.yTL,
regionWidth: region.layerWidth,
layerWidth: region.layerWidth,
layerHeight: 0,
inactiveBgColor: 0
})
);
}
if (region.yBR < region.layerHeight) {
_compositeLayerRectBG(
pixelBuffer,
layerBgColor,
bitsPerColor,
LayerRegionInfo({
xTL: 0,
yTL: region.yBR,
xBR: region.layerWidth,
yBR: region.layerHeight,
regionWidth: region.layerWidth,
layerWidth: region.layerWidth,
layerHeight: 0,
inactiveBgColor: 0
})
);
}
if (region.xTL > 0) {
_compositeLayerRectBG(
pixelBuffer,
layerBgColor,
bitsPerColor,
LayerRegionInfo({
xTL: 0,
yTL: region.yTL,
xBR: region.xTL,
yBR: region.yBR,
regionWidth: region.xTL,
layerWidth: region.layerWidth,
layerHeight: 0,
inactiveBgColor: 0
})
);
}
if (region.xBR < region.layerWidth) {
_compositeLayerRectBG(
pixelBuffer,
layerBgColor,
bitsPerColor,
LayerRegionInfo({
xTL: region.xBR,
yTL: region.yTL,
xBR: region.layerWidth,
yBR: region.yBR,
regionWidth: region.layerWidth - region.xBR,
layerWidth: region.layerWidth,
layerHeight: 0,
inactiveBgColor: 0
})
);
}
}
function _compositeLayerRectBG(
bytes memory pixelBuffer,
uint256 layerBgColor,
uint256 bitsPerColor,
LayerRegionInfo memory region
) internal pure {
unchecked {
uint256 colorMask = (1 << bitsPerColor) - 1;
uint256 alpha = layerBgColor & 0xFF;
if (alpha == 0) return;
for (uint256 y = region.yTL; y < region.yBR; ++y) {
uint256 rowStart = y * region.layerWidth + region.xTL;
uint256 rowEnd = rowStart + region.regionWidth;
if (alpha == 255) {
while (rowStart < rowEnd) {
assembly {
let bufStartBit := mul(rowStart, bitsPerColor)
let shift := sub(256, add(bitsPerColor, and(bufStartBit, 7)))
let targetOffset := add(add(pixelBuffer, 0x20), shr(3, bufStartBit))
let mask := shl(shift, colorMask)
let current := and(mload(targetOffset), not(mask))
mstore(targetOffset, or(current, shl(shift, layerBgColor)))
}
++rowStart;
}
} else {
while (rowStart < rowEnd) {
uint256 bgShift;
uint256 bgOffset;
uint256 bgWord;
assembly {
let bufStartBit := mul(rowStart, bitsPerColor)
bgShift := sub(256, add(bitsPerColor, and(bufStartBit, 7)))
bgOffset := add(add(pixelBuffer, 0x20), shr(3, bufStartBit))
bgWord := mload(bgOffset)
}
uint256 newColor =
_blendBGRA(layerBgColor, (bgWord >> bgShift) & colorMask, alpha);
assembly {
let mask := shl(bgShift, colorMask)
let current := and(bgWord, not(mask))
mstore(bgOffset, or(current, shl(bgShift, newColor)))
}
++rowStart;
}
}
}
}
}
function _blendBGRA(uint256 fgColor, uint256 bgColor, uint256 fgAlpha)
internal
pure
returns (uint256)
{
assembly ("memory-safe") {
let w2 := sub(255, fgAlpha)
let b :=
shr(
8,
add(mul(and(shr(24, fgColor), 0xff), fgAlpha), mul(and(shr(24, bgColor), 0xff), w2))
)
let g :=
shr(
8,
add(mul(and(shr(16, fgColor), 0xff), fgAlpha), mul(and(shr(16, bgColor), 0xff), w2))
)
let r :=
shr(
8,
add(mul(and(shr(8, fgColor), 0xff), fgAlpha), mul(and(shr(8, bgColor), 0xff), w2))
)
fgColor := or(or(or(shl(24, b), shl(16, g)), shl(8, r)), fgAlpha)
}
return fgColor;
}
}
文件 7 的 8:SVGImage.sol
pragma solidity ^0.8.28;
library SVGImage {
function generateSVG(uint256 bitsPerPixel, uint256 width, uint256 height, bytes memory pixels)
internal
pure
returns (string memory svg)
{
uint256 ptr;
assembly {
svg := mload(0x40)
ptr := add(svg, 0x20)
mstore(0x0f, 0x30313233343536373839616263646566)
}
ptr = _writeSVGHeader(ptr, width, height);
unchecked {
uint256 colorMask = (1 << bitsPerPixel) - 1;
for (uint256 y = 0; y < height; ++y) {
uint256 startX;
uint256 currentColor = type(uint256).max;
uint256 basePixelOffset = y * width;
for (uint256 x = 0; x < width; ++x) {
uint256 color = _getPixel(pixels, colorMask, bitsPerPixel, basePixelOffset + x);
if (uint8(color) == 0) {
if (currentColor < type(uint256).max) {
ptr = _writePath(ptr, startX, y, x - startX, currentColor);
currentColor = type(uint256).max;
}
startX = x + 1;
continue;
}
if (currentColor == type(uint256).max) {
currentColor = color;
startX = x;
} else if (color != currentColor) {
ptr = _writePath(ptr, startX, y, x - startX, currentColor);
currentColor = color;
startX = x;
}
}
if (currentColor < type(uint256).max && startX < width) {
ptr = _writePath(ptr, startX, y, width - startX, currentColor);
}
}
}
assembly {
mstore(ptr, 0x3c2f7376673e0000000000000000000000000000000000000000000000000000)
ptr := add(ptr, 6)
let length := sub(ptr, add(svg, 0x20))
mstore(svg, length)
let padding := and(sub(32, and(ptr, 31)), 31)
mstore(0x40, add(ptr, padding))
}
}
function _writeSVGHeader(uint256 ptr, uint256 width, uint256 height)
private
pure
returns (uint256)
{
assembly {
mstore(ptr, 0x3c7376672073686170652d72656e646572696e673d2263726973704564676573)
ptr := add(ptr, 32)
mstore(ptr, 0x222077696474683d220000000000000000000000000000000000000000000000)
ptr := add(ptr, 9)
}
ptr = _writeUint(ptr, width);
assembly {
mstore(ptr, 0x22206865696768743d2200000000000000000000000000000000000000000000)
ptr := add(ptr, 10)
}
ptr = _writeUint(ptr, height);
assembly {
mstore(ptr, 0x222076696577426f783d22302030200000000000000000000000000000000000)
ptr := add(ptr, 15)
}
ptr = _writeUint(ptr, width);
assembly {
mstore8(ptr, 0x20)
ptr := add(ptr, 1)
}
ptr = _writeUint(ptr, height);
assembly {
mstore(ptr, 0x2220786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323030302f)
ptr := add(ptr, 32)
mstore(ptr, 0x737667223e000000000000000000000000000000000000000000000000000000)
ptr := add(ptr, 5)
}
return ptr;
}
function _writePath(uint256 ptr, uint256 x, uint256 y, uint256 width, uint256 color)
private
pure
returns (uint256)
{
assembly {
mstore(ptr, 0x3c7061746820643d224d00000000000000000000000000000000000000000000)
ptr := add(ptr, 10)
}
ptr = _writeUint(ptr, x);
assembly {
mstore8(ptr, 0x20)
ptr := add(ptr, 1)
}
ptr = _writeUint(ptr, y);
assembly {
mstore(ptr, 0x7631680000000000000000000000000000000000000000000000000000000000)
ptr := add(ptr, 3)
}
ptr = _writeUint(ptr, width);
assembly {
mstore(ptr, 0x762d31222066696c6c3d22230000000000000000000000000000000000000000)
ptr := add(ptr, 12)
}
{
uint256 b = uint8(color >> 24);
uint256 g = uint8(color >> 16);
uint256 r = uint8(color >> 8);
uint256 a = uint8(color);
ptr = _writeUintHex(ptr, (r << 24) | (g << 16) | (b << 8) | a, 8);
}
assembly {
mstore(ptr, 0x222f3e0000000000000000000000000000000000000000000000000000000000)
ptr := add(ptr, 3)
}
return ptr;
}
function _writeUintHex(uint256 ptr, uint256 value, uint256 hexLength)
private
pure
returns (uint256)
{
assembly {
let end := add(ptr, hexLength)
let result := end
for {} 1 {} {
result := sub(result, 2)
mstore8(add(result, 1), mload(and(value, 15)))
mstore8(result, mload(and(shr(4, value), 15)))
value := shr(8, value)
if iszero(xor(result, ptr)) { break }
}
ptr := end
}
return ptr;
}
function _writeUint(uint256 ptr, uint256 value) private pure returns (uint256) {
assembly {
let len := 1
let v := div(value, 10)
for {} v {} {
len := add(len, 1)
v := div(v, 10)
}
v := add(ptr, len)
for { let end := v } 1 {} {
end := sub(end, 1)
mstore8(end, add(48, mod(value, 10)))
value := div(value, 10)
if iszero(value) { break }
}
ptr := v
}
return ptr;
}
function _getPixel(bytes memory pixels, uint256 pixelMask, uint256 bitsPerPixel, uint256 index)
private
pure
returns (uint256 result)
{
assembly ("memory-safe") {
let elemStartBit := mul(index, bitsPerPixel)
let data := mload(add(add(pixels, 0x20), shr(3, elemStartBit)))
data := shr(sub(256, add(bitsPerPixel, and(elemStartBit, 7))), data)
result := and(data, pixelMask)
}
}
}
文件 8 的 8:SafeCast.sol
pragma solidity ^0.8.20;
library SafeCast {
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
error SafeCastOverflowedIntToUint(int256 value);
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
error SafeCastOverflowedUintToInt(uint256 value);
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
function toInt256(uint256 value) internal pure returns (int256) {
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}
{
"compilationTarget": {
"src/bitmap-punk/BitmapLayers.sol": "BitmapLayers"
},
"evmVersion": "cancun",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 1000
},
"remappings": [
":@openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":@openzeppelin/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
":@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
":ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
":openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
":solady/=lib/solady/src/"
]
}
[{"inputs":[],"name":"InvalidColorBitDepth","type":"error"},{"inputs":[],"name":"InvalidColorBits","type":"error"},{"inputs":[],"name":"InvalidColorDataLength","type":"error"},{"inputs":[],"name":"InvalidLayerActiveRegionConfig","type":"error"},{"inputs":[],"name":"InvalidLayerIdsLength","type":"error"},{"inputs":[],"name":"InvalidLayerInactiveBgColor","type":"error"},{"inputs":[],"name":"InvalidPaletteId","type":"error"},{"inputs":[],"name":"InvalidPixelBits","type":"error"},{"inputs":[],"name":"InvalidPixelSize","type":"error"},{"inputs":[],"name":"PixelLayerNotExists","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"paletteId","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"bitsPerColor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"totalColors","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"colorDataSize","type":"uint256"},{"indexed":false,"internalType":"address","name":"creator","type":"address"}],"name":"PaletteCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"pixelRefId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"pixelDataLength","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"pixelHash","type":"bytes32"}],"name":"PixelDataCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"layerId","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"uint256","name":"zIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"width","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"height","type":"uint256"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"indexed":false,"internalType":"struct PixelLayerRegistry.RectRegion","name":"activeRegion","type":"tuple"},{"indexed":false,"internalType":"uint256","name":"regionPixelRefId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bgColor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"paletteId","type":"uint256"},{"indexed":false,"internalType":"address","name":"creator","type":"address"}],"name":"PixelLayerCreated","type":"event"},{"inputs":[],"name":"BITS_PER_COLOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EMPTY_PIXEL_LAYER_ID","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BITS_PER_PIXEL","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"compositeLayers","outputs":[{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"},{"internalType":"bytes","name":"pixelBuffer","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layerParam","type":"tuple"},{"internalType":"bytes","name":"pixels","type":"bytes"},{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"createLayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layerParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"internalType":"struct PixelLayerRegistry.RectRegion","name":"regionParam","type":"tuple"},{"internalType":"uint256","name":"bgcolorOrIndex","type":"uint256"},{"internalType":"uint256","name":"pixelRefId","type":"uint256"},{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"createLayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layerParam","type":"tuple"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"internalType":"struct PixelLayerRegistry.RectRegion","name":"regionParam","type":"tuple"},{"internalType":"uint256","name":"bgcolorOrIndex","type":"uint256"},{"internalType":"bytes","name":"pixels","type":"bytes"},{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"createLayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layerParam","type":"tuple"},{"internalType":"uint256","name":"pixelRefId","type":"uint256"},{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"createLayer","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint8","name":"bitsPerColor","type":"uint8"},{"internalType":"bytes","name":"colorData","type":"bytes"}],"name":"createPalette","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint8","name":"bitsPerColor","type":"uint8"},{"internalType":"bytes","name":"colorData","type":"bytes"}],"internalType":"struct PixelLayerResolver.PaletteParam","name":"palette","type":"tuple"},{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layer","type":"tuple"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"internalType":"struct PixelLayerRegistry.RectRegion","name":"regionParam","type":"tuple"},{"internalType":"uint256","name":"bgcolorOrIndex","type":"uint256"},{"internalType":"bytes","name":"pixels","type":"bytes"}],"internalType":"struct PixelLayerResolver.LayerAndPixelParam[]","name":"param1","type":"tuple[]"},{"components":[{"components":[{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"zIndex","type":"uint256"},{"internalType":"uint256","name":"bitsPerPixel","type":"uint256"},{"internalType":"uint256","name":"width","type":"uint256"},{"internalType":"uint256","name":"height","type":"uint256"}],"internalType":"struct PixelLayerRegistry.LayerParam","name":"layer","type":"tuple"},{"components":[{"internalType":"uint256","name":"xTL","type":"uint256"},{"internalType":"uint256","name":"yTL","type":"uint256"},{"internalType":"uint256","name":"xBR","type":"uint256"},{"internalType":"uint256","name":"yBR","type":"uint256"}],"internalType":"struct PixelLayerRegistry.RectRegion","name":"regionParam","type":"tuple"},{"internalType":"uint256","name":"bgcolorOrIndex","type":"uint256"},{"internalType":"uint256","name":"pixelRefId","type":"uint256"}],"internalType":"struct PixelLayerResolver.LayerAndPixelRefParam[]","name":"param2","type":"tuple[]"}],"name":"createPaletteAndLayer","outputs":[{"internalType":"uint256","name":"paletteId","type":"uint256"},{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"},{"internalType":"uint256[]","name":"layerWithRefIds","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"pixels","type":"bytes"}],"name":"createPixelData","outputs":[{"internalType":"uint256","name":"pixelRefId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"genBMPFromLayers","outputs":[{"internalType":"bytes","name":"bmp","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"genSVGFromLayers","outputs":[{"internalType":"bytes","name":"svg","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"layerId","type":"uint256"}],"name":"getLayer","outputs":[{"components":[{"internalType":"uint8","name":"zIndex","type":"uint8"},{"internalType":"uint8","name":"bitsPerPixel","type":"uint8"},{"internalType":"uint16","name":"width","type":"uint16"},{"internalType":"uint16","name":"height","type":"uint16"},{"internalType":"uint16","name":"xTL","type":"uint16"},{"internalType":"uint16","name":"yTL","type":"uint16"},{"internalType":"uint16","name":"xBR","type":"uint16"},{"internalType":"uint16","name":"yBR","type":"uint16"},{"internalType":"uint32","name":"pixelRefId","type":"uint32"},{"internalType":"uint32","name":"bgColor","type":"uint32"},{"internalType":"uint32","name":"paletteId","type":"uint32"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct PixelLayerRegistry.Layer","name":"layer","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"getLayers","outputs":[{"components":[{"internalType":"uint8","name":"zIndex","type":"uint8"},{"internalType":"uint8","name":"bitsPerPixel","type":"uint8"},{"internalType":"uint16","name":"width","type":"uint16"},{"internalType":"uint16","name":"height","type":"uint16"},{"internalType":"uint16","name":"xTL","type":"uint16"},{"internalType":"uint16","name":"yTL","type":"uint16"},{"internalType":"uint16","name":"xBR","type":"uint16"},{"internalType":"uint16","name":"yBR","type":"uint16"},{"internalType":"uint32","name":"pixelRefId","type":"uint32"},{"internalType":"uint32","name":"bgColor","type":"uint32"},{"internalType":"uint32","name":"paletteId","type":"uint32"},{"internalType":"string","name":"name","type":"string"}],"internalType":"struct PixelLayerRegistry.Layer[]","name":"layers","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"paletteId","type":"uint256"}],"name":"getPalette","outputs":[{"components":[{"internalType":"uint8","name":"bitsPerColor","type":"uint8"},{"internalType":"uint32","name":"totalColors","type":"uint32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"bytes","name":"colors","type":"bytes"}],"internalType":"struct PaletteRegistry.Palette","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"paletteIds","type":"uint256[]"}],"name":"getPalettes","outputs":[{"components":[{"internalType":"uint8","name":"bitsPerColor","type":"uint8"},{"internalType":"uint32","name":"totalColors","type":"uint32"},{"internalType":"string","name":"name","type":"string"},{"internalType":"bytes","name":"colors","type":"bytes"}],"internalType":"struct PaletteRegistry.Palette[]","name":"palettes","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"pixelRefId","type":"uint256"}],"name":"getPixelData","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastLayerId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastPaletteId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"layerIds","type":"uint256[]"}],"name":"sortLayersByZIndex","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"}]