diff options
| author | frosty <frostinator33@airmail.cc> | 2026-10-26 10:21:57 -0400 |
|---|---|---|
| committer | frosty <frostinator33@airmail.cc> | 2026-10-26 10:21:57 -0400 |
| commit | 74aecd8b0986d07b50b7ce310d64e645b8b54e38 (patch) | |
| tree | 560e6434f183eb54cd779936f3a4c9575146a066 /main/vapi/libqrencode.vapi | |
| parent | 3d7e90d401da02d430a87db0ec7e1db3a6f1a68f (diff) | |
| parent | 4436001bb361ad4f9e4e05819214ecf0ea77c063 (diff) | |
Merge 'upstream/master'
Diffstat (limited to 'main/vapi/libqrencode.vapi')
| -rw-r--r-- | main/vapi/libqrencode.vapi | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/main/vapi/libqrencode.vapi b/main/vapi/libqrencode.vapi new file mode 100644 index 00000000..360f74a5 --- /dev/null +++ b/main/vapi/libqrencode.vapi @@ -0,0 +1,81 @@ +[CCode (cheader_filename = "qrencode.h")] +namespace Qrencode { + + [CCode (cname = "QRecLevel", cprefix = "QR_ECLEVEL_")] + public enum ECLevel { + L, + M, + Q, + H + } + + [CCode (cname = "QRencodeMode", cprefix = "QR_MODE_")] + public enum EncodeMode { + NUL, + NUM, + AN, + [CCode (cname = "QR_MODE_8")] + EIGHT_BIT, + KANJI, + STRUCTURE, + ECI, + FNC1FIRST, + FNC1SECOND + } + + [CCode (cname = "QRcode", free_function = "QRcode_free", has_type_id = false)] + [Compact] + public class QRcode { + private int version; + private int width; + [CCode (array_length = false)] + private uint8[] data; + + [CCode (cname = "QRcode_encodeString")] + public QRcode (string str, int version = 0, ECLevel level = ECLevel.L, EncodeMode hint = EncodeMode.EIGHT_BIT, bool casesensitive = true); + + public Gdk.Paintable to_paintable(int module_size) { + GLib.assert(module_size > 0); + var dst_width = width*module_size; + var dst_data = new uint8[dst_width*dst_width*3]; + expand_and_upsample(data,width,width, dst_data,dst_width,dst_width); + return new Gdk.MemoryTexture(dst_width, dst_width, Gdk.MemoryFormat.R8G8B8, + new GLib.Bytes.take((owned) dst_data), dst_width*3); + + } + + /** Does 2D nearest-neighbor upsampling of an array of single-byte + * samples, while expanding the least significant bit of each sample + * to three 0-or-255 bytes. + */ + private void expand_and_upsample( + uint8[] src, uint src_w, uint src_h, + uint8[] dst, uint dst_w, uint dst_h) { + GLib.assert(dst_w % src_w == 0); + GLib.assert(dst_h % src_h == 0); + var scale_x = dst_w/src_w, + scale_y = dst_h/src_h; + /* Doing the iteration in the order of destination samples for + * improved cache-friendliness (dst is 48 times larger than src in + * the typical case of scaling by 4x4). + * The choice of multiple nested loops over a single one is for + * avoiding a ton of divisions by non-constants. + */ + for (uint src_y = 0; src_y < src_h; ++src_y) { + for (uint repeat_y = 0; repeat_y < scale_y; ++repeat_y) { + var dst_y = src_y*scale_y + repeat_y; + for (uint src_x = 0; src_x < src_w; ++src_x) { + uint8 value = (src[src_y*src_w + src_x] & 1)==1 ? 0:255; + for (uint repeat_x = 0; repeat_x < scale_x; ++repeat_x){ + var dst_x = src_x*scale_x + repeat_x; + var dst_idx = dst_y*dst_w + dst_x; + dst[dst_idx*3+0] = value; + dst[dst_idx*3+1] = value; + dst[dst_idx*3+2] = value; + } + } + } + } + } + } +} |
