#let address_text(card) = { text(font: ("OCR-B", "Noto Emoji"), size: 8pt, card.address) } #let place_avatar(text_height, card) = { style(styles => { let text_offset = (text_height - measure(address_text(card), styles).height) / 2 place( top + left, dx: 0.1in, dy: calc.max(text_offset + 4pt - 0.15in, 0pt), image(card.avatar, width: 0.3in) ) }) } #let address_content(width, height, card) = { set par(leading: 0.5em) let text_height = if card.imb == "" { height } else { height - 1in/8 } place( top + left, dx: 0.5in, block( width: width - 0.5in, height: text_height, align( start + horizon, address_text(card) ) ) ) if card.imb != "" { place( top + left, dy: height - 1in/8, dx: 0.05in, block( width: 100%, height: 1in/8, align( top + left, text(font: "USPSIMBCompact", size: 12pt, card.imb) ) ) ) } if card.avatar != none { place_avatar(text_height, card) } } #let address_block(width, height, card) = { block( width: width, height: height, breakable: false, address_content(width, height, card) ) } #let postcard_content(width, height, content_fn, args, card) = { // Content block place( top + left, dx: 1in/8, dy: 1in/8, block( width: width - 2in - 7in/8, height: height - 0.25in, breakable: false, content_fn(card) ) ) // Stamp placement guide if(not args.no_nixowos) { place( top + right, dx: -0.25in, dy: 0.25in, image("nixowos.svg", width: 0.5in) ) } // Address block place( horizon + right, dx: -1in/8, address_block(2.5in, 1in, card) ) } #let postcard_block(width, height, content_fn, args, card) = { block( width: width, height: height, breakable: false, postcard_content(width, height, content_fn, args, card) ) } #let postcard_square(width, height, margin, content_fn, args, card) = { rect( width: width + margin * 2, height: height + margin * 2, inset: margin, postcard_block(width, height, content_fn, args, card) ) } #let get_content_fn(args) = { if args.no_content { _ => [] } else { import "cache/content/content.typ" content.content } } #let sticker_sheets(width, height, margin, args, cards) = { let content_fn = get_content_fn(args) for (idx, card) in cards.enumerate() { let row = calc.rem(idx + args.skip, 2) if idx != 0 and row == 0 { pagebreak() } place( top + left, dx: 50% - width / 2 - margin, dy: 25% - height / 2 - margin + 50% * row, postcard_square(width, height, margin, content_fn, args, card) ) } } // It would be nice to calculate this but the rounding makes no sense, // hardcode it. #let iso216_lengths = ( 1189mm, 841mm, 594mm, 420mm, 297mm, 210mm, 148mm, 105mm, 74mm, 52mm, 37mm, 26mm ) #let iso216_a_size(format) = { (iso216_lengths.at(format), iso216_lengths.at(format + 1)) } // Pack together smaller ISO 216 A-series cards to make a full-size card. // Useful to print on a large printer or plotter then use a paper cutter #let iso216_a_card_sheets(page_format, card_format, args, cards) = { let is_landscape = calc.even(card_format - page_format) let (num_rows, num_cols) = if is_landscape { let num = calc.pow(2, (card_format - page_format) / 2) (num, num) } else { let cols = calc.pow(2, (card_format - 1 - page_format) / 2) (cols * 2, cols) } let (page_long, page_short) = iso216_a_size(page_format) set page(margin: 0mm, width: page_short, height: page_long, flipped: is_landscape) let (card_long, card_short) = iso216_a_size(card_format) let content_fn = get_content_fn(args) for (idx, card) in cards.enumerate() { if idx != 0 and calc.rem(idx + args.skip, num_rows * num_cols) == 0 { pagebreak() } let offset_idx = idx + args.skip let col = calc.rem(offset_idx, num_cols) let row = calc.rem(calc.floor(offset_idx / num_cols), num_rows) place( top + left, dx: col * card_long, dy: row * card_short, postcard_block(card_long, card_short, content_fn, args, card) ) } }