David PHAM-VAN

Add more color functions

... ... @@ -2,6 +2,7 @@
## 1.3.24
- Add more color functions
- Fix Pdf format
- Fix warning in tests
- Fix warning in example
... ...
... ... @@ -40,6 +40,65 @@ class PdfColor {
(int.parse(color.substring(6, 7), radix: 16) >> 24 & 0xff) / 255.0);
}
factory PdfColor.fromRYB(double red, double yellow, double blue,
[double alpha = 1.0]) {
assert(red >= 0 && red <= 1);
assert(yellow >= 0 && yellow <= 1);
assert(blue >= 0 && blue <= 1);
assert(alpha >= 0 && alpha <= 1);
const List<List<double>> magic = <List<double>>[
<double>[1, 1, 1],
<double>[1, 1, 0],
<double>[1, 0, 0],
<double>[1, 0.5, 0],
<double>[0.163, 0.373, 0.6],
<double>[0.0, 0.66, 0.2],
<double>[0.5, 0.0, 0.5],
<double>[0.2, 0.094, 0.0]
];
double cubicInt(double t, double A, double B) {
final double weight = t * t * (3 - 2 * t);
return A + weight * (B - A);
}
double getRed(double iR, double iY, double iB) {
final double x0 = cubicInt(iB, magic[0][0], magic[4][0]);
final double x1 = cubicInt(iB, magic[1][0], magic[5][0]);
final double x2 = cubicInt(iB, magic[2][0], magic[6][0]);
final double x3 = cubicInt(iB, magic[3][0], magic[7][0]);
final double y0 = cubicInt(iY, x0, x1);
final double y1 = cubicInt(iY, x2, x3);
return cubicInt(iR, y0, y1);
}
double getGreen(double iR, double iY, double iB) {
final double x0 = cubicInt(iB, magic[0][1], magic[4][1]);
final double x1 = cubicInt(iB, magic[1][1], magic[5][1]);
final double x2 = cubicInt(iB, magic[2][1], magic[6][1]);
final double x3 = cubicInt(iB, magic[3][1], magic[7][1]);
final double y0 = cubicInt(iY, x0, x1);
final double y1 = cubicInt(iY, x2, x3);
return cubicInt(iR, y0, y1);
}
double getBlue(double iR, double iY, double iB) {
final double x0 = cubicInt(iB, magic[0][2], magic[4][2]);
final double x1 = cubicInt(iB, magic[1][2], magic[5][2]);
final double x2 = cubicInt(iB, magic[2][2], magic[6][2]);
final double x3 = cubicInt(iB, magic[3][2], magic[7][2]);
final double y0 = cubicInt(iY, x0, x1);
final double y1 = cubicInt(iY, x2, x3);
return cubicInt(iR, y0, y1);
}
final double redValue = getRed(red, yellow, blue);
final double greenValue = getGreen(red, yellow, blue);
final double blueValue = getBlue(red, yellow, blue);
return PdfColor(redValue, greenValue, blueValue, alpha);
}
final double alpha;
final double red;
final double green;
... ...
... ... @@ -392,4 +392,13 @@ class PdfColors {
orangeAccent,
deepOrangeAccent,
];
static PdfColor getColor(int index) {
final double hue = index * 137.508;
final PdfColor color = PdfColorHsv(hue % 360, 1, 1);
if ((index / 3) % 2 == 0) {
return PdfColor.fromRYB(color.red, color.green, color.blue);
}
return color;
}
}
... ...
... ... @@ -15,6 +15,7 @@
*/
import 'dart:io';
import 'dart:math' as math;
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart';
... ... @@ -57,10 +58,125 @@ class Color extends StatelessWidget {
}
}
enum ColorSpace { rgb, ryb, cmy }
class ColorWheel extends Widget {
ColorWheel({
this.colorSpace = ColorSpace.rgb,
this.divisions = 12,
this.rings = 5,
this.brightness = .5,
}) : assert(brightness >= 0 && brightness <= 1);
final int divisions;
final int rings;
final double brightness;
final ColorSpace colorSpace;
@override
void layout(Context context, BoxConstraints constraints,
{bool parentUsesSize = false}) {
box = PdfRect.fromPoints(PdfPoint.zero, constraints.biggest);
}
void drawFilledArc(Context context, double centerX, double centerY,
double angleStart, double angleEnd, double radius1, double radius2) {
assert(radius1 > radius2);
final PdfPoint startTop = PdfPoint(
box.x + centerX + math.cos(angleStart) * radius1,
box.y + centerY + math.sin(angleStart) * radius1,
);
final PdfPoint endTop = PdfPoint(
box.x + centerX + math.cos(angleEnd) * radius1,
box.y + centerY + math.sin(angleEnd) * radius1,
);
final PdfPoint startBottom = PdfPoint(
box.x + centerX + math.cos(angleStart) * radius2,
box.y + centerY + math.sin(angleStart) * radius2,
);
final PdfPoint endBottom = PdfPoint(
box.x + centerX + math.cos(angleEnd) * radius2,
box.y + centerY + math.sin(angleEnd) * radius2,
);
context.canvas
..moveTo(startTop.x, startTop.y)
..bezierArc(startTop.x, startTop.y, radius1, radius1, endTop.x, endTop.y,
large: false, sweep: true)
..lineTo(endBottom.x, endBottom.y)
..bezierArc(endBottom.x, endBottom.y, radius2, radius2, startBottom.x,
startBottom.y, large: false)
..lineTo(startTop.x, startTop.y)
..fillPath()
..moveTo(startTop.x, startTop.y)
..bezierArc(startTop.x, startTop.y, radius1, radius1, endTop.x, endTop.y,
large: false, sweep: true)
..lineTo(endBottom.x, endBottom.y)
..bezierArc(endBottom.x, endBottom.y, radius2, radius2, startBottom.x,
startBottom.y,
large: false)
..lineTo(startTop.x, startTop.y)
..strokePath();
}
@override
void paint(Context context) {
super.paint(context);
final double centerX = box.width / 2;
final double centerY = box.height / 2;
final double step = math.pi * 2 / divisions;
final double angleStart = math.pi / 2 - step;
final double ringStep = math.min(centerX, centerY) / rings;
context.canvas.setStrokeColor(PdfColors.black);
for (int ring = 0; ring <= rings; ring++) {
final double radius1 = ringStep * ring;
final double radius2 = ringStep * (ring - 1);
for (double angle = 0; angle < math.pi * 2; angle += step) {
final PdfColor ic =
PdfColorHsl(angle / math.pi * 180, ring / rings, brightness);
switch (colorSpace) {
case ColorSpace.rgb:
context.canvas.setFillColor(ic);
break;
case ColorSpace.ryb:
context.canvas
.setFillColor(PdfColor.fromRYB(ic.red, ic.green, ic.blue));
break;
case ColorSpace.cmy:
context.canvas
.setFillColor(PdfColorCmyk(ic.red, ic.green, ic.blue, 0));
break;
}
drawFilledArc(
context,
centerX,
centerY,
angleStart + angle,
angleStart + angle + step,
radius1,
radius2,
);
}
}
}
}
Document pdf;
void main() {
test('Pdf Colors', () {
final Document pdf = Document(title: 'Material Colors');
setUpAll(() {
Document.debug = true;
pdf = Document();
});
test('Pdf Colors', () {
pdf.addPage(MultiPage(
pageFormat: PdfPageFormat.standard,
build: (Context context) => <Widget>[
... ... @@ -546,7 +662,52 @@ void main() {
Color(PdfColors.black, 'Black'),
]),
]));
});
test('Pdf Colors Wheel', () {
const Map<ColorSpace, String> wheels = <ColorSpace, String>{
ColorSpace.rgb: 'Red Green Blue',
ColorSpace.ryb: 'Red Yellow Blue',
ColorSpace.cmy: 'Cyan Magenta Yellow',
};
wheels.forEach((ColorSpace colorSpace, String name) {
pdf.addPage(Page(
build: (Context context) => Column(
children: <Widget>[
Header(text: name),
SizedBox(
height: context.page.pageFormat.availableWidth,
child: ColorWheel(
colorSpace: colorSpace,
),
),
],
)));
});
});
test('Pdf Colors Generator', () {
const double widthCount = 26;
const PdfPageFormat format = PdfPageFormat(400, 400);
final double w = (format.width - 1) / widthCount;
final int count = widthCount * (format.height - 1) ~/ w;
pdf.addPage(MultiPage(
pageFormat: format,
build: (Context context) => <Widget>[
Wrap(
children: List<Widget>.generate(count, (int i) {
return Container(
width: w,
height: w,
color: PdfColors.getColor(i),
);
})),
]));
});
tearDownAll(() {
final File file = File('colors.pdf');
file.writeAsBytesSync(pdf.save());
});
... ...