// Generates the 2D barcode PDF417. Supports dimensioning auto-sizing, fixed // and variable sizes, automatic and manual error levels, raw codeword input, // codeword size optimization and bitmap inversion. // Author: Paulo Soares (psoares@consiste.pt) // Modifications by Alexander Tzyganenko // unit frxBarcodePDF417; interface {$I frx.inc} uses {$IFDEF FPC} LCLType, LMessages, LazHelper, LCLIntf, {$ELSE} Windows, Messages, {$ENDIF} SysUtils, Types, StrUtils, Classes, Graphics, Controls, Forms, Dialogs, frxBarcode2DBase, frxPrinter; type TInt = array of integer; PInt = ^TInt; const START_PATTERN = $1fea8; STOP_PATTERN = $3fa29; START_CODE_SIZE = 17; STOP_SIZE = 18; _MOD = 929; ALPHA = $10000; LOWER = $20000; MIXED = $40000; PUNCTUATION = $80000; ISBYTE = $100000; BYTESHIFT = 913; PL = 25; LL = 27; _AS = 27; ML = 28; AL = 28; PS = 29; PAL = 29; SPACE = 26; TEXT_MODE = 900; BYTE_MODE_6 = 924; BYTE_MODE = 901; NUMERIC_MODE = 902; ABSOLUTE_MAX_TEXT_SIZE = 5420; MAX_DATA_CODEWORDS = 926; MACRO_SEGMENT_ID = 928; MACRO_LAST_SEGMENT = 922; MIXED_SET = '0123456789&'#13#9',:#-.$/+%*=^'; PUNCTUATION_SET = ';<>@[\]_`~!'#13#9',:'#10'-.$/"|*()?{}'''; CLUSTERS : array[0..2,0..928] of integer = ( ( $1d5c0, $1eaf0, $1f57c, $1d4e0, $1ea78, $1f53e, $1a8c0, $1d470, $1a860, $15040, $1a830, $15020, $1adc0, $1d6f0, $1eb7c, $1ace0, $1d678, $1eb3e, $158c0, $1ac70, $15860, $15dc0, $1aef0, $1d77c, $15ce0, $1ae78, $1d73e, $15c70, $1ae3c, $15ef0, $1af7c, $15e78, $1af3e, $15f7c, $1f5fa, $1d2e0, $1e978, $1f4be, $1a4c0, $1d270, $1e93c, $1a460, $1d238, $14840, $1a430, $1d21c, $14820, $1a418, $14810, $1a6e0, $1d378, $1e9be, $14cc0, $1a670, $1d33c, $14c60, $1a638, $1d31e, $14c30, $1a61c, $14ee0, $1a778, $1d3be, $14e70, $1a73c, $14e38, $1a71e, $14f78, $1a7be, $14f3c, $14f1e, $1a2c0, $1d170, $1e8bc, $1a260, $1d138, $1e89e, $14440, $1a230, $1d11c, $14420, $1a218, $14410, $14408, $146c0, $1a370, $1d1bc, $14660, $1a338, $1d19e, $14630, $1a31c, $14618, $1460c, $14770, $1a3bc, $14738, $1a39e, $1471c, $147bc, $1a160, $1d0b8, $1e85e, $14240, $1a130, $1d09c, $14220, $1a118, $1d08e, $14210, $1a10c, $14208, $1a106, $14360, $1a1b8, $1d0de, $14330, $1a19c, $14318, $1a18e, $1430c, $14306, $1a1de, $1438e, $14140, $1a0b0, $1d05c, $14120, $1a098, $1d04e, $14110, $1a08c, $14108, $1a086, $14104, $141b0, $14198, $1418c, $140a0, $1d02e, $1a04c, $1a046, $14082, $1cae0, $1e578, $1f2be, $194c0, $1ca70, $1e53c, $19460, $1ca38, $1e51e, $12840, $19430, $12820, $196e0, $1cb78, $1e5be, $12cc0, $19670, $1cb3c, $12c60, $19638, $12c30, $12c18, $12ee0, $19778, $1cbbe, $12e70, $1973c, $12e38, $12e1c, $12f78, $197be, $12f3c, $12fbe, $1dac0, $1ed70, $1f6bc, $1da60, $1ed38, $1f69e, $1b440, $1da30, $1ed1c, $1b420, $1da18, $1ed0e, $1b410, $1da0c, $192c0, $1c970, $1e4bc, $1b6c0, $19260, $1c938, $1e49e, $1b660, $1db38, $1ed9e, $16c40, $12420, $19218, $1c90e, $16c20, $1b618, $16c10, $126c0, $19370, $1c9bc, $16ec0, $12660, $19338, $1c99e, $16e60, $1b738, $1db9e, $16e30, $12618, $16e18, $12770, $193bc, $16f70, $12738, $1939e, $16f38, $1b79e, $16f1c, $127bc, $16fbc, $1279e, $16f9e, $1d960, $1ecb8, $1f65e, $1b240, $1d930, $1ec9c, $1b220, $1d918, $1ec8e, $1b210, $1d90c, $1b208, $1b204, $19160, $1c8b8, $1e45e, $1b360, $19130, $1c89c, $16640, $12220, $1d99c, $1c88e, $16620, $12210, $1910c, $16610, $1b30c, $19106, $12204, $12360, $191b8, $1c8de, $16760, $12330, $1919c, $16730, $1b39c, $1918e, $16718, $1230c, $12306, $123b8, $191de, $167b8, $1239c, $1679c, $1238e, $1678e, $167de, $1b140, $1d8b0, $1ec5c, $1b120, $1d898, $1ec4e, $1b110, $1d88c, $1b108, $1d886, $1b104, $1b102, $12140, $190b0, $1c85c, $16340, $12120, $19098, $1c84e, $16320, $1b198, $1d8ce, $16310, $12108, $19086, $16308, $1b186, $16304, $121b0, $190dc, $163b0, $12198, $190ce, $16398, $1b1ce, $1638c, $12186, $16386, $163dc, $163ce, $1b0a0, $1d858, $1ec2e, $1b090, $1d84c, $1b088, $1d846, $1b084, $1b082, $120a0, $19058, $1c82e, $161a0, $12090, $1904c, $16190, $1b0cc, $19046, $16188, $12084, $16184, $12082, $120d8, $161d8, $161cc, $161c6, $1d82c, $1d826, $1b042, $1902c, $12048, $160c8, $160c4, $160c2, $18ac0, $1c570, $1e2bc, $18a60, $1c538, $11440, $18a30, $1c51c, $11420, $18a18, $11410, $11408, $116c0, $18b70, $1c5bc, $11660, $18b38, $1c59e, $11630, $18b1c, $11618, $1160c, $11770, $18bbc, $11738, $18b9e, $1171c, $117bc, $1179e, $1cd60, $1e6b8, $1f35e, $19a40, $1cd30, $1e69c, $19a20, $1cd18, $1e68e, $19a10, $1cd0c, $19a08, $1cd06, $18960, $1c4b8, $1e25e, $19b60, $18930, $1c49c, $13640, $11220, $1cd9c, $1c48e, $13620, $19b18, $1890c, $13610, $11208, $13608, $11360, $189b8, $1c4de, $13760, $11330, $1cdde, $13730, $19b9c, $1898e, $13718, $1130c, $1370c, $113b8, $189de, $137b8, $1139c, $1379c, $1138e, $113de, $137de, $1dd40, $1eeb0, $1f75c, $1dd20, $1ee98, $1f74e, $1dd10, $1ee8c, $1dd08, $1ee86, $1dd04, $19940, $1ccb0, $1e65c, $1bb40, $19920, $1eedc, $1e64e, $1bb20, $1dd98, $1eece, $1bb10, $19908, $1cc86, $1bb08, $1dd86, $19902, $11140, $188b0, $1c45c, $13340, $11120, $18898, $1c44e, $17740, $13320, $19998, $1ccce, $17720, $1bb98, $1ddce, $18886, $17710, $13308, $19986, $17708, $11102, $111b0, $188dc, $133b0, $11198, $188ce, $177b0, $13398, $199ce, $17798, $1bbce, $11186, $13386, $111dc, $133dc, $111ce, $177dc, $133ce, $1dca0, $1ee58, $1f72e, $1dc90, $1ee4c, $1dc88, $1ee46, $1dc84, $1dc82, $198a0, $1cc58, $1e62e, $1b9a0, $19890, $1ee6e, $1b990, $1dccc, $1cc46, $1b988, $19884, $1b984, $19882, $1b982, $110a0, $18858, $1c42e, $131a0, $11090, $1884c, $173a0, $13190, $198cc, $18846, $17390, $1b9cc, $11084, $17388, $13184, $11082, $13182, $110d8, $1886e, $131d8, $110cc, $173d8, $131cc, $110c6, $173cc, $131c6, $110ee, $173ee, $1dc50, $1ee2c, $1dc48, $1ee26, $1dc44, $1dc42, $19850, $1cc2c, $1b8d0, $19848, $1cc26, $1b8c8, $1dc66, $1b8c4, $19842, $1b8c2, $11050, $1882c, $130d0, $11048, $18826, $171d0, $130c8, $19866, $171c8, $1b8e6, $11042, $171c4, $130c2, $171c2, $130ec, $171ec, $171e6, $1ee16, $1dc22, $1cc16, $19824, $19822, $11028, $13068, $170e8, $11022, $13062, $18560, $10a40, $18530, $10a20, $18518, $1c28e, $10a10, $1850c, $10a08, $18506, $10b60, $185b8, $1c2de, $10b30, $1859c, $10b18, $1858e, $10b0c, $10b06, $10bb8, $185de, $10b9c, $10b8e, $10bde, $18d40, $1c6b0, $1e35c, $18d20, $1c698, $18d10, $1c68c, $18d08, $1c686, $18d04, $10940, $184b0, $1c25c, $11b40, $10920, $1c6dc, $1c24e, $11b20, $18d98, $1c6ce, $11b10, $10908, $18486, $11b08, $18d86, $10902, $109b0, $184dc, $11bb0, $10998, $184ce, $11b98, $18dce, $11b8c, $10986, $109dc, $11bdc, $109ce, $11bce, $1cea0, $1e758, $1f3ae, $1ce90, $1e74c, $1ce88, $1e746, $1ce84, $1ce82, $18ca0, $1c658, $19da0, $18c90, $1c64c, $19d90, $1cecc, $1c646, $19d88, $18c84, $19d84, $18c82, $19d82, $108a0, $18458, $119a0, $10890, $1c66e, $13ba0, $11990, $18ccc, $18446, $13b90, $19dcc, $10884, $13b88, $11984, $10882, $11982, $108d8, $1846e, $119d8, $108cc, $13bd8, $119cc, $108c6, $13bcc, $119c6, $108ee, $119ee, $13bee, $1ef50, $1f7ac, $1ef48, $1f7a6, $1ef44, $1ef42, $1ce50, $1e72c, $1ded0, $1ef6c, $1e726, $1dec8, $1ef66, $1dec4, $1ce42, $1dec2, $18c50, $1c62c, $19cd0, $18c48, $1c626, $1bdd0, $19cc8, $1ce66, $1bdc8, $1dee6, $18c42, $1bdc4, $19cc2, $1bdc2, $10850, $1842c, $118d0, $10848, $18426, $139d0, $118c8, $18c66, $17bd0, $139c8, $19ce6, $10842, $17bc8, $1bde6, $118c2, $17bc4, $1086c, $118ec, $10866, $139ec, $118e6, $17bec, $139e6, $17be6, $1ef28, $1f796, $1ef24, $1ef22, $1ce28, $1e716, $1de68, $1ef36, $1de64, $1ce22, $1de62, $18c28, $1c616, $19c68, $18c24, $1bce8, $19c64, $18c22, $1bce4, $19c62, $1bce2, $10828, $18416, $11868, $18c36, $138e8, $11864, $10822, $179e8, $138e4, $11862, $179e4, $138e2, $179e2, $11876, $179f6, $1ef12, $1de34, $1de32, $19c34, $1bc74, $1bc72, $11834, $13874, $178f4, $178f2, $10540, $10520, $18298, $10510, $10508, $10504, $105b0, $10598, $1058c, $10586, $105dc, $105ce, $186a0, $18690, $1c34c, $18688, $1c346, $18684, $18682, $104a0, $18258, $10da0, $186d8, $1824c, $10d90, $186cc, $10d88, $186c6, $10d84, $10482, $10d82, $104d8, $1826e, $10dd8, $186ee, $10dcc, $104c6, $10dc6, $104ee, $10dee, $1c750, $1c748, $1c744, $1c742, $18650, $18ed0, $1c76c, $1c326, $18ec8, $1c766, $18ec4, $18642, $18ec2, $10450, $10cd0, $10448, $18226, $11dd0, $10cc8, $10444, $11dc8, $10cc4, $10442, $11dc4, $10cc2, $1046c, $10cec, $10466, $11dec, $10ce6, $11de6, $1e7a8, $1e7a4, $1e7a2, $1c728, $1cf68, $1e7b6, $1cf64, $1c722, $1cf62, $18628, $1c316, $18e68, $1c736, $19ee8, $18e64, $18622, $19ee4, $18e62, $19ee2, $10428, $18216, $10c68, $18636, $11ce8, $10c64, $10422, $13de8, $11ce4, $10c62, $13de4, $11ce2, $10436, $10c76, $11cf6, $13df6, $1f7d4, $1f7d2, $1e794, $1efb4, $1e792, $1efb2, $1c714, $1cf34, $1c712, $1df74, $1cf32, $1df72, $18614, $18e34, $18612, $19e74, $18e32, $1bef4 ), ( $1f560, $1fab8, $1ea40, $1f530, $1fa9c, $1ea20, $1f518, $1fa8e, $1ea10, $1f50c, $1ea08, $1f506, $1ea04, $1eb60, $1f5b8, $1fade, $1d640, $1eb30, $1f59c, $1d620, $1eb18, $1f58e, $1d610, $1eb0c, $1d608, $1eb06, $1d604, $1d760, $1ebb8, $1f5de, $1ae40, $1d730, $1eb9c, $1ae20, $1d718, $1eb8e, $1ae10, $1d70c, $1ae08, $1d706, $1ae04, $1af60, $1d7b8, $1ebde, $15e40, $1af30, $1d79c, $15e20, $1af18, $1d78e, $15e10, $1af0c, $15e08, $1af06, $15f60, $1afb8, $1d7de, $15f30, $1af9c, $15f18, $1af8e, $15f0c, $15fb8, $1afde, $15f9c, $15f8e, $1e940, $1f4b0, $1fa5c, $1e920, $1f498, $1fa4e, $1e910, $1f48c, $1e908, $1f486, $1e904, $1e902, $1d340, $1e9b0, $1f4dc, $1d320, $1e998, $1f4ce, $1d310, $1e98c, $1d308, $1e986, $1d304, $1d302, $1a740, $1d3b0, $1e9dc, $1a720, $1d398, $1e9ce, $1a710, $1d38c, $1a708, $1d386, $1a704, $1a702, $14f40, $1a7b0, $1d3dc, $14f20, $1a798, $1d3ce, $14f10, $1a78c, $14f08, $1a786, $14f04, $14fb0, $1a7dc, $14f98, $1a7ce, $14f8c, $14f86, $14fdc, $14fce, $1e8a0, $1f458, $1fa2e, $1e890, $1f44c, $1e888, $1f446, $1e884, $1e882, $1d1a0, $1e8d8, $1f46e, $1d190, $1e8cc, $1d188, $1e8c6, $1d184, $1d182, $1a3a0, $1d1d8, $1e8ee, $1a390, $1d1cc, $1a388, $1d1c6, $1a384, $1a382, $147a0, $1a3d8, $1d1ee, $14790, $1a3cc, $14788, $1a3c6, $14784, $14782, $147d8, $1a3ee, $147cc, $147c6, $147ee, $1e850, $1f42c, $1e848, $1f426, $1e844, $1e842, $1d0d0, $1e86c, $1d0c8, $1e866, $1d0c4, $1d0c2, $1a1d0, $1d0ec, $1a1c8, $1d0e6, $1a1c4, $1a1c2, $143d0, $1a1ec, $143c8, $1a1e6, $143c4, $143c2, $143ec, $143e6, $1e828, $1f416, $1e824, $1e822, $1d068, $1e836, $1d064, $1d062, $1a0e8, $1d076, $1a0e4, $1a0e2, $141e8, $1a0f6, $141e4, $141e2, $1e814, $1e812, $1d034, $1d032, $1a074, $1a072, $1e540, $1f2b0, $1f95c, $1e520, $1f298, $1f94e, $1e510, $1f28c, $1e508, $1f286, $1e504, $1e502, $1cb40, $1e5b0, $1f2dc, $1cb20, $1e598, $1f2ce, $1cb10, $1e58c, $1cb08, $1e586, $1cb04, $1cb02, $19740, $1cbb0, $1e5dc, $19720, $1cb98, $1e5ce, $19710, $1cb8c, $19708, $1cb86, $19704, $19702, $12f40, $197b0, $1cbdc, $12f20, $19798, $1cbce, $12f10, $1978c, $12f08, $19786, $12f04, $12fb0, $197dc, $12f98, $197ce, $12f8c, $12f86, $12fdc, $12fce, $1f6a0, $1fb58, $16bf0, $1f690, $1fb4c, $169f8, $1f688, $1fb46, $168fc, $1f684, $1f682, $1e4a0, $1f258, $1f92e, $1eda0, $1e490, $1fb6e, $1ed90, $1f6cc, $1f246, $1ed88, $1e484, $1ed84, $1e482, $1ed82, $1c9a0, $1e4d8, $1f26e, $1dba0, $1c990, $1e4cc, $1db90, $1edcc, $1e4c6, $1db88, $1c984, $1db84, $1c982, $1db82, $193a0, $1c9d8, $1e4ee, $1b7a0, $19390, $1c9cc, $1b790, $1dbcc, $1c9c6, $1b788, $19384, $1b784, $19382, $1b782, $127a0, $193d8, $1c9ee, $16fa0, $12790, $193cc, $16f90, $1b7cc, $193c6, $16f88, $12784, $16f84, $12782, $127d8, $193ee, $16fd8, $127cc, $16fcc, $127c6, $16fc6, $127ee, $1f650, $1fb2c, $165f8, $1f648, $1fb26, $164fc, $1f644, $1647e, $1f642, $1e450, $1f22c, $1ecd0, $1e448, $1f226, $1ecc8, $1f666, $1ecc4, $1e442, $1ecc2, $1c8d0, $1e46c, $1d9d0, $1c8c8, $1e466, $1d9c8, $1ece6, $1d9c4, $1c8c2, $1d9c2, $191d0, $1c8ec, $1b3d0, $191c8, $1c8e6, $1b3c8, $1d9e6, $1b3c4, $191c2, $1b3c2, $123d0, $191ec, $167d0, $123c8, $191e6, $167c8, $1b3e6, $167c4, $123c2, $167c2, $123ec, $167ec, $123e6, $167e6, $1f628, $1fb16, $162fc, $1f624, $1627e, $1f622, $1e428, $1f216, $1ec68, $1f636, $1ec64, $1e422, $1ec62, $1c868, $1e436, $1d8e8, $1c864, $1d8e4, $1c862, $1d8e2, $190e8, $1c876, $1b1e8, $1d8f6, $1b1e4, $190e2, $1b1e2, $121e8, $190f6, $163e8, $121e4, $163e4, $121e2, $163e2, $121f6, $163f6, $1f614, $1617e, $1f612, $1e414, $1ec34, $1e412, $1ec32, $1c834, $1d874, $1c832, $1d872, $19074, $1b0f4, $19072, $1b0f2, $120f4, $161f4, $120f2, $161f2, $1f60a, $1e40a, $1ec1a, $1c81a, $1d83a, $1903a, $1b07a, $1e2a0, $1f158, $1f8ae, $1e290, $1f14c, $1e288, $1f146, $1e284, $1e282, $1c5a0, $1e2d8, $1f16e, $1c590, $1e2cc, $1c588, $1e2c6, $1c584, $1c582, $18ba0, $1c5d8, $1e2ee, $18b90, $1c5cc, $18b88, $1c5c6, $18b84, $18b82, $117a0, $18bd8, $1c5ee, $11790, $18bcc, $11788, $18bc6, $11784, $11782, $117d8, $18bee, $117cc, $117c6, $117ee, $1f350, $1f9ac, $135f8, $1f348, $1f9a6, $134fc, $1f344, $1347e, $1f342, $1e250, $1f12c, $1e6d0, $1e248, $1f126, $1e6c8, $1f366, $1e6c4, $1e242, $1e6c2, $1c4d0, $1e26c, $1cdd0, $1c4c8, $1e266, $1cdc8, $1e6e6, $1cdc4, $1c4c2, $1cdc2, $189d0, $1c4ec, $19bd0, $189c8, $1c4e6, $19bc8, $1cde6, $19bc4, $189c2, $19bc2, $113d0, $189ec, $137d0, $113c8, $189e6, $137c8, $19be6, $137c4, $113c2, $137c2, $113ec, $137ec, $113e6, $137e6, $1fba8, $175f0, $1bafc, $1fba4, $174f8, $1ba7e, $1fba2, $1747c, $1743e, $1f328, $1f996, $132fc, $1f768, $1fbb6, $176fc, $1327e, $1f764, $1f322, $1767e, $1f762, $1e228, $1f116, $1e668, $1e224, $1eee8, $1f776, $1e222, $1eee4, $1e662, $1eee2, $1c468, $1e236, $1cce8, $1c464, $1dde8, $1cce4, $1c462, $1dde4, $1cce2, $1dde2, $188e8, $1c476, $199e8, $188e4, $1bbe8, $199e4, $188e2, $1bbe4, $199e2, $1bbe2, $111e8, $188f6, $133e8, $111e4, $177e8, $133e4, $111e2, $177e4, $133e2, $177e2, $111f6, $133f6, $1fb94, $172f8, $1b97e, $1fb92, $1727c, $1723e, $1f314, $1317e, $1f734, $1f312, $1737e, $1f732, $1e214, $1e634, $1e212, $1ee74, $1e632, $1ee72, $1c434, $1cc74, $1c432, $1dcf4, $1cc72, $1dcf2, $18874, $198f4, $18872, $1b9f4, $198f2, $1b9f2, $110f4, $131f4, $110f2, $173f4, $131f2, $173f2, $1fb8a, $1717c, $1713e, $1f30a, $1f71a, $1e20a, $1e61a, $1ee3a, $1c41a, $1cc3a, $1dc7a, $1883a, $1987a, $1b8fa, $1107a, $130fa, $171fa, $170be, $1e150, $1f0ac, $1e148, $1f0a6, $1e144, $1e142, $1c2d0, $1e16c, $1c2c8, $1e166, $1c2c4, $1c2c2, $185d0, $1c2ec, $185c8, $1c2e6, $185c4, $185c2, $10bd0, $185ec, $10bc8, $185e6, $10bc4, $10bc2, $10bec, $10be6, $1f1a8, $1f8d6, $11afc, $1f1a4, $11a7e, $1f1a2, $1e128, $1f096, $1e368, $1e124, $1e364, $1e122, $1e362, $1c268, $1e136, $1c6e8, $1c264, $1c6e4, $1c262, $1c6e2, $184e8, $1c276, $18de8, $184e4, $18de4, $184e2, $18de2, $109e8, $184f6, $11be8, $109e4, $11be4, $109e2, $11be2, $109f6, $11bf6, $1f9d4, $13af8, $19d7e, $1f9d2, $13a7c, $13a3e, $1f194, $1197e, $1f3b4, $1f192, $13b7e, $1f3b2, $1e114, $1e334, $1e112, $1e774, $1e332, $1e772, $1c234, $1c674, $1c232, $1cef4, $1c672, $1cef2, $18474, $18cf4, $18472, $19df4, $18cf2, $19df2, $108f4, $119f4, $108f2, $13bf4, $119f2, $13bf2, $17af0, $1bd7c, $17a78, $1bd3e, $17a3c, $17a1e, $1f9ca, $1397c, $1fbda, $17b7c, $1393e, $17b3e, $1f18a, $1f39a, $1f7ba, $1e10a, $1e31a, $1e73a, $1ef7a, $1c21a, $1c63a, $1ce7a, $1defa, $1843a, $18c7a, $19cfa, $1bdfa, $1087a, $118fa, $139fa, $17978, $1bcbe, $1793c, $1791e, $138be, $179be, $178bc, $1789e, $1785e, $1e0a8, $1e0a4, $1e0a2, $1c168, $1e0b6, $1c164, $1c162, $182e8, $1c176, $182e4, $182e2, $105e8, $182f6, $105e4, $105e2, $105f6, $1f0d4, $10d7e, $1f0d2, $1e094, $1e1b4, $1e092, $1e1b2, $1c134, $1c374, $1c132, $1c372, $18274, $186f4, $18272, $186f2, $104f4, $10df4, $104f2, $10df2, $1f8ea, $11d7c, $11d3e, $1f0ca, $1f1da, $1e08a, $1e19a, $1e3ba, $1c11a, $1c33a, $1c77a, $1823a, $1867a, $18efa, $1047a, $10cfa, $11dfa, $13d78, $19ebe, $13d3c, $13d1e, $11cbe, $13dbe, $17d70, $1bebc, $17d38, $1be9e, $17d1c, $17d0e, $13cbc, $17dbc, $13c9e, $17d9e, $17cb8, $1be5e, $17c9c, $17c8e, $13c5e, $17cde, $17c5c, $17c4e, $17c2e, $1c0b4, $1c0b2, $18174, $18172, $102f4, $102f2, $1e0da, $1c09a, $1c1ba, $1813a, $1837a, $1027a, $106fa, $10ebe, $11ebc, $11e9e, $13eb8, $19f5e, $13e9c, $13e8e, $11e5e, $13ede, $17eb0, $1bf5c, $17e98, $1bf4e, $17e8c, $17e86, $13e5c, $17edc, $13e4e, $17ece, $17e58, $1bf2e, $17e4c, $17e46, $13e2e, $17e6e, $17e2c, $17e26, $10f5e, $11f5c, $11f4e, $13f58, $19fae, $13f4c, $13f46, $11f2e, $13f6e, $13f2c, $13f26 ), ( $1abe0, $1d5f8, $153c0, $1a9f0, $1d4fc, $151e0, $1a8f8, $1d47e, $150f0, $1a87c, $15078, $1fad0, $15be0, $1adf8, $1fac8, $159f0, $1acfc, $1fac4, $158f8, $1ac7e, $1fac2, $1587c, $1f5d0, $1faec, $15df8, $1f5c8, $1fae6, $15cfc, $1f5c4, $15c7e, $1f5c2, $1ebd0, $1f5ec, $1ebc8, $1f5e6, $1ebc4, $1ebc2, $1d7d0, $1ebec, $1d7c8, $1ebe6, $1d7c4, $1d7c2, $1afd0, $1d7ec, $1afc8, $1d7e6, $1afc4, $14bc0, $1a5f0, $1d2fc, $149e0, $1a4f8, $1d27e, $148f0, $1a47c, $14878, $1a43e, $1483c, $1fa68, $14df0, $1a6fc, $1fa64, $14cf8, $1a67e, $1fa62, $14c7c, $14c3e, $1f4e8, $1fa76, $14efc, $1f4e4, $14e7e, $1f4e2, $1e9e8, $1f4f6, $1e9e4, $1e9e2, $1d3e8, $1e9f6, $1d3e4, $1d3e2, $1a7e8, $1d3f6, $1a7e4, $1a7e2, $145e0, $1a2f8, $1d17e, $144f0, $1a27c, $14478, $1a23e, $1443c, $1441e, $1fa34, $146f8, $1a37e, $1fa32, $1467c, $1463e, $1f474, $1477e, $1f472, $1e8f4, $1e8f2, $1d1f4, $1d1f2, $1a3f4, $1a3f2, $142f0, $1a17c, $14278, $1a13e, $1423c, $1421e, $1fa1a, $1437c, $1433e, $1f43a, $1e87a, $1d0fa, $14178, $1a0be, $1413c, $1411e, $141be, $140bc, $1409e, $12bc0, $195f0, $1cafc, $129e0, $194f8, $1ca7e, $128f0, $1947c, $12878, $1943e, $1283c, $1f968, $12df0, $196fc, $1f964, $12cf8, $1967e, $1f962, $12c7c, $12c3e, $1f2e8, $1f976, $12efc, $1f2e4, $12e7e, $1f2e2, $1e5e8, $1f2f6, $1e5e4, $1e5e2, $1cbe8, $1e5f6, $1cbe4, $1cbe2, $197e8, $1cbf6, $197e4, $197e2, $1b5e0, $1daf8, $1ed7e, $169c0, $1b4f0, $1da7c, $168e0, $1b478, $1da3e, $16870, $1b43c, $16838, $1b41e, $1681c, $125e0, $192f8, $1c97e, $16de0, $124f0, $1927c, $16cf0, $1b67c, $1923e, $16c78, $1243c, $16c3c, $1241e, $16c1e, $1f934, $126f8, $1937e, $1fb74, $1f932, $16ef8, $1267c, $1fb72, $16e7c, $1263e, $16e3e, $1f274, $1277e, $1f6f4, $1f272, $16f7e, $1f6f2, $1e4f4, $1edf4, $1e4f2, $1edf2, $1c9f4, $1dbf4, $1c9f2, $1dbf2, $193f4, $193f2, $165c0, $1b2f0, $1d97c, $164e0, $1b278, $1d93e, $16470, $1b23c, $16438, $1b21e, $1641c, $1640e, $122f0, $1917c, $166f0, $12278, $1913e, $16678, $1b33e, $1663c, $1221e, $1661e, $1f91a, $1237c, $1fb3a, $1677c, $1233e, $1673e, $1f23a, $1f67a, $1e47a, $1ecfa, $1c8fa, $1d9fa, $191fa, $162e0, $1b178, $1d8be, $16270, $1b13c, $16238, $1b11e, $1621c, $1620e, $12178, $190be, $16378, $1213c, $1633c, $1211e, $1631e, $121be, $163be, $16170, $1b0bc, $16138, $1b09e, $1611c, $1610e, $120bc, $161bc, $1209e, $1619e, $160b8, $1b05e, $1609c, $1608e, $1205e, $160de, $1605c, $1604e, $115e0, $18af8, $1c57e, $114f0, $18a7c, $11478, $18a3e, $1143c, $1141e, $1f8b4, $116f8, $18b7e, $1f8b2, $1167c, $1163e, $1f174, $1177e, $1f172, $1e2f4, $1e2f2, $1c5f4, $1c5f2, $18bf4, $18bf2, $135c0, $19af0, $1cd7c, $134e0, $19a78, $1cd3e, $13470, $19a3c, $13438, $19a1e, $1341c, $1340e, $112f0, $1897c, $136f0, $11278, $1893e, $13678, $19b3e, $1363c, $1121e, $1361e, $1f89a, $1137c, $1f9ba, $1377c, $1133e, $1373e, $1f13a, $1f37a, $1e27a, $1e6fa, $1c4fa, $1cdfa, $189fa, $1bae0, $1dd78, $1eebe, $174c0, $1ba70, $1dd3c, $17460, $1ba38, $1dd1e, $17430, $1ba1c, $17418, $1ba0e, $1740c, $132e0, $19978, $1ccbe, $176e0, $13270, $1993c, $17670, $1bb3c, $1991e, $17638, $1321c, $1761c, $1320e, $1760e, $11178, $188be, $13378, $1113c, $17778, $1333c, $1111e, $1773c, $1331e, $1771e, $111be, $133be, $177be, $172c0, $1b970, $1dcbc, $17260, $1b938, $1dc9e, $17230, $1b91c, $17218, $1b90e, $1720c, $17206, $13170, $198bc, $17370, $13138, $1989e, $17338, $1b99e, $1731c, $1310e, $1730e, $110bc, $131bc, $1109e, $173bc, $1319e, $1739e, $17160, $1b8b8, $1dc5e, $17130, $1b89c, $17118, $1b88e, $1710c, $17106, $130b8, $1985e, $171b8, $1309c, $1719c, $1308e, $1718e, $1105e, $130de, $171de, $170b0, $1b85c, $17098, $1b84e, $1708c, $17086, $1305c, $170dc, $1304e, $170ce, $17058, $1b82e, $1704c, $17046, $1302e, $1706e, $1702c, $17026, $10af0, $1857c, $10a78, $1853e, $10a3c, $10a1e, $10b7c, $10b3e, $1f0ba, $1e17a, $1c2fa, $185fa, $11ae0, $18d78, $1c6be, $11a70, $18d3c, $11a38, $18d1e, $11a1c, $11a0e, $10978, $184be, $11b78, $1093c, $11b3c, $1091e, $11b1e, $109be, $11bbe, $13ac0, $19d70, $1cebc, $13a60, $19d38, $1ce9e, $13a30, $19d1c, $13a18, $19d0e, $13a0c, $13a06, $11970, $18cbc, $13b70, $11938, $18c9e, $13b38, $1191c, $13b1c, $1190e, $13b0e, $108bc, $119bc, $1089e, $13bbc, $1199e, $13b9e, $1bd60, $1deb8, $1ef5e, $17a40, $1bd30, $1de9c, $17a20, $1bd18, $1de8e, $17a10, $1bd0c, $17a08, $1bd06, $17a04, $13960, $19cb8, $1ce5e, $17b60, $13930, $19c9c, $17b30, $1bd9c, $19c8e, $17b18, $1390c, $17b0c, $13906, $17b06, $118b8, $18c5e, $139b8, $1189c, $17bb8, $1399c, $1188e, $17b9c, $1398e, $17b8e, $1085e, $118de, $139de, $17bde, $17940, $1bcb0, $1de5c, $17920, $1bc98, $1de4e, $17910, $1bc8c, $17908, $1bc86, $17904, $17902, $138b0, $19c5c, $179b0, $13898, $19c4e, $17998, $1bcce, $1798c, $13886, $17986, $1185c, $138dc, $1184e, $179dc, $138ce, $179ce, $178a0, $1bc58, $1de2e, $17890, $1bc4c, $17888, $1bc46, $17884, $17882, $13858, $19c2e, $178d8, $1384c, $178cc, $13846, $178c6, $1182e, $1386e, $178ee, $17850, $1bc2c, $17848, $1bc26, $17844, $17842, $1382c, $1786c, $13826, $17866, $17828, $1bc16, $17824, $17822, $13816, $17836, $10578, $182be, $1053c, $1051e, $105be, $10d70, $186bc, $10d38, $1869e, $10d1c, $10d0e, $104bc, $10dbc, $1049e, $10d9e, $11d60, $18eb8, $1c75e, $11d30, $18e9c, $11d18, $18e8e, $11d0c, $11d06, $10cb8, $1865e, $11db8, $10c9c, $11d9c, $10c8e, $11d8e, $1045e, $10cde, $11dde, $13d40, $19eb0, $1cf5c, $13d20, $19e98, $1cf4e, $13d10, $19e8c, $13d08, $19e86, $13d04, $13d02, $11cb0, $18e5c, $13db0, $11c98, $18e4e, $13d98, $19ece, $13d8c, $11c86, $13d86, $10c5c, $11cdc, $10c4e, $13ddc, $11cce, $13dce, $1bea0, $1df58, $1efae, $1be90, $1df4c, $1be88, $1df46, $1be84, $1be82, $13ca0, $19e58, $1cf2e, $17da0, $13c90, $19e4c, $17d90, $1becc, $19e46, $17d88, $13c84, $17d84, $13c82, $17d82, $11c58, $18e2e, $13cd8, $11c4c, $17dd8, $13ccc, $11c46, $17dcc, $13cc6, $17dc6, $10c2e, $11c6e, $13cee, $17dee, $1be50, $1df2c, $1be48, $1df26, $1be44, $1be42, $13c50, $19e2c, $17cd0, $13c48, $19e26, $17cc8, $1be66, $17cc4, $13c42, $17cc2, $11c2c, $13c6c, $11c26, $17cec, $13c66, $17ce6, $1be28, $1df16, $1be24, $1be22, $13c28, $19e16, $17c68, $13c24, $17c64, $13c22, $17c62, $11c16, $13c36, $17c76, $1be14, $1be12, $13c14, $17c34, $13c12, $17c32, $102bc, $1029e, $106b8, $1835e, $1069c, $1068e, $1025e, $106de, $10eb0, $1875c, $10e98, $1874e, $10e8c, $10e86, $1065c, $10edc, $1064e, $10ece, $11ea0, $18f58, $1c7ae, $11e90, $18f4c, $11e88, $18f46, $11e84, $11e82, $10e58, $1872e, $11ed8, $18f6e, $11ecc, $10e46, $11ec6, $1062e, $10e6e, $11eee, $19f50, $1cfac, $19f48, $1cfa6, $19f44, $19f42, $11e50, $18f2c, $13ed0, $19f6c, $18f26, $13ec8, $11e44, $13ec4, $11e42, $13ec2, $10e2c, $11e6c, $10e26, $13eec, $11e66, $13ee6, $1dfa8, $1efd6, $1dfa4, $1dfa2, $19f28, $1cf96, $1bf68, $19f24, $1bf64, $19f22, $1bf62, $11e28, $18f16, $13e68, $11e24, $17ee8, $13e64, $11e22, $17ee4, $13e62, $17ee2, $10e16, $11e36, $13e76, $17ef6, $1df94, $1df92, $19f14, $1bf34, $19f12, $1bf32, $11e14, $13e34, $11e12, $17e74, $13e32, $17e72, $1df8a, $19f0a, $1bf1a, $11e0a, $13e1a, $17e3a, $1035c, $1034e, $10758, $183ae, $1074c, $10746, $1032e, $1076e, $10f50, $187ac, $10f48, $187a6, $10f44, $10f42, $1072c, $10f6c, $10726, $10f66, $18fa8, $1c7d6, $18fa4, $18fa2, $10f28, $18796, $11f68, $18fb6, $11f64, $10f22, $11f62, $10716, $10f36, $11f76, $1cfd4, $1cfd2, $18f94, $19fb4, $18f92, $19fb2, $10f14, $11f34, $10f12, $13f74, $11f32, $13f72, $1cfca, $18f8a, $19f9a, $10f0a, $11f1a, $13f3a, $103ac, $103a6, $107a8, $183d6, $107a4, $107a2, $10396, $107b6, $187d4, $187d2, $10794, $10fb4, $10792, $10fb2, $1c7ea )); ERRLVL0 : array[0..1] of integer = ( 27, 917 ); ERRLVL1 : array[0..3] of integer = ( 522, 568, 723, 809 ); ERRLVL2 : array[0..7] of integer = ( 237, 308, 436, 284, 646, 653, 428, 379 ); ERRLVL3: array[0..15] of integer = ( 274, 562, 232, 755, 599, 524, 801, 132, 295, 116, 442, 428, 295, 42, 176, 65 ); ERRLVL4 : array[0..31] of integer = ( 361, 575, 922, 525, 176, 586, 640, 321, 536, 742, 677, 742, 687, 284, 193, 517, 273, 494, 263, 147, 593, 800, 571, 320, 803, 133, 231, 390, 685, 330, 63, 410 ); ERRLVL5 : array[0..63] of integer = ( 539, 422, 6, 93, 862, 771, 453, 106, 610, 287, 107, 505, 733, 877, 381, 612, 723, 476, 462, 172, 430, 609, 858, 822, 543, 376, 511, 400, 672, 762, 283, 184, 440, 35, 519, 31, 460, 594, 225, 535, 517, 352, 605, 158, 651, 201, 488, 502, 648, 733, 717, 83, 404, 97, 280, 771, 840, 629, 4, 381, 843, 623, 264, 543 ); ERRLVL6 : array[0..127] of integer = ( 521, 310, 864, 547, 858, 580, 296, 379, 53, 779, 897, 444, 400, 925, 749, 415, 822, 93, 217, 208, 928, 244, 583, 620, 246, 148, 447, 631, 292, 908, 490, 704, 516, 258, 457, 907, 594, 723, 674, 292, 272, 96, 684, 432, 686, 606, 860, 569, 193, 219, 129, 186, 236, 287, 192, 775, 278, 173, 40, 379, 712, 463, 646, 776, 171, 491, 297, 763, 156, 732, 95, 270, 447, 90, 507, 48, 228, 821, 808, 898, 784, 663, 627, 378, 382, 262, 380, 602, 754, 336, 89, 614, 87, 432, 670, 616, 157, 374, 242, 726, 600, 269, 375, 898, 845, 454, 354, 130, 814, 587, 804, 34, 211, 330, 539, 297, 827, 865, 37, 517, 834, 315, 550, 86, 801, 4, 108, 539 ); ERRLVL7 : array[0..255] of integer = ( 524, 894, 75, 766, 882, 857, 74, 204, 82, 586, 708, 250, 905, 786, 138, 720, 858, 194, 311, 913, 275, 190, 375, 850, 438, 733, 194, 280, 201, 280, 828, 757, 710, 814, 919, 89, 68, 569, 11, 204, 796, 605, 540, 913, 801, 700, 799, 137, 439, 418, 592, 668, 353, 859, 370, 694, 325, 240, 216, 257, 284, 549, 209, 884, 315, 70, 329, 793, 490, 274, 877, 162, 749, 812, 684, 461, 334, 376, 849, 521, 307, 291, 803, 712, 19, 358, 399, 908, 103, 511, 51, 8, 517, 225, 289, 470, 637, 731, 66, 255, 917, 269, 463, 830, 730, 433, 848, 585, 136, 538, 906, 90, 2, 290, 743, 199, 655, 903, 329, 49, 802, 580, 355, 588, 188, 462, 10, 134, 628, 320, 479, 130, 739, 71, 263, 318, 374, 601, 192, 605, 142, 673, 687, 234, 722, 384, 177, 752, 607, 640, 455, 193, 689, 707, 805, 641, 48, 60, 732, 621, 895, 544, 261, 852, 655, 309, 697, 755, 756, 60, 231, 773, 434, 421, 726, 528, 503, 118, 49, 795, 32, 144, 500, 238, 836, 394, 280, 566, 319, 9, 647, 550, 73, 914, 342, 126, 32, 681, 331, 792, 620, 60, 609, 441, 180, 791, 893, 754, 605, 383, 228, 749, 760, 213, 54, 297, 134, 54, 834, 299, 922, 191, 910, 532, 609, 829, 189, 20, 167, 29, 872, 449, 83, 402, 41, 656, 505, 579, 481, 173, 404, 251, 688, 95, 497, 555, 642, 543, 307, 159, 924, 558, 648, 55, 497, 10 ); ERRLVL8 : array[0..511] of integer = ( 352, 77, 373, 504, 35, 599, 428, 207, 409, 574, 118, 498, 285, 380, 350, 492, 197, 265, 920, 155, 914, 299, 229, 643, 294, 871, 306, 88, 87, 193, 352, 781, 846, 75, 327, 520, 435, 543, 203, 666, 249, 346, 781, 621, 640, 268, 794, 534, 539, 781, 408, 390, 644, 102, 476, 499, 290, 632, 545, 37, 858, 916, 552, 41, 542, 289, 122, 272, 383, 800, 485, 98, 752, 472, 761, 107, 784, 860, 658, 741, 290, 204, 681, 407, 855, 85, 99, 62, 482, 180, 20, 297, 451, 593, 913, 142, 808, 684, 287, 536, 561, 76, 653, 899, 729, 567, 744, 390, 513, 192, 516, 258, 240, 518, 794, 395, 768, 848, 51, 610, 384, 168, 190, 826, 328, 596, 786, 303, 570, 381, 415, 641, 156, 237, 151, 429, 531, 207, 676, 710, 89, 168, 304, 402, 40, 708, 575, 162, 864, 229, 65, 861, 841, 512, 164, 477, 221, 92, 358, 785, 288, 357, 850, 836, 827, 736, 707, 94, 8, 494, 114, 521, 2, 499, 851, 543, 152, 729, 771, 95, 248, 361, 578, 323, 856, 797, 289, 51, 684, 466, 533, 820, 669, 45, 902, 452, 167, 342, 244, 173, 35, 463, 651, 51, 699, 591, 452, 578, 37, 124, 298, 332, 552, 43, 427, 119, 662, 777, 475, 850, 764, 364, 578, 911, 283, 711, 472, 420, 245, 288, 594, 394, 511, 327, 589, 777, 699, 688, 43, 408, 842, 383, 721, 521, 560, 644, 714, 559, 62, 145, 873, 663, 713, 159, 672, 729, 624, 59, 193, 417, 158, 209, 563, 564, 343, 693, 109, 608, 563, 365, 181, 772, 677, 310, 248, 353, 708, 410, 579, 870, 617, 841, 632, 860, 289, 536, 35, 777, 618, 586, 424, 833, 77, 597, 346, 269, 757, 632, 695, 751, 331, 247, 184, 45, 787, 680, 18, 66, 407, 369, 54, 492, 228, 613, 830, 922, 437, 519, 644, 905, 789, 420, 305, 441, 207, 300, 892, 827, 141, 537, 381, 662, 513, 56, 252, 341, 242, 797, 838, 837, 720, 224, 307, 631, 61, 87, 560, 310, 756, 665, 397, 808, 851, 309, 473, 795, 378, 31, 647, 915, 459, 806, 590, 731, 425, 216, 548, 249, 321, 881, 699, 535, 673, 782, 210, 815, 905, 303, 843, 922, 281, 73, 469, 791, 660, 162, 498, 308, 155, 422, 907, 817, 187, 62, 16, 425, 535, 336, 286, 437, 375, 273, 610, 296, 183, 923, 116, 667, 751, 353, 62, 366, 691, 379, 687, 842, 37, 357, 720, 742, 330, 5, 39, 923, 311, 424, 242, 749, 321, 54, 669, 316, 342, 299, 534, 105, 667, 488, 640, 672, 576, 540, 316, 486, 721, 610, 46, 656, 447, 171, 616, 464, 190, 531, 297, 321, 762, 752, 533, 175, 134, 14, 381, 433, 717, 45, 111, 20, 596, 284, 736, 138, 646, 411, 877, 669, 141, 919, 45, 780, 407, 164, 332, 899, 165, 726, 600, 325, 498, 655, 357, 752, 768, 223, 849, 647, 63, 310, 863, 251, 366, 304, 282, 738, 675, 410, 389, 244, 31, 121, 303, 263 ); ERROR_LEVEL : array[0..8] of PInt = ( @ERRLVL0, @ERRLVL1, @ERRLVL2, @ERRLVL3, @ERRLVL4, @ERRLVL5, @ERRLVL6, @ERRLVL7, @ERRLVL8 ); type /// Specifies the error correction level used for PDF417 barcode. PDF417ErrorCorrection = ( AutoCorr, Level0, Level1, Level2, Level3, Level4, Level5, Level6, Level7, Level8 ); /// Specifies the compaction mode used for PDF417 barcode. PDF417CompactionMode = ( AutoCompaction, TextComp, Numeric, Binary ); Segment = class public _type : char; _start, _end : integer; constructor Create( _t : char; _s, _e : integer); end; TSegmentList = class(TObject) public List : TList; constructor Create; destructor Destroy; override; procedure Add(_type: char; _start,_end : integer); function Get(idx : integer) : Segment; procedure Remove( idx : integer); function Size : integer; end; /// /// Generates the 2D PDF417 barcode. /// /// This example shows how to configure the BarcodeObject to display PDF417 barcode. /// /// BarcodeObject barcode; /// ... /// barcode.Barcode = new BarcodePDF417(); /// (barcode.Barcode as BarcodePDF417).CompactionMode = PDF417CompactionMode.Text; /// /// TfrxBarcodePDF417 = class(TfrxBarcode2DBaseWithUnion) private codeColumns, FRows, FColumns : integer; codewords : array[0 .. MAX_DATA_CODEWORDS + 1] of integer; lenCodewords, errorLevel : integer; FErrorCorrection : PDF417ErrorCorrection; FCompactionMode : PDF417CompactionMode; bytes : array of byte; FAspectRatio : extended; FCodePage, bitPtr, cwPtr : integer; segmentList : TSegmentList; FImage: array of Byte; arrOB: T2DBooleanArray; function CheckSegmentType( var segm : Segment; typ : char) : boolean; function GetSegmentLength( var segm : Segment ) : integer; procedure OutCodeword17( codeword : integer); procedure OutCodeword18( codeword : integer); procedure OutCodeword( codeword : integer ); procedure OutStopPattern; procedure OutStartPattern; procedure OutPaintCode; procedure CalculateErrorCorrection(dest : integer); function GetTextTypeAndValue( var input : array of byte; maxLength, idx : integer ) : integer; overload; function GetTextTypeAndValue(maxLength, idx : integer) : integer; overload; procedure TextCompaction(var input : array of byte; start, length : integer); overload; procedure TextCompaction( start, length : integer); overload; //procedure BasicNumberCompaction( start, length : integer); overload; procedure BasicNumberCompaction(var input : array of byte; start, length : integer); overload; procedure NumberCompaction(var input : array of byte; start,length : integer); overload; procedure NumberCompaction( start, length : integer); overload; procedure ByteCompaction6( start : integer ); procedure ByteCompaction( start, length : integer); procedure BreakString; procedure Assemble; function MaxPossibleErrorLevel( remain: integer) : integer; function GetMaxSquare : integer; procedure PaintCode; procedure Initialize; procedure SetAspectRatio(v : extended); procedure SetColumns(v : integer); procedure SetRows(v : integer); procedure SetErrorCorrection(v : PDF417ErrorCorrection); procedure SetCodePage(v : integer); procedure SetCompactionMode(v : PDF417CompactionMode); protected procedure SetText(v : string); override; public constructor Create; override; destructor Destroy; override; procedure Assign( source : TfrxBarcode2DBase ); override; published /// Gets or sets the barcode aspect ratio. /// A ratio or 0.5 will make the barcode width twice as large as the height. property AspectRatio : extended read FAspectRatio write SetAspectRatio; /// Gets or sets the number of barcode data columns. /// To calculate the necessary number of columns and rows, set the /// and properties to 0. In this case, the property /// should be set to desired aspect ratio. property Columns : integer read FColumns write SetColumns; /// Gets or sets the number of barcode data rows. /// To calculate the necessary number of columns and rows, set the /// and properties to 0. In this case, the property /// should be set to desired aspect ratio. property Rows : integer read FRows write SetRows; /// Gets or sets the error level correction used for the barcode. // [DefaultValue(PDF417ErrorCorrection.Auto)] property ErrorCorrection : PDF417ErrorCorrection read FErrorCorrection write SetErrorCorrection; /// Gets or sets the code page used for text conversion. /// Use this property to encode non-ASCII characters. For example, set this /// property to 1251 to use Window CP1251. /// [DefaultValue(437)] property CodePage : integer read FCodePage write SetCodePage; /// Gets or sets the compaction mode. /// [DefaultValue(PDF417CompactionMode.Auto)] property CompactionMode : PDF417CompactionMode read FCompactionMode write SetCompactionMode; /// Gets or sets the size of the pixel. end; implementation uses frxUnicodeUtils; procedure TfrxBarcodePDF417.SetText(v : string); begin if( FText <> v) then begin FText := v; Initialize; end; end; procedure TfrxBarcodePDF417.SetAspectRatio(v : extended); begin if v <> FAspectRatio then begin FAspectRatio := v; Initialize; end; end; procedure TfrxBarcodePDF417.SetColumns(v : integer); begin if v <> FColumns then begin FColumns := v; Initialize; end; end; procedure TfrxBarcodePDF417.SetRows(v : integer); begin if v <> FRows then begin FRows := v; Initialize; end; end; procedure TfrxBarcodePDF417.SetErrorCorrection(v : PDF417ErrorCorrection); begin if v <> FErrorCorrection then begin FErrorCorrection := v; Initialize; end; end; procedure TfrxBarcodePDF417.SetCodePage(v : integer); begin if v <> FCodePage then begin FCodePage := v; Initialize; end; end; procedure TfrxBarcodePDF417.SetCompactionMode(v : PDF417CompactionMode); begin if v <> FCompactionMode then begin FCompactionMode := v; Initialize; end; end; procedure TfrxBarcodePDF417.Initialize; var i, k, j, p, b: Integer; s: AnsiString; {$IFNDEF DELPHI12} us: WideString; {$ENDIF} begin {$IFNDEF DELPHI12} us := WideString(text); if FCodePage = 65001 then s := UTF8Encode(us) else s := _UnicodeToAnsi(us, DEFAULT_CHARSET, FCodePage); {$ELSE} if FCodePage = 65001 then s := UTF8Encode(text) else s := _UnicodeToAnsi(text, DEFAULT_CHARSET, FCodePage); {$ENDIF} SetLength( bytes, Length(s)); for i := 1 to Length(s) do bytes[i - 1] := Ord(s[i]); codeColumns := FColumns; FHeight := FRows; fillChar(codeWords[0],(MAX_DATA_CODEWORDS + 1) * sizeof(integer),0); PaintCode(); //pnly PDF417 array of byte -> array of array of boolean SetLength(arrOB, FWidth, FHeight); for k := 0 to fwidth-1 do for j := 0 to fheight-1 do ArrOB[k][j] := False; for k := 0 to FHeight - 1 do begin p := k * ((FWidth + 7) div 8); for j := 0 to FWidth - 1 do begin b := FImage[p + (j div 8)] and $FF; b := b shl (j mod 8); if (b and $80) <> 0 then arrOB[j][k] := True; end; end; SetLength(FImage, 0); T2DBooleanArrayToVectorPrimitives(arrOB, FWidth, FHeight); end; /// Initializes a new instance of the class with default settings. constructor TfrxBarcodePDF417.Create; begin inherited; FImage := nil; SetLength( bytes, 0); Setlength(FImage, 0); FPixelwidth := 2; FPixelHeight := 8; FAspectRatio := 0.5; FCodePage := 437; Columns := 0; Rows := 0; FCompactionMode := AutoCompaction; Initialize; end; destructor TfrxBarcodePDF417.Destroy; begin SetLength(bytes, 0); SetLength(arrOB, 0, 0); inherited; end; procedure TfrxBarcodePDF417.Assign( source : TfrxBarcode2DBase ); var src : TfrxBarcodePDF417; begin inherited; if source is TfrxBarcodePDF417 then begin src := source as TfrxBarcodePDF417; AspectRatio := src.AspectRatio; Columns := src.Columns; Rows := src.Rows; CodePage := src.CodePage; CompactionMode := src.CompactionMode; ErrorCorrection := src.ErrorCorrection; end; end; //** Paints the barcode. If no exception was thrown a valid barcode is available. */ procedure TfrxBarcodePDF417.PaintCode; var maxErr, lenErr, tot, pad : integer; fixedColumn, skipRowColAdjust : boolean; c, b, yHeight : extended; begin ErrorText := ''; try try if (bytes = nil) then raise Exception.Create('Text cannot be null.'); if (Length(bytes) > ABSOLUTE_MAX_TEXT_SIZE) then raise Exception.Create('The text is too big.'); segmentList := TSegmentList.Create; BreakString; Assemble; except on e: Exception do ErrorText := e.Message; end; finally FreeAndNil(segmentList); end; codewords[0] := cwPtr; lenCodewords := cwPtr; // error correction level maxErr := MaxPossibleErrorLevel(MAX_DATA_CODEWORDS + 2 - lenCodewords); if (ErrorCorrection = AutoCorr ) then begin if (lenCodewords < 41) then errorLevel := 2 else if (lenCodewords < 161) then errorLevel := 3 else if (lenCodewords < 321) then errorLevel := 4 else errorLevel := 5; end else errorLevel := integer(ord(ErrorCorrection) - 1); if (errorLevel < 0) then errorLevel := 0 else if (errorLevel > maxErr) then errorLevel := maxErr; if (codeColumns < 1) then codeColumns := 1 else if (codeColumns > 30) then codeColumns := 30; if (FHeight < 3) then FHeight := 3 else if (FHeight > 90) then FHeight := 90; lenErr := 2 shl errorLevel; fixedColumn := FRows = 0; skipRowColAdjust := false; tot := lenCodewords + lenErr; if (FColumns <> 0) and (FRows <> 0) then begin tot := codeColumns * FHeight; if (tot > MAX_DATA_CODEWORDS + 2) then tot := GetMaxSquare; if (tot < lenCodewords + lenErr) then tot := lenCodewords + lenErr else skipRowColAdjust := true; end else begin fixedColumn := true; if (FAspectRatio < 0.001) then FAspectRatio := 0.001 else if (FAspectRatio > 1000) then FAspectRatio := 1000; if PixelWidth = 0 then yHeight := 3 else yHeight := PixelHeight / PixelWidth; b := 73 * FAspectRatio - 4; c := (-b + Sqrt(b * b + 4 * 17 * FAspectRatio * (lenCodewords + lenErr) * yHeight)) / (2 * 17 * FAspectRatio); codeColumns := trunc(c + 0.5); if (codeColumns < 1) then codeColumns := 1 else if (codeColumns > 30) then codeColumns := 30; end; if not skipRowColAdjust then begin if (fixedColumn) then begin FHeight := (tot - 1) div codeColumns + 1; if (FHeight < 3) then FHeight := 3 else if (FHeight > 90) then begin FHeight := 90; codeColumns := (tot - 1) div 90 + 1; end; end else begin codeColumns := (tot - 1) div FHeight + 1; if (codeColumns > 30) then begin codeColumns := 30; FHeight := (tot - 1) div 30 + 1; end; end; tot := FHeight * codeColumns; end; if (tot > MAX_DATA_CODEWORDS + 2) then tot := GetMaxSquare; errorLevel := MaxPossibleErrorLevel(tot - lenCodewords); lenErr := 2 shl errorLevel; pad := tot - lenErr - lenCodewords; cwPtr := lenCodewords; while (pad <> 0) do begin dec(pad); codewords[cwPtr] := TEXT_MODE; inc(cwPtr); end; codewords[0] := cwPtr; lenCodewords := cwPtr; CalculateErrorCorrection(lenCodewords); lenCodewords := tot; OutPaintCode; end; function TfrxBarcodePDF417.GetMaxSquare : integer; begin if (codeColumns > 21) then begin codeColumns := 29; FHeight := 32; end else begin codeColumns := 16; FHeight := 58; end; result := MAX_DATA_CODEWORDS + 2; end; function TfrxBarcodePDF417.MaxPossibleErrorLevel( remain: integer) : integer; var level, size : integer; begin level := 8; size := 512; while (level > 0) do begin if (remain >= size) then begin result := level; exit; end; dec(level); size := size shr 1; end; result := 0; end; procedure TfrxBarcodePDF417.Assemble; var k : integer; v : Segment; begin if segmentList.Size = 0 then exit; cwPtr := 1; for k := 0 to segmentList.Size-1 do begin v := segmentList.Get(k); case v._type of 'T': begin if (k <> 0) then begin codewords[cwPtr] := TEXT_MODE; inc(cwPtr); end; TextCompaction(v._start, GetSegmentLength(v)); end; 'N': begin codewords[cwPtr] := NUMERIC_MODE; inc(cwPtr); NumberCompaction(v._start, GetSegmentLength(v)); end; 'B': begin if (GetSegmentLength(v) mod 6) <> 0 then begin codewords[cwPtr] := BYTE_MODE; inc(cwPtr); end else begin codewords[cwPtr] := BYTE_MODE_6; inc(cwPtr); end; ByteCompaction(v._start, GetSegmentLength(v)); end; end; end; end; procedure TfrxBarcodePDF417.BreakString; var textLength, lastP, startN, nd, k, j : integer; c : char; lastTxt, txt, redo : boolean; v, vp, vn : Segment; begin textLength := Length(bytes); lastP := 0; startN := 0; nd := 0; case CompactionMode of TextComp: begin segmentList.Add('T', 0, textLength); exit; end; Numeric: begin segmentList.Add('N', 0, textLength); exit; end; Binary: begin segmentList.Add('B', 0, textLength); exit; end; end; for k := 0 to textLength-1 do begin c := char((bytes[k] and $ff)); if (c >= '0') and (c <= '9') then begin if (nd = 0) then startN := k; inc(nd); continue; end; if (nd >= 13) then begin if (lastP <> startN) then begin c := char((bytes[lastP] and $ff)); lastTxt := ((c >= ' ') and (c < #127)) or ( c = #13 ) or ( c = #10 ) or ( c = #9 ); for j := lastP to startN - 1 do begin c := char((bytes[j] and $ff)); txt := ((c >= ' ') and (c < #127)) or ( c = #13 ) or ( c = #10 ) or ( c = #9 ); if (txt <> lastTxt) then begin if lastTxt then segmentList.Add('T', lastP, j) else segmentList.Add('B', lastP, j); lastP := j; lastTxt := txt; end; end; if lastTxt then segmentList.Add('T', lastP, startN) else segmentList.Add('B', lastP, startN); end; segmentList.Add('N', startN, k); lastP := k; end; nd := 0; end; if (nd < 13) then startN := textLength; if (lastP <> startN) then begin c := char((bytes[lastP] and $ff)); lastTxt := ((c >= ' ') and (c < #127)) or (c = #10) or ( c = #13) or ( c = #9 ); for j := lastP to startN-1 do begin c := char((bytes[j] and $ff)); txt := ((c >= ' ') and (c < #127)) or ( c = #10 ) or ( c = #13 ) or ( c = #9 ); if (txt <> lastTxt) then begin if lastTxt then segmentList.Add('T', lastP, j) else segmentList.Add('B', lastP, j); lastP := j; lastTxt := txt; end; end; if lastTxt then segmentList.Add('T', lastP, startN) else segmentList.Add('B', lastP, startN); end; if (nd >= 13) then segmentList.Add('N', startN, textLength); //optimize //merge short binary k := 0; while k < segmentList.Size do begin v := segmentList.Get(k); vp := segmentList.Get(k - 1); vn := segmentList.Get(k + 1); if ( CheckSegmentType(v, 'B') and ( GetSegmentLength(v) = 1) ) then begin if CheckSegmentType(vp, 'T') and CheckSegmentType(vn, 'T') and (GetSegmentLength(vp) + GetSegmentLength(vn) >= 3) then begin vp._end := vn._end; segmentList.Remove(k); segmentList.Remove(k); k := -1; inc(k); continue; end; end; inc(k); end; //merge text sections k := 0; while k < segmentList.Size do begin v := segmentList.Get(k); vp := segmentList.Get(k - 1); vn := segmentList.Get(k + 1); if CheckSegmentType(v, 'T') and (GetSegmentLength(v) >= 5) then begin redo := false; if ( CheckSegmentType(vp, 'B') and (GetSegmentLength(vp) = 1)) or CheckSegmentType(vp, 'T') then begin redo := true; v._start := vp._start; segmentList.Remove(k - 1); dec(k); end; if ( CheckSegmentType(vn, 'B') and (GetSegmentLength(vn) = 1)) or CheckSegmentType(vn, 'T') then begin redo := true; v._end := vn._end; segmentList.Remove(k + 1); end; if (redo) then begin k := -1; inc(k); continue; end; end; inc(k); end; //merge binary sections k := 0; while k < segmentList.Size do begin v := segmentList.Get(k); vp := segmentList.Get(k - 1); vn := segmentList.Get(k + 1); if CheckSegmentType(v, 'B') then begin redo := false; if (CheckSegmentType(vp, 'T') and ( GetSegmentLength(vp) < 5 ) ) or CheckSegmentType(vp, 'B') then begin redo := true; v._start := vp._start; segmentList.Remove(k - 1); dec(k); end; if ( CheckSegmentType(vn, 'T') and (GetSegmentLength(vn) < 5)) or CheckSegmentType(vn, 'B') then begin redo := true; v._end := vn._end; segmentList.Remove(k + 1); end; if (redo) then begin k := -1; inc(k); continue; end; end; inc(k); end; // check if all numbers v := segmentList.Get(0); if (segmentList.Size = 1) and (v._type = 'T') and ( GetSegmentLength(v) >= 8 ) then begin for k := v._start to v._end-1 do begin c := char((bytes[k] and $ff)); if (c < '0') or ( c > '9') then break; end; if (k = v._end) then v._type := 'N'; end; end; procedure TfrxBarcodePDF417.ByteCompaction( start, length : integer); var k,j, size : integer; begin size := (length div 6) * 5 + (length mod 6); if (size + cwPtr ) > MAX_DATA_CODEWORDS then raise Exception.Create('The text is too big.'); inc(length,start); k := start; while k < length do begin size := length - k; if size>=44 then size:=6; if (size < 6) then begin for j := 0 to size-1 do begin codewords[cwPtr] := integer(bytes[k + j]) and $ff; inc(cwPtr); end; end else begin ByteCompaction6(k); end; inc(k, 6); end; end; procedure TfrxBarcodePDF417.ByteCompaction6( start : integer ); var length, ret, retLast, ni, k : integer; begin length := 6; ret := cwPtr; retLast := 4; inc(cwPtr, retLast + 1); for k := 0 to retLast do codewords[ret + k] := 0; inc( length, start ); for ni := start to length-1 do begin // multiply by 256 for k := retLast downto 0 do codewords[ret + k] := codewords[ret + k] * 256; // add the digit inc(codewords[ret + retLast], integer(bytes[ni]) and $ff); // propagate carry for k := retLast downto 1 do begin inc(codewords[ret + k - 1], codewords[ret + k] div 900); codewords[ret + k] := codewords[ret + k] mod 900; end; end; end; procedure TfrxBarcodePDF417.NumberCompaction( start, length : integer); begin NumberCompaction(bytes, start, length); end; procedure TfrxBarcodePDF417.NumberCompaction(var input : array of byte; start,length : integer); var full, size, k : integer; begin full := (length div 44) * 15; size := length mod 44; if (size = 0) then size := full else size := full + size div 3 + 1; if (size + cwPtr > MAX_DATA_CODEWORDS) then raise Exception.Create('The text is too big.'); inc(length, start); k := start; while( k < length ) do begin size := length - k; if size > 44 then size := 44; BasicNumberCompaction(input, k, size); inc(k ,44); end; end; procedure TfrxBarcodePDF417.BasicNumberCompaction(var input : array of byte; start, length : integer); var ret, retLast, ni, k : integer; begin ret := cwPtr; retLast := length div 3; inc(cwPtr, retLast + 1); for k := 0 to retLast do codewords[ret + k] := 0; codewords[ret + retLast] := 1; inc(length, start); for ni := start to length-1 do begin // multiply by 10 for k := retLast downto 0 do codewords[ret + k] := codewords[ret + k] * 10; // add the digit inc(codewords[ret + retLast], input[ni] - ord('0')); // propagate carry for k := retLast downto 1 do begin inc(codewords[ret + k - 1], codewords[ret + k] div 900); codewords[ret + k] := codewords[ret + k] mod 900; end; end; end; {procedure TfrxBarcodePDF417.BasicNumberCompaction( start, length : integer); begin BasicNumberCompaction(bytes, start, length); end;} procedure TfrxBarcodePDF417.TextCompaction( start, length : integer); begin TextCompaction(bytes, start, length); end; procedure TfrxBarcodePDF417.TextCompaction(var input : array of byte; start, length : integer); var dest : TInt; mode, ptr, fullBytes, v, k, size : integer; begin SetLength( dest, ABSOLUTE_MAX_TEXT_SIZE * 2 ); FillChar(dest[0], sizeof(dest), 0); mode := ALPHA; ptr := 0; fullBytes := 0; inc(length, start); k := start; while ( k < length) do begin v := GetTextTypeAndValue(input, length, k); if ((v and mode) <> 0) then begin dest[ptr] := v and $ff; inc(ptr); inc(k); continue; end; if ((v and ISBYTE) <> 0) then begin if ((ptr and 1) <> 0) then begin //add a padding word // dest[ptr] := PAL; if mode and PUNCTUATION <> 0 then dest[ptr] := PAL else dest[ptr] := PS; inc(ptr); if (mode and PUNCTUATION) <> 0 then mode := ALPHA; end; dest[ptr] := BYTESHIFT; inc(ptr); dest[ptr] := v and $ff; inc(ptr); inc(fullBytes, 2); inc(k); continue; end; case (mode) of ALPHA: if ((v and LOWER) <> 0) then begin dest[ptr] := LL; inc(ptr); dest[ptr] := v and $ff; inc(ptr); mode := LOWER; end else if ((v and MIXED) <> 0) then begin dest[ptr] := ML; inc(ptr); dest[ptr] := v and $ff; inc(ptr); mode := MIXED; end else if ((GetTextTypeAndValue(input, length, k + 1) and GetTextTypeAndValue(input, length, k + 2) and PUNCTUATION) <> 0) then begin dest[ptr] := ML; inc(ptr); dest[ptr] := PL; inc(ptr); dest[ptr] := v and $ff; inc(ptr); mode := PUNCTUATION; end else begin dest[ptr] := PS; inc(ptr); dest[ptr] := v and $ff; inc(ptr); end; LOWER: if ((v and ALPHA) <> 0) then begin if ((GetTextTypeAndValue(length, k + 1) and GetTextTypeAndValue(length, k + 2) and ALPHA) <> 0) then begin dest[ptr] := ML; inc(ptr); dest[ptr] := AL; inc(ptr); mode := ALPHA; end else begin dest[ptr] := _AS; inc(ptr); end; dest[ptr] := v and $ff; inc(ptr); end else if ((v and MIXED) <> 0) then begin dest[ptr] := ML; inc(ptr); dest[ptr] := v and $ff; inc(ptr); mode := MIXED; end else if ((GetTextTypeAndValue(input, length, k + 1) and GetTextTypeAndValue(input, length, k + 2) and PUNCTUATION) <> 0) then begin dest[ptr] := ML; inc(ptr); dest[ptr] := PL; inc(ptr); dest[ptr] := v and $ff; inc(ptr); mode := PUNCTUATION; end else begin dest[ptr] := PS; inc(ptr); dest[ptr] := v and $ff; inc(ptr); end; MIXED: if ((v and LOWER) <> 0) then begin dest[ptr] := LL; inc(ptr); dest[ptr] := v and $ff; inc(ptr); mode := LOWER; end else if ((v and ALPHA) <> 0) then begin dest[ptr] := AL; inc(ptr); dest[ptr] := v and $ff; inc(ptr); mode := ALPHA; end else if ((GetTextTypeAndValue(input, length, k + 1) and GetTextTypeAndValue(input, length, k + 2) and PUNCTUATION) <> 0) then begin dest[ptr] := PL; inc(ptr); dest[ptr] := v and $ff; inc(ptr); mode := PUNCTUATION; end else begin dest[ptr] := PS; inc(ptr); dest[ptr] := v and $ff; inc(ptr); end; PUNCTUATION: begin dest[ptr] := PAL; inc(ptr); mode := ALPHA; dec(k); end; end; // case inc(k); end; // for if ((ptr and 1) <> 0) then begin dest[ptr] := PS; inc(ptr); end; size := (ptr + fullBytes) div 2; if (size + cwPtr > MAX_DATA_CODEWORDS) then raise Exception.Create('The text is too big.'); length := ptr; ptr := 0; while (ptr < length) do begin v := dest[ptr]; inc(ptr); if (v >= 30) then begin codewords[cwPtr] := v; inc(cwPtr); codewords[cwPtr] := dest[ptr]; inc(cwPtr); inc(ptr); end else begin codewords[cwPtr] := v * 30 + dest[ptr]; inc(cwPtr); inc(ptr); end; end; SetLength(dest, 0); end; function TfrxBarcodePDF417.GetTextTypeAndValue(maxLength, idx : integer) : integer; begin result := GetTextTypeAndValue(bytes, maxLength, idx); end; function TfrxBarcodePDF417.GetTextTypeAndValue( var input : array of byte; maxLength, idx : integer ) : integer; var c : char; ms,ps : integer; begin if (idx >= maxLength) then begin result := 0; exit; end; c := char(input[idx] and $ff); if (c >= 'A') and (c <= 'Z') then begin result := (ALPHA + ord(c) - ord('A')); exit; end; if (c >= 'a') and (c <= 'z') then begin result := (LOWER + ord(c) - ord('a')); exit; end; if (c = ' ') then begin result := (ALPHA + LOWER + MIXED + SPACE); exit; end; ms := Pos(c,MIXED_SET) - 1; ps := Pos(c,PUNCTUATION_SET) - 1; if (ms < 0) and (ps < 0) then begin result := (ISBYTE + (ord(c) and $ff)); exit; end; if (ms = ps) then begin result := (MIXED + PUNCTUATION + ms); exit; end; if (ms >= 0) then begin result := (MIXED + ms); exit; end; result := (PUNCTUATION + ps); end; procedure TfrxBarcodePDF417.CalculateErrorCorrection( dest : integer); var A : TInt; ALength,e,k,t1,t2,t3, LastE : integer; begin if (errorLevel < 0) or ( errorLevel > 8) then errorLevel := 0; A := TInt(ERROR_LEVEL[errorLevel]); Alength := 2 shl errorLevel; for k := 0 to Alength-1 do codewords[dest + k] := 0; lastE := Alength - 1; for k := 0 to lenCodewords-1 do begin t1 := codewords[k] + codewords[dest]; for e := 0 to lastE do begin t2 := (t1 * A[lastE - e]) mod _MOD; t3 := _MOD - t2; if e = LastE then codewords[dest + e] := t3 mod _MOD else codewords[dest + e] := ((codewords[dest + e + 1]) + t3) mod _MOD; end; end; for k := 0 to Alength- 1 do codewords[dest + k] := (_MOD - codewords[dest + k]) mod _MOD; end; procedure TfrxBarcodePDF417.OutPaintCode; var codePtr, lenBits, rowMod, edge, column, row : integer; cluster : ^integer; begin codePtr := 0; FWidth := START_CODE_SIZE * (codeColumns + 3) + STOP_SIZE; lenBits := ((FWidth - 1) div 8 + 1) * FHeight; SetLength(FImage, lenBits); FillChar(FImage[0],length(FImage),0); for row := 0 to FHeight-1 do begin bitPtr := ((FWidth - 1) div 8 + 1) * 8 * row; rowMod := row mod 3; cluster := @CLUSTERS[rowMod]; OutStartPattern; case (rowMod) of 0: edge := 30 * (row div 3) + ((FHeight - 1) div 3); 1: edge := 30 * (row div 3) + errorLevel * 3 + ((FHeight - 1) mod 3); else edge := 30 * (row div 3) + codeColumns - 1; end; OutCodeword(TInt(cluster)[edge]); for column := 0 to codeColumns-1 do begin OutCodeword(TInt(cluster)[codewords[codePtr]]); inc(codePtr); end; case rowMod of 0: edge := 30 * (row div 3) + codeColumns - 1; 1: edge := 30 * (row div 3) + ((FHeight - 1) div 3); else edge := 30 * (row div 3) + errorLevel * 3 + ((FHeight - 1) mod 3); end; OutCodeword(TInt(cluster)[edge]); OutStopPattern; end; end; procedure TfrxBarcodePDF417.OutStartPattern; begin OutCodeword17(START_PATTERN); end; procedure TfrxBarcodePDF417.OutStopPattern; begin OutCodeword18(STOP_PATTERN); end; procedure TfrxBarcodePDF417.OutCodeword( codeword : integer ); begin OutCodeword17(codeword); end; procedure TfrxBarcodePDF417.OutCodeword18( codeword : integer); var bytePtr, bit : integer; begin bytePtr := bitPtr div 8; bit := bitPtr - bytePtr * 8; FImage[bytePtr] := FImage[bytePtr] or (byte((codeword shr (10 + bit)))); inc(bytePtr); FImage[bytePtr] := FImage[bytePtr] or (byte(codeword shr (2 + bit))); inc(bytePtr); codeword := codeword shl 8; FImage[bytePtr] := FImage[bytePtr] or (byte((codeword shr (2 + bit)))); if (bit = 7) then begin inc(bytePtr); FImage[bytePtr] := FImage[bytePtr] or $80; end; inc(bitPtr, 18); end; procedure TfrxBarcodePDF417.OutCodeword17( codeword : integer); var bytePtr, bit : integer; begin bytePtr := bitPtr div 8; bit := bitPtr - bytePtr * 8; FImage[bytePtr] := FImage[bytePtr] or ( byte((codeword shr (9 + bit)))); inc(bytePtr); FImage[bytePtr] := FImage[bytePtr] or ( byte((codeword shr (1 + bit)))); inc(bytePtr); codeword := codeword shl 8; FImage[bytePtr] := FImage[bytePtr] or ( byte((codeword shr (1 + bit)))); inc(bitPtr, 17); end; function TfrxBarcodePDF417.GetSegmentLength(var segm : Segment ) : integer; begin if (segm = nil) then result := 0 else result := segm._end - segm._start; end; function TfrxBarcodePDF417.CheckSegmentType(var segm : Segment; typ : char) : boolean; begin if (segm = nil) then result := false else result := segm._type = typ; end; constructor Segment.Create( _t : char; _s, _e : integer); begin _type := _t; _start := _s; _end := _e; end; constructor TSegmentList.Create; begin list := TList.Create; end; destructor TSegmentList.Destroy; var i: Integer; begin for i := 0 to list.Count - 1 do Segment(List[i]).Free; List.Free; end; procedure TSegmentList.Add(_type: char; _start,_end : integer); begin list.Add(Segment.Create(_type, _start, _end)); end; function TSegmentList.Get(idx : integer) : Segment; begin if (idx < 0) or (idx >= list.Count) then result := nil else result := list[idx]; end; procedure TSegmentList.Remove( idx : integer); begin if (idx < 0) or (idx >= list.Count) then exit; list.Delete(idx); end; function TSegmentList.Size : integer; begin result := list.count; end; end.