#include #include "studio/geometry.h" #include "studio/pdf.h" #include "studio/random.h" #include "triangles.h" int postcard(void * const device, const int cards) { if (cards <= 0) return 0; const vector pagesize = landscape(a6); const vector margin = scalar(7.5 mm); const vector grid = {.x = 13.0, .y = 9.0}; const vector tile = divide(subtract(multiply(margin, scalar(2.0)), pagesize), grid); const vector squares = scalar(min(tile.x, tile.y)); const matrix layout = scale(squares, translate(divide(subtract(multiply(grid, squares), pagesize), scalar(2.0)), identity())); uint32_t triangles[(90 * 90) - 1] = {0}; static_assert(count(triangles) <= UINT32_MAX, ""); for (uint32_t number = 0; number < count(triangles); ++number) triangles[number] = number; assert(grid.x <= count(triangles) / grid.y); struct pdf pdf = startpdf( (struct pdf){.write = output, .device = device, .title = "triangles", .author = "David W. Speck"} ); const size_t resources = (pdf = dictionary(pdf, "/ProcSet [/PDF]")).object.number; for (unsigned card = 0; card < (unsigned)cards; ++card) { const struct pdf stream = (pdf = startpage(pdf, pagesize, resources)); for (unsigned column = 0; column <= grid.x; ++column) { pdf = generate(point(generate(point(pdf, transform((vector){.x = column, .y = 0}, layout)), "m "), transform((vector){.x = column, .y = grid.y}, layout)), "l\n" ); } for (unsigned row = 0; row <= grid.y; ++row) { pdf = generate(point(generate(point(pdf, transform((vector){.x = 0, .y = row}, layout)), "m "), transform((vector){.x = grid.x, .y = row}, layout)), "l\n" ); } pdf = generate(pdf, "0 w S\n"); for (unsigned column = 0; column < grid.x; ++column) { for (unsigned row = 0; row < grid.y; ++row) { const size_t cell = (column * grid.y) + row; const size_t pick = cell + any((count(triangles) - 1) - cell); const uint32_t picked = triangles[pick]; triangles[pick] = triangles[cell]; triangles[cell] = picked; const struct vertices object = triangle(shape(picked)); const matrix position = translate((vector){.x = column, .y = row}, layout); pdf = generate(generate(point(generate(point(generate(point(pdf, transform(object.A, position)), "m "), transform(object.B, position)), "l "), transform(object.C, position)), "l "), "h\n" ); } } pdf = endpage(generate(pdf, "1 j 1 M %0.2f w S\n", 0.4 mm), stream); } const size_t textresources = (pdf = dictionary(pdf, "/ProcSet [/PDF /text] /Font <<\n" " /Courier-Bold <<\n" " /Type /Font /Subtype /Type1 /Name /Courier-Bold /BaseFont /Courier-Bold /Encoding /MacRomanEncoding\n" " >> /Courier-BoldOblique <<\n" " /Type /Font /Subtype /Type1 /Name /Courier-BoldOblique /BaseFont /Courier-BoldOblique /Encoding /MacRomanEncoding\n" " >>\n" ">> " )).object.number; const struct pdf stream = (pdf = startpage(pdf, pagesize, textresources)); const double fontsize = 10; const double leading = fontsize * 1.2; pdf = generate(point(generate(pdf, "BT %0.2f TL ", leading), add((vector){.y = 5 * leading}, margin)), "Td\n" "/Courier-Bold %0.2f Tf (triangles) '\n" "/Courier-BoldOblique %0.2f Tf (dreiecke) '\n" "/Courier-Bold %0.2f Tf () '\n" "(David W. Speck, 2025) '\n" "(rndmao.org/dws) '\n" "ET\n", fontsize, fontsize, fontsize ); pdf = endpdf(endpage(pdf, stream)); return 1; }