blob: 7a413121a2de63a7041d10d27571fa4f2053b42c [file] [log] [blame]
import 'dart:typed_data';
import 'pvrtc_bit_utility.dart';
import 'pvrtc_color.dart';
/// Ported from Jeffrey Lim's PVRTC encoder/decoder,
/// https://bitbucket.org/jthlim/pvrtccompressor
class PvrtcPacket {
Uint32List rawData;
int index;
PvrtcPacket(TypedData data) : rawData = Uint32List.view(data.buffer);
void setBlock(int x, int y) => setIndex(_getMortonNumber(x, y));
void setIndex(int i) {
// A PvrtcPacket uses 2 uint32 values, so get the physical index
// from the logical index by multiplying by 2.
index = i << 1;
// Pull in the values from the raw data.
_update();
}
int get modulationData => rawData[index];
set modulationData(int x) => rawData[index] = x;
int get colorData => rawData[index + 1];
set colorData(int x) => rawData[index + 1] = x;
int get usePunchthroughAlpha => _usePunchthroughAlpha;
set usePunchthroughAlpha(int x) {
_usePunchthroughAlpha = x;
colorData = _getColorData();
}
int get colorA => _colorA;
set colorA(int x) {
_colorA = x;
colorData = _getColorData();
}
int get colorAIsOpaque => _colorAIsOpaque;
set colorAIsOpaque(int x) {
_colorAIsOpaque = x;
colorData = _getColorData();
}
int get colorB => _colorB;
set colorB(int x) {
_colorB = x;
colorData = _getColorData();
}
int get colorBIsOpaque => _colorBIsOpaque;
set colorBIsOpaque(int x) {
_colorBIsOpaque = x;
colorData = _getColorData();
}
void setColorRgbA(PvrtcColorRgb c) {
int r = BitUtility.BITSCALE_8_TO_5_FLOOR[c.r];
int g = BitUtility.BITSCALE_8_TO_5_FLOOR[c.g];
int b = BitUtility.BITSCALE_8_TO_4_FLOOR[c.b];
colorA = r << 9 | g << 4 | b;
colorAIsOpaque = 1;
}
void setColorRgbaA(PvrtcColorRgba c) {
int a = BitUtility.BITSCALE_8_TO_3_FLOOR[c.a];
if (a == 7) {
int r = BitUtility.BITSCALE_8_TO_5_FLOOR[c.r];
int g = BitUtility.BITSCALE_8_TO_5_FLOOR[c.g];
int b = BitUtility.BITSCALE_8_TO_4_FLOOR[c.b];
colorA = r << 9 | g << 4 | b;
colorAIsOpaque = 1;
} else {
int r = BitUtility.BITSCALE_8_TO_4_FLOOR[c.r];
int g = BitUtility.BITSCALE_8_TO_4_FLOOR[c.g];
int b = BitUtility.BITSCALE_8_TO_3_FLOOR[c.b];
colorA = a << 11 | r << 7 | g << 3 | b;
colorAIsOpaque = 0;
}
}
void setColorRgbB(PvrtcColorRgb c) {
int r = BitUtility.BITSCALE_8_TO_5_CEIL[c.r];
int g = BitUtility.BITSCALE_8_TO_5_CEIL[c.g];
int b = BitUtility.BITSCALE_8_TO_5_CEIL[c.b];
colorB = r << 10 | g << 5 | b;
colorBIsOpaque = 1;
}
void setColorRgbaB(PvrtcColorRgba c) {
int a = BitUtility.BITSCALE_8_TO_3_CEIL[c.a];
if (a == 7) {
int r = BitUtility.BITSCALE_8_TO_5_CEIL[c.r];
int g = BitUtility.BITSCALE_8_TO_5_CEIL[c.g];
int b = BitUtility.BITSCALE_8_TO_5_CEIL[c.b];
colorB = r << 10 | g << 5 | b;
colorBIsOpaque = 1;
} else {
int r = BitUtility.BITSCALE_8_TO_4_CEIL[c.r];
int g = BitUtility.BITSCALE_8_TO_4_CEIL[c.g];
int b = BitUtility.BITSCALE_8_TO_4_CEIL[c.b];
colorB = a << 12 | r << 8 | g << 4 | b;
colorBIsOpaque = 0;
}
}
PvrtcColorRgb getColorRgbA() {
if (colorAIsOpaque != 0) {
var r = colorA >> 9;
var g = colorA >> 4 & 0x1f;
var b = colorA & 0xf;
return new PvrtcColorRgb(BitUtility.BITSCALE_5_TO_8[r],
BitUtility.BITSCALE_5_TO_8[g], BitUtility.BITSCALE_4_TO_8[b]);
} else {
var r = (colorA >> 7) & 0xf;
var g = (colorA >> 3) & 0xf;
var b = colorA & 7;
return new PvrtcColorRgb(BitUtility.BITSCALE_4_TO_8[r],
BitUtility.BITSCALE_4_TO_8[g], BitUtility.BITSCALE_3_TO_8[b]);
}
}
PvrtcColorRgba getColorRgbaA() {
if (colorAIsOpaque != 0) {
var r = colorA >> 9;
var g = colorA >> 4 & 0x1f;
var b = colorA & 0xf;
return new PvrtcColorRgba(BitUtility.BITSCALE_5_TO_8[r],
BitUtility.BITSCALE_5_TO_8[g], BitUtility.BITSCALE_4_TO_8[b], 255);
} else {
var a = colorA >> 11 & 7;
var r = (colorA >> 7) & 0xf;
var g = (colorA >> 3) & 0xf;
var b = colorA & 7;
return new PvrtcColorRgba(
BitUtility.BITSCALE_4_TO_8[r],
BitUtility.BITSCALE_4_TO_8[g],
BitUtility.BITSCALE_3_TO_8[b],
BitUtility.BITSCALE_3_TO_8[a]);
}
}
PvrtcColorRgb getColorRgbB() {
if (colorBIsOpaque != 0) {
var r = colorB >> 10;
var g = colorB >> 5 & 0x1f;
var b = colorB & 0x1f;
return new PvrtcColorRgb(BitUtility.BITSCALE_5_TO_8[r],
BitUtility.BITSCALE_5_TO_8[g], BitUtility.BITSCALE_5_TO_8[b]);
} else {
var r = colorB >> 8 & 0xf;
var g = colorB >> 4 & 0xf;
var b = colorB & 0xf;
return new PvrtcColorRgb(BitUtility.BITSCALE_4_TO_8[r],
BitUtility.BITSCALE_4_TO_8[g], BitUtility.BITSCALE_4_TO_8[b]);
}
}
PvrtcColorRgba getColorRgbaB() {
if (colorBIsOpaque != 0) {
var r = colorB >> 10;
var g = colorB >> 5 & 0x1f;
var b = colorB & 0x1f;
return new PvrtcColorRgba(BitUtility.BITSCALE_5_TO_8[r],
BitUtility.BITSCALE_5_TO_8[g], BitUtility.BITSCALE_5_TO_8[b], 255);
} else {
var a = colorB >> 12 & 7;
var r = colorB >> 8 & 0xf;
var g = colorB >> 4 & 0xf;
var b = colorB & 0xf;
return new PvrtcColorRgba(
BitUtility.BITSCALE_4_TO_8[r],
BitUtility.BITSCALE_4_TO_8[g],
BitUtility.BITSCALE_4_TO_8[b],
BitUtility.BITSCALE_3_TO_8[a]);
}
}
int _usePunchthroughAlpha = 0;
int _colorA = 0;
int _colorAIsOpaque = 0;
int _colorB = 0;
int _colorBIsOpaque = 0;
int _getColorData() =>
((usePunchthroughAlpha & 1)) |
((colorA & BITS_14) << 1) |
((colorAIsOpaque & 1) << 15) |
((colorB & BITS_15) << 16) |
((colorBIsOpaque & 1) << 31);
void _update() {
int x = colorData;
usePunchthroughAlpha = x & 1;
colorA = (x >> 1) & BITS_14;
colorAIsOpaque = (x >> 15) & 1;
colorB = (x >> 16) & BITS_15;
colorBIsOpaque = (x >> 31) & 1;
}
static int _getMortonNumber(int x, int y) {
return MORTON_TABLE[x >> 8] << 17 |
MORTON_TABLE[y >> 8] << 16 |
MORTON_TABLE[x & 0xFF] << 1 |
MORTON_TABLE[y & 0xFF];
}
static const BITS_14 = (1 << 14) - 1;
static const BITS_15 = (1 << 15) - 1;
static const BILINEAR_FACTORS = const [
const [4, 4, 4, 4],
const [2, 6, 2, 6],
const [8, 0, 8, 0],
const [6, 2, 6, 2],
const [2, 2, 6, 6],
const [1, 3, 3, 9],
const [4, 0, 12, 0],
const [3, 1, 9, 3],
const [8, 8, 0, 0],
const [4, 12, 0, 0],
const [16, 0, 0, 0],
const [12, 4, 0, 0],
const [6, 6, 2, 2],
const [3, 9, 1, 3],
const [12, 0, 4, 0],
const [9, 3, 3, 1],
];
// Weights are { colorA, colorB, alphaA, alphaB }
static const WEIGHTS = const [
// Weights for Mode=0
const [8, 0, 8, 0],
const [5, 3, 5, 3],
const [3, 5, 3, 5],
const [0, 8, 0, 8],
// Weights for Mode=1
const [8, 0, 8, 0],
const [4, 4, 4, 4],
const [4, 4, 0, 0],
const [0, 8, 0, 8],
];
static const MORTON_TABLE = const [
0x0000,
0x0001,
0x0004,
0x0005,
0x0010,
0x0011,
0x0014,
0x0015,
0x0040,
0x0041,
0x0044,
0x0045,
0x0050,
0x0051,
0x0054,
0x0055,
0x0100,
0x0101,
0x0104,
0x0105,
0x0110,
0x0111,
0x0114,
0x0115,
0x0140,
0x0141,
0x0144,
0x0145,
0x0150,
0x0151,
0x0154,
0x0155,
0x0400,
0x0401,
0x0404,
0x0405,
0x0410,
0x0411,
0x0414,
0x0415,
0x0440,
0x0441,
0x0444,
0x0445,
0x0450,
0x0451,
0x0454,
0x0455,
0x0500,
0x0501,
0x0504,
0x0505,
0x0510,
0x0511,
0x0514,
0x0515,
0x0540,
0x0541,
0x0544,
0x0545,
0x0550,
0x0551,
0x0554,
0x0555,
0x1000,
0x1001,
0x1004,
0x1005,
0x1010,
0x1011,
0x1014,
0x1015,
0x1040,
0x1041,
0x1044,
0x1045,
0x1050,
0x1051,
0x1054,
0x1055,
0x1100,
0x1101,
0x1104,
0x1105,
0x1110,
0x1111,
0x1114,
0x1115,
0x1140,
0x1141,
0x1144,
0x1145,
0x1150,
0x1151,
0x1154,
0x1155,
0x1400,
0x1401,
0x1404,
0x1405,
0x1410,
0x1411,
0x1414,
0x1415,
0x1440,
0x1441,
0x1444,
0x1445,
0x1450,
0x1451,
0x1454,
0x1455,
0x1500,
0x1501,
0x1504,
0x1505,
0x1510,
0x1511,
0x1514,
0x1515,
0x1540,
0x1541,
0x1544,
0x1545,
0x1550,
0x1551,
0x1554,
0x1555,
0x4000,
0x4001,
0x4004,
0x4005,
0x4010,
0x4011,
0x4014,
0x4015,
0x4040,
0x4041,
0x4044,
0x4045,
0x4050,
0x4051,
0x4054,
0x4055,
0x4100,
0x4101,
0x4104,
0x4105,
0x4110,
0x4111,
0x4114,
0x4115,
0x4140,
0x4141,
0x4144,
0x4145,
0x4150,
0x4151,
0x4154,
0x4155,
0x4400,
0x4401,
0x4404,
0x4405,
0x4410,
0x4411,
0x4414,
0x4415,
0x4440,
0x4441,
0x4444,
0x4445,
0x4450,
0x4451,
0x4454,
0x4455,
0x4500,
0x4501,
0x4504,
0x4505,
0x4510,
0x4511,
0x4514,
0x4515,
0x4540,
0x4541,
0x4544,
0x4545,
0x4550,
0x4551,
0x4554,
0x4555,
0x5000,
0x5001,
0x5004,
0x5005,
0x5010,
0x5011,
0x5014,
0x5015,
0x5040,
0x5041,
0x5044,
0x5045,
0x5050,
0x5051,
0x5054,
0x5055,
0x5100,
0x5101,
0x5104,
0x5105,
0x5110,
0x5111,
0x5114,
0x5115,
0x5140,
0x5141,
0x5144,
0x5145,
0x5150,
0x5151,
0x5154,
0x5155,
0x5400,
0x5401,
0x5404,
0x5405,
0x5410,
0x5411,
0x5414,
0x5415,
0x5440,
0x5441,
0x5444,
0x5445,
0x5450,
0x5451,
0x5454,
0x5455,
0x5500,
0x5501,
0x5504,
0x5505,
0x5510,
0x5511,
0x5514,
0x5515,
0x5540,
0x5541,
0x5544,
0x5545,
0x5550,
0x5551,
0x5554,
0x5555
];
}